Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 1dcd9434 authored by Marten Gajda's avatar Marten Gajda Committed by GitHub
Browse files

Send out PROVIDER_CHANGED broadcasts again, fixes #822 (#825)

Since Android 8 it's not possible to listen to implicit broadcasts anymore when the reciever is declared in the AndroidManifest.xml.
In a previous commit we disabled sending out broadcasts to other apps. This caused some trouble.
For new we hard code 3rd party receiver package names in a resource array. This is supposed to be changed later on, see #824.
parent e711e6ea
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
def jems_version = '1.23'
def jems_version = '1.24'
def contentpal_version = '0.5'
def androidx_test_runner_version = '1.1.1'

+1 −8
Original line number Diff line number Diff line
@@ -1317,15 +1317,8 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou
        super.onEndTransaction(callerIsSyncAdapter);
        if (mChanged.compareAndSet(true, false))
        {
            Intent providerChangedIntent = new Intent(Intent.ACTION_PROVIDER_CHANGED, TaskContract.getContentUri(mAuthority));
            updateNotifications();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
            {
                // for now we only notify our own package
                // we'll have to figure out how to do this correctly on Android 8+, e.g. how is it done by CalendarProvider and ContactsProvider
                providerChangedIntent.setPackage(getContext().getPackageName());
            }
            getContext().sendBroadcast(providerChangedIntent);
            Utils.sendActionProviderChangedBroadCast(getContext(), mAuthority);
        }

        if (Boolean.TRUE.equals(mStaleListCreated.get()))
+19 −2
Original line number Diff line number Diff line
@@ -23,7 +23,13 @@ import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import org.dmfs.iterables.SingletonIterable;
import org.dmfs.jems.iterable.composite.Joined;
import org.dmfs.jems.iterable.decorators.Mapped;
import org.dmfs.jems.procedure.composite.Batch;
import org.dmfs.provider.tasks.TaskDatabaseHelper.Tables;
import org.dmfs.provider.tasks.utils.ResourceArray;
import org.dmfs.provider.tasks.utils.With;
import org.dmfs.tasks.contract.TaskContract;
import org.dmfs.tasks.contract.TaskContract.Instances;
import org.dmfs.tasks.contract.TaskContract.SyncState;
@@ -31,6 +37,7 @@ import org.dmfs.tasks.contract.TaskContract.TaskListColumns;
import org.dmfs.tasks.contract.TaskContract.TaskListSyncColumns;
import org.dmfs.tasks.contract.TaskContract.TaskLists;
import org.dmfs.tasks.contract.TaskContract.Tasks;
import org.dmfs.tasks.provider.R;

import java.util.ArrayList;
import java.util.Arrays;
@@ -49,8 +56,18 @@ public class Utils
    {
        // TODO: Using the TaskContract content uri results in a "Unknown URI content" error message. Using the Tasks content uri instead will break the
        // broadcast receiver. We have to find away around this
        Intent providerChangedIntent = new Intent(Intent.ACTION_PROVIDER_CHANGED, TaskContract.getContentUri(authority));
        context.sendBroadcast(providerChangedIntent);
        // TODO: coalesce fast consecutive broadcasts, a delay of up to 1 second should be acceptable

        new With<>(new Intent(Intent.ACTION_PROVIDER_CHANGED, TaskContract.getContentUri(authority)))
                .process(providerChangedIntent ->
                        new Batch<Intent>(context::sendBroadcast)
                                .process(new Mapped<>(
                                        packageName -> new Intent(providerChangedIntent).setPackage(packageName),
                                        // TODO: fow now we hard code 3rd party package names, this should be replaced by some sort or registry
                                        // see https://github.com/dmfs/opentasks/issues/824
                                        new Joined<>(
                                                new SingletonIterable<>(context.getPackageName()),
                                                new ResourceArray(context, R.array.opentasks_provider_changed_receivers)))));
    }


+49 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 dmfs GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.dmfs.provider.tasks.utils;

import android.content.Context;

import org.dmfs.iterators.elementary.Seq;

import java.util.Iterator;


/**
 * An {@link Iterable} of a string array resource.
 *
 * @author Marten Gajda
 */
public final class ResourceArray implements Iterable<String>
{
    private final Context mContext;
    private final int mResource;


    public ResourceArray(Context context, int resource)
    {
        mContext = context;
        mResource = resource;
    }


    @Override
    public Iterator<String> iterator()
    {
        return new Seq<>(mContext.getResources().getStringArray(mResource));
    }
}
+53 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 dmfs GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.dmfs.provider.tasks.utils;

import org.dmfs.jems.procedure.Procedure;
import org.dmfs.jems.single.Single;


/**
 * Experiemental Procedure which calls another procedure with a given value.
 * <p>
 * TODO move to jems if this works out well
 *
 * @author Marten Gajda
 */
@Deprecated
public final class With<T> implements Procedure<Procedure<T>>
{
    private final Single<T> mValue;


    public With(T value)
    {
        this(() -> value);
    }


    public With(Single<T> value)
    {
        mValue = value;
    }


    @Override
    public void process(Procedure<T> delegate)
    {
        delegate.process(mValue.value());
    }
}
Loading