From 705df2a536a5a206c7ec8ce8abb099354736742e Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Thu, 14 Mar 2019 21:15:17 +0000 Subject: [PATCH] Overhaul the notification system and add notification channels. --- .../syncadapter/AcraConfiguration.java | 2 +- .../main/java/com/etesync/syncadapter/App.kt | 3 + .../com/etesync/syncadapter/log/Logger.kt | 5 +- .../syncadapter/SyncAdapterService.kt | 3 +- .../syncadapter/SyncNotification.kt | 39 +++------- .../syncadapter/utils/NotificationUtils.kt | 78 +++++++++++++++++++ app/src/main/res/values/strings.xml | 11 +++ 7 files changed, 109 insertions(+), 32 deletions(-) create mode 100644 app/src/main/java/com/etesync/syncadapter/utils/NotificationUtils.kt diff --git a/app/src/main/java/com/etesync/syncadapter/AcraConfiguration.java b/app/src/main/java/com/etesync/syncadapter/AcraConfiguration.java index 7d4528f4..3d60b48b 100644 --- a/app/src/main/java/com/etesync/syncadapter/AcraConfiguration.java +++ b/app/src/main/java/com/etesync/syncadapter/AcraConfiguration.java @@ -24,7 +24,7 @@ public class AcraConfiguration { builder.getPluginConfigurationBuilder(NotificationConfigurationBuilder.class) .setResTitle(R.string.crash_title) .setResText(R.string.crash_message) - .setChannelName("crash-notification") + .setResChannelName(R.string.notification_channel_crash_reports) .setSendOnClick(true) .setEnabled(true); diff --git a/app/src/main/java/com/etesync/syncadapter/App.kt b/app/src/main/java/com/etesync/syncadapter/App.kt index 62040c42..b5138dbd 100644 --- a/app/src/main/java/com/etesync/syncadapter/App.kt +++ b/app/src/main/java/com/etesync/syncadapter/App.kt @@ -33,6 +33,7 @@ import com.etesync.syncadapter.resource.LocalCalendar import com.etesync.syncadapter.ui.AccountsActivity import com.etesync.syncadapter.utils.HintManager import com.etesync.syncadapter.utils.LanguageUtils +import com.etesync.syncadapter.utils.NotificationUtils import io.requery.Persistable import io.requery.android.sqlite.DatabaseSource import io.requery.meta.EntityModel @@ -74,6 +75,8 @@ class App : Application() { StrictMode.enableDefaults() initPrefVersion() + NotificationUtils.createChannels(this) + appName = getString(R.string.app_name) accountType = getString(R.string.account_type) addressBookAccountType = getString(R.string.account_type_address_book) diff --git a/app/src/main/java/com/etesync/syncadapter/log/Logger.kt b/app/src/main/java/com/etesync/syncadapter/log/Logger.kt index 59bd803f..6a29bb81 100644 --- a/app/src/main/java/com/etesync/syncadapter/log/Logger.kt +++ b/app/src/main/java/com/etesync/syncadapter/log/Logger.kt @@ -21,9 +21,9 @@ import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import com.etesync.syncadapter.App import com.etesync.syncadapter.Constants -import com.etesync.syncadapter.syncadapter.SyncNotification import com.etesync.syncadapter.R import com.etesync.syncadapter.ui.AppSettingsActivity +import com.etesync.syncadapter.utils.NotificationUtils import org.apache.commons.lang3.time.DateFormatUtils import java.io.File import java.io.IOException @@ -73,11 +73,10 @@ object Logger : SharedPreferences.OnSharedPreferenceChangeListener { val nm = NotificationManagerCompat.from(context) // log to external file according to preferences if (logToFile) { - val builder = NotificationCompat.Builder(context) + val builder = NotificationUtils.newBuilder(context, NotificationUtils.CHANNEL_DEBUG) builder.setSmallIcon(R.drawable.ic_sd_storage_light) .setLargeIcon(App.getLauncherBitmap(context)) .setContentTitle(context.getString(R.string.logging_davdroid_file_logging)) - .setChannelId(SyncNotification.CHANNEL_ID) val logDir = debugDir(context) ?: return val logFile = File(logDir, diff --git a/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncAdapterService.kt b/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncAdapterService.kt index a9cee8e4..29289d73 100644 --- a/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncAdapterService.kt +++ b/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncAdapterService.kt @@ -28,6 +28,7 @@ import com.etesync.syncadapter.model.CollectionInfo import com.etesync.syncadapter.model.JournalEntity import com.etesync.syncadapter.model.JournalModel import com.etesync.syncadapter.ui.PermissionsActivity +import com.etesync.syncadapter.utils.NotificationUtils import okhttp3.HttpUrl import java.util.* import java.util.logging.Level @@ -59,7 +60,7 @@ abstract class SyncAdapterService : Service() { val intent = Intent(context, PermissionsActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - val notify = NotificationCompat.Builder(context) + val notify = NotificationUtils.newBuilder(context, NotificationUtils.CHANNEL_SYNC_ERRORS) .setSmallIcon(R.drawable.ic_error_light) .setLargeIcon(App.getLauncherBitmap(context)) .setContentTitle(context.getString(R.string.sync_error_permissions)) diff --git a/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncNotification.kt b/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncNotification.kt index 57c211d2..f41861a0 100644 --- a/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncNotification.kt +++ b/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncNotification.kt @@ -1,21 +1,17 @@ package com.etesync.syncadapter.syncadapter import android.app.Activity -import android.app.NotificationChannel -import android.app.NotificationManager import android.app.PendingIntent import android.content.Context import android.content.Intent import android.database.sqlite.SQLiteException import android.net.Uri -import android.os.Build import android.os.Bundle import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import at.bitfire.ical4android.CalendarStorageException import at.bitfire.vcard4android.ContactsStorageException import com.etesync.syncadapter.AccountSettings -import com.etesync.syncadapter.App import com.etesync.syncadapter.Constants import com.etesync.syncadapter.R import com.etesync.syncadapter.journalmanager.Exceptions @@ -23,6 +19,7 @@ import com.etesync.syncadapter.log.Logger import com.etesync.syncadapter.ui.AccountSettingsActivity import com.etesync.syncadapter.ui.DebugInfoActivity import com.etesync.syncadapter.ui.WebViewActivity +import com.etesync.syncadapter.utils.NotificationUtils import java.util.logging.Level class SyncNotification(internal val context: Context, internal val notificationTag: String, internal val notificationId: Int) { @@ -79,12 +76,16 @@ class SyncNotification(internal val context: Context, internal val notificationT @JvmOverloads fun notify(title: String, content: String, bigText: String?, intent: Intent, _icon: Int = -1) { var icon = _icon - createNotificationChannel() - val builder = NotificationCompat.Builder(context) - val category = if (throwable == null) - NotificationCompat.CATEGORY_STATUS - else - NotificationCompat.CATEGORY_ERROR + val category: String; + val channel: String; + if (throwable == null) { + category = NotificationCompat.CATEGORY_STATUS + channel = NotificationUtils.CHANNEL_SYNC_STATUS + } else { + category = NotificationCompat.CATEGORY_ERROR + channel = NotificationUtils.CHANNEL_SYNC_ERRORS + } + val builder = NotificationUtils.newBuilder(context, channel) if (icon == -1) { //Check if error was configured if (throwable == null) { @@ -94,10 +95,8 @@ class SyncNotification(internal val context: Context, internal val notificationT } } - builder.setLargeIcon(App.getLauncherBitmap(context)) - .setContentTitle(title) + builder .setContentTitle(title) .setContentText(content) - .setChannelId(CHANNEL_ID) .setAutoCancel(true) .setCategory(category) .setSmallIcon(icon) @@ -143,18 +142,4 @@ class SyncNotification(internal val context: Context, internal val notificationT finish() } } - - private fun createNotificationChannel() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val name = context.getString(R.string.notification_channel_name) - val channel = NotificationChannel(CHANNEL_ID, name, NotificationManager.IMPORTANCE_LOW) - val notificationManager = context.getSystemService(NotificationManager::class.java) - notificationManager!!.createNotificationChannel(channel) - } - } - - companion object { - val CHANNEL_ID = "EteSync_default" - } - } diff --git a/app/src/main/java/com/etesync/syncadapter/utils/NotificationUtils.kt b/app/src/main/java/com/etesync/syncadapter/utils/NotificationUtils.kt new file mode 100644 index 00000000..093b3fa4 --- /dev/null +++ b/app/src/main/java/com/etesync/syncadapter/utils/NotificationUtils.kt @@ -0,0 +1,78 @@ +/* + * Copyright © Ricki Hirner (bitfire web engineering). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + */ + +package com.etesync.syncadapter.utils + +import android.annotation.TargetApi +import android.app.NotificationChannel +import android.app.NotificationChannelGroup +import android.app.NotificationManager +import android.content.Context +import android.os.Build +import androidx.core.app.NotificationCompat +import com.etesync.syncadapter.App +import com.etesync.syncadapter.R + +object NotificationUtils { + + // notification IDs + const val NOTIFY_EXTERNAL_FILE_LOGGING = 1 + const val NOTIFY_REFRESH_COLLECTIONS = 2 + const val NOTIFY_SYNC_ERROR = 10 + const val NOTIFY_INVALID_RESOURCE = 11 + const val NOTIFY_OPENTASKS = 20 + const val NOTIFY_PERMISSIONS = 21 + const val NOTIFY_LICENSE = 100 + + // notification channels + const val CHANNEL_GENERAL = "general" + const val CHANNEL_DEBUG = "debug" + + private const val CHANNEL_SYNC = "sync" + const val CHANNEL_SYNC_ERRORS = "syncProblems" + const val CHANNEL_SYNC_WARNINGS = "syncWarnings" + const val CHANNEL_SYNC_STATUS = "syncStatus" + + + fun createChannels(context: Context) { + @TargetApi(Build.VERSION_CODES.O) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + + nm.createNotificationChannelGroup(NotificationChannelGroup(CHANNEL_SYNC, context.getString(R.string.notification_channel_sync))) + + nm.createNotificationChannels(listOf( + NotificationChannel(CHANNEL_DEBUG, context.getString(R.string.notification_channel_debugging), NotificationManager.IMPORTANCE_HIGH), + NotificationChannel(CHANNEL_GENERAL, context.getString(R.string.notification_channel_general), NotificationManager.IMPORTANCE_DEFAULT), + + NotificationChannel(CHANNEL_SYNC_ERRORS, context.getString(R.string.notification_channel_sync_errors), NotificationManager.IMPORTANCE_DEFAULT).apply { + description = context.getString(R.string.notification_channel_sync_errors_desc) + group = CHANNEL_SYNC + }, + NotificationChannel(CHANNEL_SYNC_WARNINGS, context.getString(R.string.notification_channel_sync_warnings), NotificationManager.IMPORTANCE_LOW).apply { + description = context.getString(R.string.notification_channel_sync_warnings_desc) + group = CHANNEL_SYNC + }, + NotificationChannel(CHANNEL_SYNC_STATUS, context.getString(R.string.notification_channel_sync_status), NotificationManager.IMPORTANCE_LOW).apply { + description = context.getString(R.string.notification_channel_sync_status_desc) + group = CHANNEL_SYNC + } + )) + } + } + + fun newBuilder(context: Context, channel: String): NotificationCompat.Builder { + val builder = NotificationCompat.Builder(context, channel) + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) + builder.setLargeIcon(App.getLauncherBitmap(context)) + + return builder + } + +} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fab77a49..7fcfcf67 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -21,6 +21,17 @@ Please wait … Send + Crash Reports + Debugging + Other important messages + Synchronization + Synchronization errors + Important errors which stop synchronization like unexpected server replies + Synchronization warnings + Non-fatal synchronization problems like dismissed changes of read-only collections + Status messages + Informational status messages like the sync change summary + EteSync has crashed! Please send stack trace to developers.