From c5fdbdd43cd7d4380e1077d02fa57579ee7c9099 Mon Sep 17 00:00:00 2001 From: Marten Gajda <marten@dmfs.org> Date: Thu, 8 Nov 2018 00:52:16 +0100 Subject: [PATCH] Update SDK target level to 26. Implements #703 (#719) This also updates the support library version to 26.1.0. Due to changes in Android 8 we had to limit some background service and broadcast functionality. There are no limitations to the user experience though, but some planned features may require a different solution now (mostly because implicit broadcasts no longer work). --- .travis.yml | 7 +- dependencies.gradle | 2 +- gradle.properties | 4 +- .../dmfs/provider/tasks/ContentOperation.java | 6 + .../org/dmfs/provider/tasks/TaskProvider.java | 18 +-- opentasks/src/main/AndroidManifest.xml | 2 +- .../java/org/dmfs/tasks/TaskListActivity.java | 14 ++- .../notification/AlarmBroadcastReceiver.java | 8 ++ .../notification/NotificationActionUtils.java | 8 +- .../NotificationUpdaterService.java | 116 ++++++++++++++++-- .../notification/TaskNotificationHandler.java | 28 ++++- .../src/main/res/layout/undo_notification.xml | 4 +- opentasks/src/main/res/values-de/strings.xml | 3 + opentasks/src/main/res/values-v21/styles.xml | 4 +- opentasks/src/main/res/values/strings.xml | 6 + opentasks/src/main/res/values/styles.xml | 4 +- 16 files changed, 195 insertions(+), 39 deletions(-) diff --git a/.travis.yml b/.travis.yml index 78486a9b5..806c007b4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,15 +9,17 @@ android: - tools - platform-tools - tools + - build-tools-26.0.2 - build-tools-27.0.1 - android-24 - - android-25 - android-26 + - extra - extra-android-m2repository - sys-img-armeabi-v7a-android-24 # Emulator Management: Create, Start and Wait before_script: + - android list targets - echo no | android create avd --force -n test --target android-24 --abi armeabi-v7a - QEMU_AUDIO_DRV=none emulator -avd test -no-window & - android-wait-for-emulator @@ -26,3 +28,6 @@ before_script: script: - android list target - ./gradlew check connectedAndroidTest + +after_script: + - cat /home/travis/build/dmfs/opentasks/opentasks/build/reports/lint-results.xml \ No newline at end of file diff --git a/dependencies.gradle b/dependencies.gradle index 3cb9e2806..17ee39b6a 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,4 +1,4 @@ -def support_lib_version = '25.4.0' +def support_lib_version = '26.1.0' def jems_version = '1.15' def contentpal_version = '9b087b2' // 9b087b2 -> 2017-12-12 def support_test_runner_version = '0.5' diff --git a/gradle.properties b/gradle.properties index b7460b615..7cb4a36c9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -COMPILE_SDK_VERSION=25 +COMPILE_SDK_VERSION=26 BUILD_TOOLS_VERSION=27.0.1 MIN_SDK_VERSION=15 -TARGET_SDK_VERSION=25 +TARGET_SDK_VERSION=26 diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/ContentOperation.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/ContentOperation.java index 2022c7fed..f45287e6a 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/ContentOperation.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/ContentOperation.java @@ -26,6 +26,7 @@ import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; +import android.os.Build; import android.os.Handler; import android.util.Log; @@ -183,6 +184,11 @@ private void sendBroadcast(Context context, String action, Uri uri, DateTime dat intent.putExtra(TaskContract.EXTRA_TASK_TIMEZONE, datetime.getTimeZone().getID()); } intent.putExtra(TaskContract.EXTRA_TASK_TITLE, title); + if (Build.VERSION.SDK_INT >= 26) + { + // for now only notify our own package + intent.setPackage(context.getPackageName()); + } context.sendBroadcast(intent); } }), diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskProvider.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskProvider.java index 481714174..6441619f2 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskProvider.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskProvider.java @@ -32,6 +32,7 @@ import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; +import android.os.Build; import android.os.Handler; import android.os.HandlerThread; import android.text.TextUtils; @@ -1294,6 +1295,12 @@ protected void onEndTransaction(boolean callerIsSyncAdapter) } // add the change log to the broadcast providerChangedIntent.putExtras(mOperationsLog.toBundle(true)); + if (Build.VERSION.SDK_INT >= 26) + { + // 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); } @@ -1313,6 +1320,8 @@ public void onDatabaseCreated(SQLiteDatabase db) // notify listeners that the database has been created Intent dbInitializedIntent = new Intent(TaskContract.ACTION_DATABASE_INITIALIZED); dbInitializedIntent.setDataAndType(TaskContract.getContentUri(mAuthority), TaskContract.MIMETYPE_AUTHORITY); + // Android SDK 26 doesn't allow us to send implicit broadcasts, this particular brodcast is only for internal use, so just make it explicit by setting our package name + dbInitializedIntent.setPackage(getContext().getPackageName()); getContext().sendBroadcast(dbInitializedIntent); } @@ -1322,14 +1331,7 @@ public void onDatabaseUpdate(SQLiteDatabase db, int oldVersion, int newVersion) { if (oldVersion < 15) { - mAsyncHandler.post(new Runnable() - { - @Override - public void run() - { - ContentOperation.UPDATE_TIMEZONE.fire(getContext(), null); - } - }); + mAsyncHandler.post(() -> ContentOperation.UPDATE_TIMEZONE.fire(getContext(), null)); } } diff --git a/opentasks/src/main/AndroidManifest.xml b/opentasks/src/main/AndroidManifest.xml index 02b61d25f..716131456 100644 --- a/opentasks/src/main/AndroidManifest.xml +++ b/opentasks/src/main/AndroidManifest.xml @@ -207,7 +207,7 @@ <!-- custom alarm receivers --> <receiver android:name="org.dmfs.tasks.notification.AlarmBroadcastReceiver" - android:permission=""> + android:exported="false"> <intent-filter> <action android:name="org.dmfs.android.tasks.TASK_DUE"/> diff --git a/opentasks/src/main/java/org/dmfs/tasks/TaskListActivity.java b/opentasks/src/main/java/org/dmfs/tasks/TaskListActivity.java index 608b3c615..a9f4ebd79 100644 --- a/opentasks/src/main/java/org/dmfs/tasks/TaskListActivity.java +++ b/opentasks/src/main/java/org/dmfs/tasks/TaskListActivity.java @@ -25,6 +25,7 @@ import android.os.Build.VERSION; import android.os.Bundle; import android.os.Handler; +import android.provider.Settings; import android.support.annotation.ColorInt; import android.support.annotation.NonNull; import android.support.design.widget.AppBarLayout; @@ -639,7 +640,18 @@ else if (item.getItemId() == R.id.menu_visible_list) } else if (item.getItemId() == R.id.opentasks_menu_app_settings) { - startActivity(new Intent(this, AppSettingsActivity.class)); + if (VERSION.SDK_INT < 26) + { + startActivity(new Intent(this, AppSettingsActivity.class)); + } + else + { + // for now just open the notification settings, which is all we currently support anyway + Intent intent = new Intent(); + intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS); + intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName()); + startActivity(intent); + } return true; } else diff --git a/opentasks/src/main/java/org/dmfs/tasks/notification/AlarmBroadcastReceiver.java b/opentasks/src/main/java/org/dmfs/tasks/notification/AlarmBroadcastReceiver.java index 3b01ef36e..91612a1ff 100644 --- a/opentasks/src/main/java/org/dmfs/tasks/notification/AlarmBroadcastReceiver.java +++ b/opentasks/src/main/java/org/dmfs/tasks/notification/AlarmBroadcastReceiver.java @@ -22,6 +22,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; +import android.os.Build; import android.preference.PreferenceManager; import org.dmfs.tasks.R; @@ -47,6 +48,7 @@ public void onReceive(Context context, Intent intent) { if (isNotificationEnabled(context)) { + NotificationUpdaterService.createChannels(context); Uri taskUri = intent.getData(); boolean noSignal = intent.getBooleanExtra(NotificationActionUtils.EXTRA_NOTIFICATION_NO_SIGNAL, false); @@ -72,6 +74,7 @@ else if (intent.getAction().equals(TaskContract.ACTION_BROADCAST_TASK_DUE)) { if (isNotificationEnabled(context)) { + NotificationUpdaterService.createChannels(context); Uri taskUri = intent.getData(); boolean noSignal = intent.getBooleanExtra(NotificationActionUtils.EXTRA_NOTIFICATION_NO_SIGNAL, false); @@ -100,6 +103,11 @@ else if (intent.getAction().equals(TaskContract.ACTION_BROADCAST_TASK_DUE)) public boolean isNotificationEnabled(Context context) { + if (Build.VERSION.SDK_INT >= 26) + { + // on Android 8+ we leave this decision to Android and always attempt to show the notification + return true; + } SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); return settings.getBoolean(context.getString(R.string.opentasks_pref_notification_enabled), true); diff --git a/opentasks/src/main/java/org/dmfs/tasks/notification/NotificationActionUtils.java b/opentasks/src/main/java/org/dmfs/tasks/notification/NotificationActionUtils.java index 3eb2105b2..ac7e4a1d2 100644 --- a/opentasks/src/main/java/org/dmfs/tasks/notification/NotificationActionUtils.java +++ b/opentasks/src/main/java/org/dmfs/tasks/notification/NotificationActionUtils.java @@ -92,7 +92,8 @@ public static void sendDueAlarmNotification(Context context, String title, Uri t } // build notification - NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context).setSmallIcon(R.drawable.ic_notification) + NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, NotificationUpdaterService.CHANNEL_DUE_DATES).setSmallIcon( + R.drawable.ic_notification) .setContentTitle(title).setContentText(dueString); // color @@ -172,7 +173,8 @@ public static void sendStartNotification(Context context, String title, Uri task NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); // build notification - NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context).setSmallIcon(R.drawable.ic_notification) + NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, NotificationUpdaterService.CHANNEL_DUE_DATES).setSmallIcon( + R.drawable.ic_notification) .setContentTitle(title).setContentText(startString); // color @@ -251,7 +253,7 @@ public static PendingIntent getNotificationActionPendingIntent(Context context, */ public static void createUndoNotification(final Context context, NotificationAction action) { - NotificationCompat.Builder builder = new NotificationCompat.Builder(context); + NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NotificationUpdaterService.CHANNEL_DUE_DATES); builder.setContentTitle(context.getString(action.getActionTextResId() )); diff --git a/opentasks/src/main/java/org/dmfs/tasks/notification/NotificationUpdaterService.java b/opentasks/src/main/java/org/dmfs/tasks/notification/NotificationUpdaterService.java index b8bdcdcb7..53306cc7f 100644 --- a/opentasks/src/main/java/org/dmfs/tasks/notification/NotificationUpdaterService.java +++ b/opentasks/src/main/java/org/dmfs/tasks/notification/NotificationUpdaterService.java @@ -16,9 +16,12 @@ package org.dmfs.tasks.notification; +import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.AlarmManager; import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.ContentProviderOperation; @@ -68,6 +71,9 @@ */ public class NotificationUpdaterService extends Service { + public static final String CHANNEL_PINNED = "org.dmfs.opentasks.PINNED"; + public static final String CHANNEL_DUE_DATES = "org.dmfs.opentasks.DUE_DATES"; + private static final String TAG = "NotificationUpdaterSe"; /** @@ -79,6 +85,8 @@ public class NotificationUpdaterService extends Service private static final int REQUEST_CODE_DELAY = 2; private static final int REQUEST_CODE_UNPIN = 3; + private static final int DUMMY_NOTIFICATION_ID = -10; + // actions public static final String ACTION_PINNED_TASK_DUE = "org.dmfs.tasks.intent.ACTION_PINNED_TASK_DUE"; public static final String ACTION_PINNED_TASK_START = "org.dmfs.tasks.intent.ACTION_PINNED_TASK_START"; @@ -97,11 +105,13 @@ public class NotificationUpdaterService extends Service public static final String EXTRA_TIMEZONE = "org.dmfs.tasks.extras.notification.TIMEZONE"; public static final String EXTRA_ALLDAY = "org.dmfs.tasks.extras.notification.ALLDAY"; - private final NotificationCompat.Builder mBuilder = new Builder(this); + private final NotificationCompat.Builder mBuilder = new Builder(this, NotificationUpdaterService.CHANNEL_DUE_DATES); private PendingIntent mDateChangePendingIntent; ArrayList<ContentSet> mTasksToPin; private String mAuthority; + private int mForegroundPinned = -1; + @Override public IBinder onBind(Intent intent) @@ -117,10 +127,50 @@ public NotificationUpdaterService() } + public static void createChannels(Context context) + { + if (VERSION.SDK_INT >= 26) + { + NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + NotificationChannel pinnedChannel = new NotificationChannel(CHANNEL_PINNED, context.getString(R.string.opentasks_notification_channel_pinned_tasks), + NotificationManager.IMPORTANCE_DEFAULT); + // pinned Notifications should not get a badge, but they may vibrate + pinnedChannel.setShowBadge(false); + pinnedChannel.enableLights(false); + pinnedChannel.enableVibration(true); + pinnedChannel.setVibrationPattern(new long[] { 0, 100, 100, 100, 0 }); + nm.createNotificationChannel(pinnedChannel); + + NotificationChannel dueDates = new NotificationChannel(NotificationUpdaterService.CHANNEL_DUE_DATES, + context.getString(R.string.opentasks_notification_channel_due_dates), NotificationManager.IMPORTANCE_HIGH); + dueDates.setShowBadge(true); + dueDates.enableLights(true); + dueDates.enableVibration(true); + nm.createNotificationChannel(dueDates); + } + } + + + @SuppressLint("WrongConstant") @Override public void onCreate() { mAuthority = AuthorityUtil.taskAuthority(this); + + if (VERSION.SDK_INT >= 26) + { + createChannels(this); + + // note this notification is to make Android happy, it should never be visible to the user because it's either replaced or + // discarded in onStartCommand + startForeground(DUMMY_NOTIFICATION_ID, new NotificationCompat.Builder(this, NotificationUpdaterService.CHANNEL_PINNED).setTicker("OpenTasks") + .setSmallIcon(R.drawable.ic_24_opentasks) + .setSound(null) + .setVibrate(null) + .setPriority(NotificationCompat.PRIORITY_MIN) + .build()); + } + super.onCreate(); updateNextDayAlarm(); } @@ -129,7 +179,6 @@ public void onCreate() @Override public int onStartCommand(Intent intent, int flags, int startId) { - String intentAction = intent.getAction(); boolean noSignal = intent.getBooleanExtra(NotificationActionUtils.EXTRA_NOTIFICATION_NO_SIGNAL, false); if (intentAction != null) @@ -200,13 +249,39 @@ public int onStartCommand(Intent intent, int flags, int startId) // check if the service needs to kept alive if (mTasksToPin == null || mTasksToPin.isEmpty()) { + if (VERSION.SDK_INT >= 26) + { + this.stopForeground(true); + mForegroundPinned = -1; + } this.stopSelf(); } + else if (VERSION.SDK_INT >= 26 && (mForegroundPinned < 0 || !isPinned(mForegroundPinned))) + { + // on Android 8+ we have to create or change the foreground notification if we didn't do that yet or of the respective task is no longer pinned + mBuilder.setChannelId(CHANNEL_PINNED); + ContentSet task = mTasksToPin.get(0); + startForeground(TaskFieldAdapters.TASK_ID.get(task), makePinNotification(this, mBuilder, task, true, false, false)); + mForegroundPinned = TaskFieldAdapters.TASK_ID.get(task); + } return Service.START_NOT_STICKY; } + private boolean isPinned(long id) + { + for (ContentSet task : mTasksToPin) + { + if (id == TaskFieldAdapters.TASK_ID.get(task)) + { + return true; + } + } + return false; + } + + private void updateNotifications(boolean isReboot, boolean noSignal, boolean withHeadsUpNotification) { // update pinned tasks @@ -225,6 +300,7 @@ private void updatePinnedNotifications(ArrayList<ContentSet> tasksToPin, boolean { boolean isAlreadyShown = pinnedTaskUris.contains(taskContentSet.getUri()); Integer taskId = TaskFieldAdapters.TASK_ID.get(taskContentSet); + mBuilder.setChannelId(CHANNEL_PINNED); notificationManager.notify(taskId, makePinNotification(this, mBuilder, taskContentSet, isAlreadyShown && noSignal, isAlreadyShown && noSignal, withHeadsUpNotification)); } @@ -241,12 +317,7 @@ private void updatePinnedNotifications(ArrayList<ContentSet> tasksToPin, boolean long taskId = ContentUris.parseId(uri); if (taskId > -1 == !containsTask(tasksToPin, uri)) { - - Integer notificationId = Long.valueOf(ContentUris.parseId(uri)).intValue(); - if (notificationId != null) - { - notificationManager.cancel(notificationId); - } + notificationManager.cancel((int) taskId); } } } @@ -314,6 +385,7 @@ private static Notification makePinNotification(Context context, Builder builder { Resources resources = context.getResources(); + builder.setChannelId(CHANNEL_PINNED); // reset actions builder.mActions = new ArrayList<Action>(2); @@ -392,7 +464,11 @@ private static Notification makePinNotification(Context context, Builder builder // unpin action builder.addAction(NotificationUpdaterService.getUnpinAction(context, TaskFieldAdapters.TASK_ID.get(task), task.getUri())); - builder.setDefaults(new Conditional(!noSignal, context).value()); + if (VERSION.SDK_INT < 26) + { + builder.setDefaults(new Conditional(!noSignal, context).value()); + } + builder.setOnlyAlertOnce(noSignal); return builder.build(); } @@ -480,6 +556,11 @@ private void resendNotification(NotificationAction notificationAction) startIntent.putExtra(TaskContract.EXTRA_TASK_TITLE, notificationAction.title()); startIntent.putExtra(TaskContract.EXTRA_TASK_TIMESTAMP, notificationAction.getWhen()); startIntent.putExtra(NotificationActionUtils.EXTRA_NOTIFICATION_NO_SIGNAL, true); + if (Build.VERSION.SDK_INT >= 26) + { + // for now only notify our own package + startIntent.setPackage(getPackageName()); + } sendBroadcast(startIntent); // Due broadcast @@ -489,6 +570,11 @@ private void resendNotification(NotificationAction notificationAction) dueIntent.putExtra(TaskContract.EXTRA_TASK_TITLE, notificationAction.title()); dueIntent.putExtra(TaskContract.EXTRA_TASK_TIMESTAMP, notificationAction.getWhen()); dueIntent.putExtra(NotificationActionUtils.EXTRA_NOTIFICATION_NO_SIGNAL, true); + if (Build.VERSION.SDK_INT >= 26) + { + // for now only notify our own package + dueIntent.setPackage(getPackageName()); + } sendBroadcast(dueIntent); } } @@ -660,14 +746,18 @@ private void delayTask(Uri taskUri, Time dueTime) private void delayedCancelHeadsUpNotification() { Handler handler = new Handler(Looper.getMainLooper()); - final Runnable r = new Runnable() + final Runnable r = () -> { - public void run() + Intent intent = new Intent(getBaseContext(), NotificationUpdaterService.class); + intent.setAction(ACTION_CANCEL_HEADUP_NOTIFICATION); + if (VERSION.SDK_INT < 26) { - Intent intent = new Intent(getBaseContext(), NotificationUpdaterService.class); - intent.setAction(ACTION_CANCEL_HEADUP_NOTIFICATION); startService(intent); } + else + { + startForegroundService(intent); + } }; handler.postDelayed(r, HEAD_UP_NOTIFICATION_DURATION); } diff --git a/opentasks/src/main/java/org/dmfs/tasks/notification/TaskNotificationHandler.java b/opentasks/src/main/java/org/dmfs/tasks/notification/TaskNotificationHandler.java index 82fcaca8c..fb9835fd4 100644 --- a/opentasks/src/main/java/org/dmfs/tasks/notification/TaskNotificationHandler.java +++ b/opentasks/src/main/java/org/dmfs/tasks/notification/TaskNotificationHandler.java @@ -23,6 +23,7 @@ import android.content.SharedPreferences.Editor; import android.database.Cursor; import android.net.Uri; +import android.os.Build; import android.preference.PreferenceManager; import org.dmfs.provider.tasks.AuthorityUtil; @@ -99,7 +100,14 @@ private static void startPinnedTaskService(Context context, Uri taskUri, String intent.setData(taskUri); intent.setAction(action); intent.putExtra(NotificationUpdaterService.EXTRA_NEW_PINNED_TASK, task); - context.startService(intent); + if (Build.VERSION.SDK_INT < 26) + { + context.startService(intent); + } + else + { + context.startForegroundService(intent); + } } @@ -191,7 +199,14 @@ public static void sendPinnedTaskStartNotification(Context context, Uri taskUri, intent.setAction(NotificationUpdaterService.ACTION_PINNED_TASK_START); intent.putExtra(NotificationActionUtils.EXTRA_NOTIFICATION_NO_SIGNAL, noSignal); intent.setData(taskUri); - context.startService(intent); + if (Build.VERSION.SDK_INT < 26) + { + context.startService(intent); + } + else + { + context.startForegroundService(intent); + } } @@ -201,7 +216,14 @@ public static void sendPinnedTaskDueNotification(Context context, Uri taskUri, b intent.setAction(NotificationUpdaterService.ACTION_PINNED_TASK_DUE); intent.putExtra(NotificationActionUtils.EXTRA_NOTIFICATION_NO_SIGNAL, noSignal); intent.setData(taskUri); - context.startService(intent); + if (Build.VERSION.SDK_INT < 26) + { + context.startService(intent); + } + else + { + context.startForegroundService(intent); + } } } diff --git a/opentasks/src/main/res/layout/undo_notification.xml b/opentasks/src/main/res/layout/undo_notification.xml index 359252990..c0a85e0c1 100644 --- a/opentasks/src/main/res/layout/undo_notification.xml +++ b/opentasks/src/main/res/layout/undo_notification.xml @@ -27,7 +27,7 @@ android:ellipsize="marquee" android:fadingEdge="horizontal" android:gravity="center_vertical" - android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title.colorFix"/> + android:textAppearance="@style/TextAppearance.AppCompat.Notification.Title.colorFix"/> <ImageView android:layout_width="1dip" @@ -53,6 +53,6 @@ android:paddingRight="16dip" android:text="@string/notification_undo" android:textAllCaps="true" - android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Action"/> + android:textAppearance="@style/TextAppearance.AppCompat.Notification.Action"/> </LinearLayout> \ No newline at end of file diff --git a/opentasks/src/main/res/values-de/strings.xml b/opentasks/src/main/res/values-de/strings.xml index a8f73aa8c..e6f1b7dd3 100644 --- a/opentasks/src/main/res/values-de/strings.xml +++ b/opentasks/src/main/res/values-de/strings.xml @@ -274,4 +274,7 @@ <!-- Format indicating a date and time. Example: "23 Aug, 11:00 am" --> <string name="opentasks_date_time">%1$s, %2$s</string> + <string name="opentasks_notification_channel_pinned_tasks">Angeheftete Aufgaben</string> + <string name="opentasks_notification_channel_due_dates">Beginn und Fälligkeiten</string> + </resources> diff --git a/opentasks/src/main/res/values-v21/styles.xml b/opentasks/src/main/res/values-v21/styles.xml index 8aaca4435..71fb88770 100644 --- a/opentasks/src/main/res/values-v21/styles.xml +++ b/opentasks/src/main/res/values-v21/styles.xml @@ -11,13 +11,13 @@ <item name="actionBarItemBackground">@drawable/selectable_background_white</item> </style> - <style name="TextAppearance.StatusBar.EventContent.Title.colorFix"> + <style name="TextAppearance.AppCompat.Notification.Title.colorFix"> <item name="android:textColor">@color/abc_primary_text_material_light</item> <item name="android:fontFamily">sans-serif</item> <item name="android:textStyle">normal</item> </style> - <style name="TextAppearance.StatusBar.EventContent.Action"> + <style name="TextAppearance.AppCompat.Notification.Action"> <item name="android:textColor">@color/abc_secondary_text_material_light</item> <item name="android:fontFamily">sans-serif-light</item> <item name="android:textStyle">bold</item> diff --git a/opentasks/src/main/res/values/strings.xml b/opentasks/src/main/res/values/strings.xml index 27933bfcc..5f0023057 100644 --- a/opentasks/src/main/res/values/strings.xml +++ b/opentasks/src/main/res/values/strings.xml @@ -280,4 +280,10 @@ <!-- Format indicating a date and time. Example: "23 Aug, 11:00 am" --> <string name="opentasks_date_time">%1$s, %2$s</string> + <!-- Title of the notification channel for pinned tasks --> + <string name="opentasks_notification_channel_pinned_tasks">Pinned tasks</string> + + <!-- Title of the notification channel for start and due alerts --> + <string name="opentasks_notification_channel_due_dates">Start and due dates </string> + </resources> diff --git a/opentasks/src/main/res/values/styles.xml b/opentasks/src/main/res/values/styles.xml index 61b01cb2f..0673b2f1f 100644 --- a/opentasks/src/main/res/values/styles.xml +++ b/opentasks/src/main/res/values/styles.xml @@ -348,9 +348,9 @@ <!-- styles for actionbar / toolbar --> - <style name="TextAppearance.StatusBar.EventContent.Title.colorFix"/> + <style name="TextAppearance.AppCompat.Notification.Title.colorFix"/> - <style name="TextAppearance.StatusBar.EventContent.Action"/> + <style name="TextAppearance.AppCompat.Notification.Action"/> <style name="ot_notification_icon_undo"> <item name="android:src">@drawable/ic_24_undo_white</item>