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

Commit 9bf85c80 authored by Marten Gajda's avatar Marten Gajda
Browse files

Refactor Notifications, implements #780

* Introduce composable TaskAction handlers
* Implement TaskActions required for feature parity with the old service
* Clean up old notification services
parent ee559389
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -153,8 +153,10 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou

    /**
     * Boolean to track if there are changes within a transaction.
     * <p>
     * This can be shared by multiple threads, hence the {@link AtomicReference}.
     */
    private boolean mChanged = false;
    private AtomicReference<Boolean> mChanged = new AtomicReference<>(false);

    /**
     * This is a per transaction/thread flag which indicates whether new lists with an unknown account have been added.
@@ -762,7 +764,7 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou
                        final ListAdapter list = new CursorContentValuesListAdapter(ListAdapter._ID.getFrom(cursor), cursor, new ContentValues());

                        mListProcessorChain.delete(db, list, isSyncAdapter);
                        mChanged = true;
                        mChanged.set(true);
                        count++;
                    }
                }
@@ -804,7 +806,7 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou

                        mTaskProcessorChain.delete(db, task, isSyncAdapter);

                        mChanged = true;
                        mChanged.set(true);
                        count++;
                    }
                }
@@ -923,7 +925,7 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou
                list.set(ListAdapter.ACCOUNT_TYPE, accountType);

                mListProcessorChain.insert(db, list, isSyncAdapter);
                mChanged = true;
                mChanged.set(true);

                rowId = list.id();
                result_uri = TaskContract.TaskLists.getContentUri(mAuthority);
@@ -943,7 +945,7 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou

                mTaskProcessorChain.insert(db, task, isSyncAdapter);

                mChanged = true;
                mChanged.set(true);

                rowId = task.id();
                result_uri = TaskContract.Tasks.getContentUri(mAuthority);
@@ -1070,7 +1072,7 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou
                        final ListAdapter list = new CursorContentValuesListAdapter(listId, cursor, cursor.getCount() > 1 ? new ContentValues(values) : values);

                        mListProcessorChain.update(db, list, isSyncAdapter);
                        mChanged = true;
                        mChanged.set(true);
                        count++;
                    }
                }
@@ -1100,7 +1102,7 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou
                        mTaskProcessorChain.update(db, task, isSyncAdapter);
                        if (dataChanged && task.hasUpdates())
                        {
                            mChanged = true;
                            mChanged.set(true);
                        }
                        count++;
                    }
@@ -1313,7 +1315,7 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou
    protected void onEndTransaction(boolean callerIsSyncAdapter)
    {
        super.onEndTransaction(callerIsSyncAdapter);
        if (mChanged)
        if (mChanged.compareAndSet(true, false))
        {
            Intent providerChangedIntent = new Intent(Intent.ACTION_PROVIDER_CHANGED, TaskContract.getContentUri(mAuthority));
            updateNotifications();
@@ -1324,7 +1326,6 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou
                providerChangedIntent.setPackage(getContext().getPackageName());
            }
            getContext().sendBroadcast(providerChangedIntent);
            mChanged = false;
        }

        if (Boolean.TRUE.equals(mStaleListCreated.get()))
+74 −87
Original line number Diff line number Diff line
@@ -2,7 +2,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        package="org.dmfs.tasks">
    <!-- TODO Remove after https://github.com/dmfs/opentasks/issues/392 -->
    <uses-sdk tools:overrideLibrary="org.dmfs.android.bolts"/>

    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="org.dmfs.permission.READ_TASKS"/>
    <uses-permission android:name="org.dmfs.permission.WRITE_TASKS"/>
    <uses-permission
@@ -14,21 +17,18 @@
    <uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

    <!--TODO Remove after https://github.com/dmfs/opentasks/issues/392-->
    <uses-sdk tools:overrideLibrary="org.dmfs.android.bolts"/>

    <application
            android:name=".TasksApplication"
            android:icon="@mipmap/ic_launcher"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:label="@string/app_name"
            android:name=".TasksApplication"
            android:taskAffinity="org.dmfs.tasks.TaskListActivity"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="false"
            android:taskAffinity="org.dmfs.tasks.TaskListActivity"
            android:theme="@style/OpenTasksAppTheme">

        <!-- TaskListActivity listens for MAIN intents -->
        <activity
                android:name="org.dmfs.tasks.TaskListActivity"
                android:name=".TaskListActivity"
                android:label="@string/title_task_list"
                android:launchMode="singleTask">
            <intent-filter>
@@ -40,9 +40,9 @@

        <!-- ViewTaskActivity listens for VIEW intents -->
        <activity
                android:name="org.dmfs.tasks.ViewTaskActivity"
                android:name=".ViewTaskActivity"
                android:label="@string/title_task_detail"
                android:parentActivityName="org.dmfs.tasks.TaskListActivity"
                android:parentActivityName=".TaskListActivity"
                android:theme="@style/OpenTasksAppTheme"
                android:windowSoftInputMode="adjustResize">
            <intent-filter android:label="edit">
@@ -51,17 +51,17 @@
                <category android:name="android.intent.category.DEFAULT"/>

                <data
                        android:scheme="content"
                        android:host="@string/opentasks_authority"
                        android:mimeType="vnd.android.cursor.item/org.dmfs.tasks.tasks"/>
                        android:mimeType="vnd.android.cursor.item/org.dmfs.tasks.tasks"
                        android:scheme="content"/>
            </intent-filter>
        </activity>

        <!-- EditTaskActivity listens for EDIT, INSERT and INSERT_OR_EDIT intents -->
        <activity
                android:name="org.dmfs.tasks.EditTaskActivity"
                android:name=".EditTaskActivity"
                android:label="@string/activity_add_task_title"
                android:parentActivityName="org.dmfs.tasks.TaskListActivity"
                android:parentActivityName=".TaskListActivity"
                android:theme="@style/DetailsTheme"
                android:windowSoftInputMode="stateHidden|adjustResize">
            <meta-data
@@ -74,9 +74,9 @@
                <category android:name="android.intent.category.DEFAULT"/>

                <data
                        android:scheme="content"
                        android:host="@string/opentasks_authority"
                        android:mimeType="vnd.android.cursor.item/org.dmfs.tasks.tasks"/>
                        android:mimeType="vnd.android.cursor.item/org.dmfs.tasks.tasks"
                        android:scheme="content"/>
            </intent-filter>

            <!-- Voice command "note to self" in google search -->
@@ -102,9 +102,9 @@
                <category android:name="android.intent.category.DEFAULT"/>

                <data
                        android:scheme="content"
                        android:host="@string/opentasks_authority"
                        android:mimeType="vnd.android.cursor.dir/org.dmfs.tasks.tasks"/>
                        android:mimeType="vnd.android.cursor.dir/org.dmfs.tasks.tasks"
                        android:scheme="content"/>
            </intent-filter>
            <intent-filter android:label="@string/activity_add_task_title">
                <action android:name="android.intent.action.INSERT_OR_EDIT"/>
@@ -112,21 +112,20 @@
                <category android:name="android.intent.category.DEFAULT"/>

                <data
                        android:scheme="content"
                        android:host="@string/opentasks_authority"
                        android:mimeType="vnd.android.cursor.dir/org.dmfs.tasks.tasks"/>
                        android:mimeType="vnd.android.cursor.dir/org.dmfs.tasks.tasks"
                        android:scheme="content"/>
                <data
                        android:scheme="content"
                        android:host="@string/opentasks_authority"
                        android:mimeType="vnd.android.cursor.item/org.dmfs.tasks.tasks"/>
                        android:mimeType="vnd.android.cursor.item/org.dmfs.tasks.tasks"
                        android:scheme="content"/>
            </intent-filter>
        </activity>


        <activity
                android:name="org.dmfs.tasks.SyncSettingsActivity"
                android:name=".SyncSettingsActivity"
                android:label="@string/title_activity_settings"
                android:parentActivityName="org.dmfs.tasks.TaskListActivity"
                android:parentActivityName=".TaskListActivity"
                android:theme="@style/AppTheme">
            <meta-data
                    android:name="android.support.PARENT_ACTIVITY"
@@ -135,19 +134,20 @@

        <!-- homescreen widgets -->
        <activity
                android:name="org.dmfs.tasks.homescreen.TaskListWidgetSettingsActivity"
                android:name=".homescreen.TaskListWidgetSettingsActivity"
                android:label="@string/task_list_selection_title"
                android:theme="@style/Theme.MaterialDialog">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
            </intent-filter>
        </activity>

        <service
                android:name="org.dmfs.tasks.homescreen.TaskListWidgetUpdaterService"
                android:name=".homescreen.TaskListWidgetUpdaterService"
                android:permission="android.permission.BIND_REMOTEVIEWS"/>

        <receiver
                android:name="org.dmfs.tasks.homescreen.TaskListWidgetProvider"
                android:name=".homescreen.TaskListWidgetProvider"
                android:label="@string/task_list_widget_title">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
@@ -166,9 +166,9 @@
                <action android:name="org.dmfs.android.tasks.TASK_START"/>

                <data
                        android:scheme="content"
                        android:host="@string/opentasks_authority"
                        android:mimeType="vnd.android.cursor.item/org.dmfs.tasks.tasks"/>
                        android:mimeType="vnd.android.cursor.item/org.dmfs.tasks.tasks"
                        android:scheme="content"/>
            </intent-filter>

            <meta-data
@@ -176,7 +176,7 @@
                    android:resource="@xml/task_widget_info"/>
        </receiver>
        <receiver
                android:name="org.dmfs.tasks.homescreen.TaskListWidgetProviderLarge"
                android:name=".homescreen.TaskListWidgetProviderLarge"
                android:enabled="true"
                android:label="@string/task_list_widget_title_4x4">
            <intent-filter>
@@ -196,9 +196,9 @@
                <action android:name="org.dmfs.android.tasks.TASK_START"/>

                <data
                        android:scheme="content"
                        android:host="@string/opentasks_authority"
                        android:mimeType="vnd.android.cursor.item/org.dmfs.tasks.tasks"/>
                        android:mimeType="vnd.android.cursor.item/org.dmfs.tasks.tasks"
                        android:scheme="content"/>
            </intent-filter>

            <meta-data
@@ -206,31 +206,9 @@
                    android:resource="@xml/task_widget_info_large"/>
        </receiver>

        <!-- custom alarm receivers -->
        <receiver
                android:name="org.dmfs.tasks.notification.AlarmBroadcastReceiver"
                android:exported="false">
            <intent-filter>
                <action android:name="org.dmfs.android.tasks.TASK_DUE"/>

                <data
                        android:scheme="content"
                        android:host="@string/opentasks_authority"
                        android:mimeType="vnd.android.cursor.item/org.dmfs.tasks.tasks"/>
            </intent-filter>
            <intent-filter>
                <action android:name="org.dmfs.android.tasks.TASK_START"/>

                <data
                        android:scheme="content"
                        android:host="@string/opentasks_authority"
                        android:mimeType="vnd.android.cursor.item/org.dmfs.tasks.tasks"/>
            </intent-filter>
        </receiver>

        <!-- Dashclock extension -->
        <service
                android:name="org.dmfs.tasks.dashclock.TasksExtension"
                android:name=".dashclock.TasksExtension"
                android:icon="@drawable/ic_dashboard"
                android:label="@string/dashclock_extension_title"
                android:permission="com.google.android.apps.dashclock.permission.READ_EXTENSION_DATA">
@@ -254,13 +232,14 @@
        </service>

        <activity
                android:name="org.dmfs.tasks.dashclock.DashClockPreferenceActivity"
                android:name=".dashclock.DashClockPreferenceActivity"
                android:exported="true"
                android:label="@string/title_task_list"
                android:theme="@style/AppTheme"/>

        <!-- Manage List -->
        <activity
                android:name="org.dmfs.tasks.ManageListActivity"
                android:name=".ManageListActivity"
                android:theme="@style/AppThemeDialog">
            <intent-filter>
                <action android:name="android.intent.action.INSERT"/>
@@ -285,15 +264,16 @@
                        android:scheme="content"/>
            </intent-filter>
        </activity>

        <!-- App Settings -->
        <activity
                android:name=".AppSettingsActivity"
                android:theme="@style/AppTheme"
                android:label="@string/title_activity_settings"/>
                android:label="@string/title_activity_settings"
                android:theme="@style/AppTheme"/>

        <!-- Notification -->
        <receiver
                android:name="org.dmfs.tasks.notification.TaskNotificationHandler"
                android:name=".notification.TaskNotificationHandler"
                android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.PROVIDER_CHANGED"/>
@@ -304,31 +284,12 @@
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
                <action android:name="android.intent.action.QUICKBOOT_POWERON"/>
                <action android:name="android.intent.action.TIME_SET"/>
                <action android:name="android.intent.action.TIMEZONE_CHANGED"/>
                <action android:name="android.intent.action.DATE_CHANGED"/>
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_FIRST_LAUNCH"/>
                <action android:name="android.intent.action.PACKAGE_REPLACED"/>
                <action android:name="android.intent.action.PACKAGE_ADDED"/>

                <data
                        android:path="org.dmfs.tasks"
                        android:scheme="package"/>
            </intent-filter>
            <intent-filter>
                <action android:name="org.dmfs.tasks.action.notification.COMPLETE"/>
                <action android:name="org.dmfs.tasks.action.notification.UNPIN"/>
                <action android:name="org.dmfs.tasks.action.notification.DELAY_1H"/>
                <action android:name="org.dmfs.tasks.action.notification.DELAY_1D"/>

                <data
                        android:scheme="content"
                        android:host="@string/opentasks_authority"
                        android:mimeType="vnd.android.cursor.item/org.dmfs.tasks.tasks"/>
            </intent-filter>
            <intent-filter>
                <action android:name="org.dmfs.tasks.intent.ACTION_DAY_CHANGED"/>
                <action android:name="org.dmfs.tasks.action.notification.UNDO"/>
@@ -337,7 +298,7 @@
            </intent-filter>
        </receiver>
        <receiver
                android:name="org.dmfs.tasks.utils.DatabaseInitializedReceiver"
                android:name=".utils.DatabaseInitializedReceiver"
                android:enabled="@bool/opentasks_support_local_lists"
                android:exported="false">
            <intent-filter>
@@ -358,20 +319,46 @@
        </receiver>

        <service
                android:name="org.dmfs.tasks.notification.NotificationUpdaterService"
                android:exported="false"/>

                android:name=".notification.TaskNotificationService"
                android:exported="true"
                android:permission="android.permission.BIND_JOB_SERVICE"/>
        <service
                android:name="org.dmfs.tasks.quicksettings.TaskQuickSettingsTile"
                android:name=".quicksettings.TaskQuickSettingsTile"
                android:description="@string/quicksettingstile_create"
                android:icon="@drawable/content_edit"
                android:label="@string/quicksettingstile_create"
                android:description="@string/quicksettingstile_create"
                android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
            <intent-filter>
                <action android:name="android.service.quicksettings.action.QS_TILE"/>
            </intent-filter>
        </service>

        <receiver
                android:name=".notification.ActionReceiver"
                android:enabled="true"
                android:exported="false">
            <intent-filter>
                <action android:name="org.dmfs.android.tasks.TASK_DUE"/>

                <data
                        android:host="@string/opentasks_authority"
                        android:mimeType="vnd.android.cursor.item/org.dmfs.tasks.tasks"
                        android:scheme="content"/>
            </intent-filter>
            <intent-filter>
                <action android:name="org.dmfs.android.tasks.TASK_START"/>

                <data
                        android:host="@string/opentasks_authority"
                        android:mimeType="vnd.android.cursor.item/org.dmfs.tasks.tasks"
                        android:scheme="content"/>
            </intent-filter>
        </receiver>

        <service
                android:name=".notification.ActionService"
                android:exported="true"
                android:permission="android.permission.BIND_JOB_SERVICE"/>
    </application>

</manifest>
 No newline at end of file
+36 −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.tasks;

import android.support.v4.app.JobIntentService;


/**
 * Apparently there is some sort of contraint on Job IDs used with {@link JobIntentService}s or Jobs in general.
 * <p>
 * To avoid ID collisions this interface hosts all Job IDs we're using.
 *
 * @author Marten Gajda
 */
public interface JobIds
{
    // base number ("task" in hex)
    int BASE = 0x7461736b;

    int NOTIFICATION_SERVICE = BASE + 1;
    int NOTIFICATION_ACTION_SERVICE = BASE + 2;
}
+4 −4
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ import org.dmfs.tasks.model.Model;
import org.dmfs.tasks.model.OnContentChangeListener;
import org.dmfs.tasks.model.Sources;
import org.dmfs.tasks.model.TaskFieldAdapters;
import org.dmfs.tasks.notification.TaskNotificationHandler;
import org.dmfs.tasks.notification.ActionService;
import org.dmfs.tasks.share.ShareIntentFactory;
import org.dmfs.tasks.utils.ContentValueMapper;
import org.dmfs.tasks.utils.OnModelLoadedListener;
@@ -584,12 +584,12 @@ public class ViewTaskFragment extends SupportFragment
            if (TaskFieldAdapters.PINNED.get(mContentSet))
            {
                item.setIcon(R.drawable.ic_pin_white_24dp);
                TaskNotificationHandler.unpinTask(mAppContext, mContentSet);
                ActionService.startAction(getActivity(), ActionService.ACTION_UNPIN, mTaskUri);
            }
            else
            {
                item.setIcon(R.drawable.ic_pin_off_white_24dp);
                TaskNotificationHandler.pinTask(mAppContext, mContentSet);
                ActionService.startAction(getActivity(), ActionService.ACTION_PIN_TASK, mTaskUri);
            }
            persistTask();
            return true;
+60 −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.tasks.actions;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.ContentProviderClient;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.OperationApplicationException;
import android.net.Uri;
import android.os.RemoteException;

import org.dmfs.android.contentpal.RowDataSnapshot;
import org.dmfs.tasks.contract.TaskContract;
import org.dmfs.tasks.notification.ActionReceiver;


/**
 * A {@link TaskAction} which cancels the delayed execution of another {@link TaskAction}.
 *
 * @author Marten Gajda
 */
public final class CancelDelayedAction implements TaskAction
{
    private final String mAction;


    public CancelDelayedAction(String action)
    {
        mAction = action;
    }


    @Override
    public void execute(Context context, ContentProviderClient contentProviderClient, RowDataSnapshot<TaskContract.Tasks> rowSnapshot, Uri taskUri) throws RemoteException, OperationApplicationException
    {
        ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).cancel(
                PendingIntent.getBroadcast(
                        context,
                        (int) ContentUris.parseId(taskUri),
                        new Intent(context, ActionReceiver.class).setAction(mAction).setData(taskUri),
                        PendingIntent.FLAG_UPDATE_CURRENT));
    }
}
Loading