Add notification channel support.

Bucket our notifications into channels. Required to target API 26.
This commit is contained in:
Greyson Parrelli 2018-08-06 12:20:24 -04:00
parent d0db6aa509
commit dbd42c4af2
17 changed files with 122 additions and 18 deletions

View File

@ -577,6 +577,12 @@
</intent-filter>
</receiver>
<receiver android:name=".notifications.LocaleChangedReceiver">
<intent-filter>
<action android:name="android.intent.action.LOCALE_CHANGED"/>
</intent-filter>
</receiver>
<receiver android:name=".notifications.MessageNotifier$ReminderReceiver">
<intent-filter>
<action android:name="org.thoughtcrime.securesms.MessageNotifier.REMINDER_ACTION"/>

View File

@ -663,6 +663,15 @@
<string name="MessageNotifier_contact_message">%1$s %2$s</string>
<string name="MessageNotifier_unknown_contact_message">Contact</string>
<!-- Notification Channels -->
<string name="NotificationChannel_messages">Messages</string>
<string name="NotificationChannel_calls">Calls</string>
<string name="NotificationChannel_failures">Failures</string>
<string name="NotificationChannel_backups">Backups</string>
<string name="NotificationChannel_locked_status">Locked status</string>
<string name="NotificationChannel_app_updates">App updates</string>
<string name="NotificationChannel_other">Other</string>
<!-- QuickResponseService -->
<string name="QuickResponseService_quick_response_unavailable_when_Signal_is_locked">Quick response unavailable when Signal is locked!</string>
<string name="QuickResponseService_problem_sending_message">Problem sending message!</string>

View File

@ -17,6 +17,8 @@
package org.thoughtcrime.securesms;
import android.annotation.SuppressLint;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.arch.lifecycle.DefaultLifecycleObserver;
import android.arch.lifecycle.LifecycleOwner;
import android.arch.lifecycle.ProcessLifecycleOwner;
@ -25,6 +27,7 @@ import android.os.AsyncTask;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.multidex.MultiDexApplication;
import android.support.v4.app.NotificationManagerCompat;
import com.google.android.gms.security.ProviderInstaller;
@ -47,6 +50,7 @@ import org.thoughtcrime.securesms.logging.CustomSignalProtocolLogger;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.logging.PersistentLogger;
import org.thoughtcrime.securesms.logging.UncaughtExceptionLogger;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
import org.thoughtcrime.securesms.service.DirectoryRefreshListener;
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
@ -103,6 +107,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
initializePeriodicTasks();
initializeCircumvention();
initializeWebRtc();
NotificationChannels.create(this);
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
}
@ -259,7 +264,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private void executePendingContactSync() {
if (TextSecurePreferences.needsFullContactSync(this)) {
ApplicationContext.getInstance(this).getJobManager().add(new MultiDeviceContactUpdateJob(this, true));

View File

@ -18,6 +18,7 @@ import com.melnykov.fab.FloatingActionButton;
import com.nineoldandroids.animation.ArgbEvaluator;
import org.thoughtcrime.securesms.IntroPagerAdapter.IntroPage;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
@ -221,7 +222,7 @@ public class ExperienceUpgradeActivity extends BaseActionBarActivity {
if (TextSecurePreferences.getLastExperienceVersionCode(context) < 339 &&
!TextSecurePreferences.isPasswordDisabled(context))
{
Notification notification = new NotificationCompat.Builder(context)
Notification notification = new NotificationCompat.Builder(context, NotificationChannels.OTHER)
.setSmallIcon(R.drawable.icon_notification)
.setColor(context.getResources().getColor(R.color.signal_primary))
.setContentTitle(context.getString(R.string.ExperienceUpgradeActivity_unlock_to_complete_update))
@ -250,7 +251,7 @@ public class ExperienceUpgradeActivity extends BaseActionBarActivity {
Intent dismissIntent = new Intent(context, AppUpgradeReceiver.class);
dismissIntent.setAction(DISMISS_ACTION);
Notification notification = new NotificationCompat.Builder(context)
Notification notification = new NotificationCompat.Builder(context, NotificationChannels.OTHER)
.setSmallIcon(R.drawable.icon_notification)
.setColor(context.getResources().getColor(R.color.signal_primary))
.setContentTitle(context.getString(experienceUpgrade.get().getNotificationTitle()))

View File

@ -33,6 +33,7 @@ import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
@ -91,7 +92,7 @@ public class GcmRefreshJob extends ContextJob implements InjectableType {
private void notifyGcmFailure() {
Intent intent = new Intent(context, PlayServicesProblemActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 1122, intent, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NotificationChannels.FAILURES);
builder.setSmallIcon(R.drawable.icon_notification);
builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(),

View File

@ -12,6 +12,7 @@ import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.NoExternalStorageException;
import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.service.GenericForegroundService;
import org.thoughtcrime.securesms.util.BackupUtil;
@ -48,7 +49,8 @@ public class LocalBackupJob extends ContextJob {
}
GenericForegroundService.startForegroundTask(context,
context.getString(R.string.LocalBackupJob_creating_backup));
context.getString(R.string.LocalBackupJob_creating_backup),
NotificationChannels.BACKUPS);
try {
String backupPassword = TextSecurePreferences.getBackupPassphrase(context);

View File

@ -46,6 +46,7 @@ import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
import org.thoughtcrime.securesms.mms.QuoteModel;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.WebRtcCallService;
import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage;
@ -135,7 +136,7 @@ public class PushDecryptJob extends ContextJob {
if (TextSecurePreferences.getNeedsSqlCipherMigration(context)) {
Log.w(TAG, "Skipping job, waiting for sqlcipher migration...");
NotificationManagerCompat.from(context).notify(494949,
new NotificationCompat.Builder(context)
new NotificationCompat.Builder(context, NotificationChannels.MESSAGES)
.setSmallIcon(R.drawable.icon_notification)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)

View File

@ -31,6 +31,7 @@ public abstract class AbstractNotificationBuilder extends NotificationCompat.Bui
this.context = context;
this.privacy = privacy;
setChannelId(NotificationChannels.MESSAGES);
setLed();
}

View File

@ -23,6 +23,7 @@ public class FailedNotificationBuilder extends AbstractNotificationBuilder {
setContentIntent(PendingIntent.getActivity(context, 0, intent, 0));
setAutoCancel(true);
setAlarms(null, RecipientDatabase.VibrateState.DEFAULT);
setChannelId(NotificationChannels.FAILURES);
}

View File

@ -0,0 +1,13 @@
package org.thoughtcrime.securesms.notifications;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class LocaleChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
NotificationChannels.create(context);
}
}

View File

@ -0,0 +1,50 @@
package org.thoughtcrime.securesms.notifications;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.R;
import java.util.Arrays;
public class NotificationChannels {
public static String MESSAGES = "messages";
public static String CALLS = "calls";
public static String FAILURES = "failures";
public static String APP_UPDATES = "app_updates";
public static String BACKUPS = "backups";
public static String LOCKED_STATUS = "locked_status";
public static String OTHER = "other";
/**
* Ensures all of the notification channels are created. No harm in repeat calls. Call is safely
* ignored for API < 26.
*/
public static void create(@NonNull Context context) {
if (Build.VERSION.SDK_INT < 26) {
return;
}
NotificationChannel messages = new NotificationChannel(MESSAGES, context.getString(R.string.NotificationChannel_messages), NotificationManager.IMPORTANCE_HIGH);
NotificationChannel calls = new NotificationChannel(CALLS, context.getString(R.string.NotificationChannel_calls), NotificationManager.IMPORTANCE_LOW);
NotificationChannel failures = new NotificationChannel(FAILURES, context.getString(R.string.NotificationChannel_failures), NotificationManager.IMPORTANCE_HIGH);
NotificationChannel backups = new NotificationChannel(BACKUPS, context.getString(R.string.NotificationChannel_backups), NotificationManager.IMPORTANCE_LOW);
NotificationChannel lockedStatus = new NotificationChannel(LOCKED_STATUS, context.getString(R.string.NotificationChannel_locked_status), NotificationManager.IMPORTANCE_LOW);
NotificationChannel other = new NotificationChannel(OTHER, context.getString(R.string.NotificationChannel_other), NotificationManager.IMPORTANCE_LOW);
NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
notificationManager.createNotificationChannels(Arrays.asList(messages, calls, failures, backups, lockedStatus, other));
if (BuildConfig.PLAY_STORE_DISABLED) {
NotificationChannel appUpdates = new NotificationChannel(APP_UPDATES, context.getString(R.string.NotificationChannel_app_updates), NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(appUpdates);
} else {
notificationManager.deleteNotificationChannel(APP_UPDATES);
}
}
}

View File

@ -20,6 +20,7 @@ import org.thoughtcrime.securesms.ConversationListActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.SmsMigrator;
import org.thoughtcrime.securesms.database.SmsMigrator.ProgressDescription;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import java.lang.ref.WeakReference;
import java.util.concurrent.Executor;
@ -124,7 +125,7 @@ public class ApplicationMigrationService extends Service
}
private NotificationCompat.Builder initializeBackgroundNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NotificationChannels.OTHER);
builder.setSmallIcon(R.drawable.icon_notification);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon_notification));
@ -179,7 +180,7 @@ public class ApplicationMigrationService extends Service
private static class CompletedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NotificationChannels.OTHER);
builder.setSmallIcon(R.drawable.icon_notification);
builder.setContentTitle(context.getString(R.string.ApplicationMigrationService_import_complete));
builder.setContentText(context.getString(R.string.ApplicationMigrationService_system_database_import_is_complete));

View File

@ -12,13 +12,15 @@ import android.support.v4.app.NotificationCompat;
import org.thoughtcrime.securesms.ConversationListActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import java.util.concurrent.atomic.AtomicInteger;
public class GenericForegroundService extends Service {
private static final int NOTIFICATION_ID = 827353982;
private static final String EXTRA_TITLE = "extra_title";
private static final int NOTIFICATION_ID = 827353982;
private static final String EXTRA_TITLE = "extra_title";
private static final String EXTRA_CHANNEL_ID = "extra_channel_id";
private static final String ACTION_START = "start";
private static final String ACTION_STOP = "stop";
@ -40,11 +42,14 @@ public class GenericForegroundService extends Service {
private void handleStart(@NonNull Intent intent) {
String title = intent.getStringExtra(EXTRA_TITLE);
String title = intent.getStringExtra(EXTRA_TITLE);
String channelId = intent.getStringExtra(EXTRA_CHANNEL_ID);
assert title != null;
assert channelId != null;
if (foregroundCount.getAndIncrement() == 0) {
startForeground(NOTIFICATION_ID, new NotificationCompat.Builder(this)
startForeground(NOTIFICATION_ID, new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_signal_grey_24dp)
.setContentTitle(title)
.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, ConversationListActivity.class), 0))
@ -66,9 +71,14 @@ public class GenericForegroundService extends Service {
}
public static void startForegroundTask(@NonNull Context context, @NonNull String task) {
startForegroundTask(context, task, NotificationChannels.OTHER);
}
public static void startForegroundTask(@NonNull Context context, @NonNull String task, @NonNull String channelId) {
Intent intent = new Intent(context, GenericForegroundService.class);
intent.setAction(ACTION_START);
intent.putExtra(EXTRA_TITLE, task);
intent.putExtra(EXTRA_CHANNEL_ID, channelId);
context.startService(intent);
}

View File

@ -42,6 +42,7 @@ import org.thoughtcrime.securesms.crypto.InvalidPassphraseException;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
@ -264,7 +265,7 @@ public class KeyCachingService extends Service {
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void foregroundServiceModern() {
Log.i(TAG, "foregrounding KCS");
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NotificationChannels.LOCKED_STATUS);
builder.setContentTitle(getString(R.string.KeyCachingService_passphrase_cached));
builder.setContentText(getString(R.string.KeyCachingService_signal_passphrase_cached));
@ -280,7 +281,7 @@ public class KeyCachingService extends Service {
}
private void foregroundServiceICS() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NotificationChannels.LOCKED_STATUS);
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.key_caching_notification);
remoteViews.setOnClickPendingIntent(R.id.lock_cache_icon, buildLockIntent());
@ -294,7 +295,7 @@ public class KeyCachingService extends Service {
}
private void foregroundServiceLegacy() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NotificationChannels.LOCKED_STATUS);
builder.setSmallIcon(R.drawable.icon_cached);
builder.setWhen(System.currentTimeMillis());

View File

@ -16,6 +16,7 @@ import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement;
import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirementProvider;
import org.thoughtcrime.securesms.jobmanager.requirements.RequirementListener;
import org.thoughtcrime.securesms.jobs.PushContentReceiveJob;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.InvalidVersionException;
import org.whispersystems.signalservice.api.SignalServiceMessagePipe;
@ -104,7 +105,7 @@ public class MessageRetrievalService extends Service implements InjectableType,
private void setForegroundIfNecessary() {
if (TextSecurePreferences.isGcmDisabled(this)) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NotificationChannels.OTHER);
builder.setContentTitle(getString(R.string.MessageRetrievalService_signal));
builder.setContentText(getString(R.string.MessageRetrievalService_background_connection_enabled));
builder.setPriority(NotificationCompat.PRIORITY_MIN);

View File

@ -14,6 +14,7 @@ import android.support.v4.app.NotificationCompat;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.util.FileProviderUtil;
import org.thoughtcrime.securesms.util.FileUtils;
import org.thoughtcrime.securesms.util.Hex;
@ -61,7 +62,7 @@ public class UpdateApkReadyListener extends BroadcastReceiver {
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
Notification notification = new NotificationCompat.Builder(context)
Notification notification = new NotificationCompat.Builder(context, NotificationChannels.APP_UPDATES)
.setOngoing(true)
.setContentTitle(context.getString(R.string.UpdateApkReadyListener_Signal_update))
.setContentText(context.getString(R.string.UpdateApkReadyListener_a_new_version_of_signal_is_available_tap_to_update))

View File

@ -13,6 +13,7 @@ import android.support.v4.app.NotificationCompat;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.WebRtcCallActivity;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.WebRtcCallService;
import org.thoughtcrime.securesms.util.ServiceUtil;
@ -40,7 +41,7 @@ public class CallNotificationBuilder {
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, contentIntent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NotificationChannels.CALLS)
.setSmallIcon(R.drawable.ic_call_secure_white_24dp)
.setContentIntent(pendingIntent)
.setOngoing(true)