diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index 16558b9ea1..30c0d83708 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -26,6 +26,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.annotation.WorkerThread; +import androidx.core.content.ContextCompat; import androidx.multidex.MultiDexApplication; import com.google.android.gms.security.ProviderInstaller; @@ -84,6 +85,7 @@ import org.thoughtcrime.securesms.mms.SignalGlideComponents; import org.thoughtcrime.securesms.mms.SignalGlideModule; import org.thoughtcrime.securesms.net.NetworkManager; +import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.providers.BlobProvider; import org.thoughtcrime.securesms.ratelimit.RateLimitUtil; import org.thoughtcrime.securesms.recipients.Recipient; @@ -310,7 +312,7 @@ public void onUnlock() { } @MainThread - public void onLock() { + public void onLock(boolean keyExpired) { Log.i(TAG, "onLock()"); stopService(new Intent(this, WebRtcCallService.class)); @@ -319,6 +321,16 @@ public void onLock() { finalizeMessageRetrieval(); unregisterKeyEventReceiver(); + MessageNotifier messageNotifier = ApplicationDependencies.getMessageNotifier(); + messageNotifier.cancelDelayedNotifications(); + boolean hadActiveNotifications = messageNotifier.clearNotifications(this); + + if (hadActiveNotifications && keyExpired && SignalStore.account().isPushAvailable() && + TextSecurePreferences.isPassphraseLockNotificationsEnabled(this) ) { + Log.d(TAG, "Replacing active notifications with may-have-messages notification"); + FcmFetchManager.postMayHaveMessagesNotification(this); + } + ThreadUtil.runOnMainDelayed(() -> { ApplicationDependencies.getJobManager().shutdown(TimeUnit.SECONDS.toMillis(10)); KeyCachingService.clearMasterSecret(); @@ -628,15 +640,15 @@ public void e(@NonNull String tag, @NonNull String message, @Nullable Throwable private final BroadcastReceiver keyEventReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - onLock(); + boolean keyExpired = intent.getBooleanExtra(KeyCachingService.EXTRA_KEY_EXPIRED, false); + onLock(keyExpired); } }; private void registerKeyEventReceiver() { IntentFilter filter = new IntentFilter(); filter.addAction(KeyCachingService.CLEAR_KEY_EVENT); - - registerReceiver(keyEventReceiver, filter, KeyCachingService.KEY_PERMISSION, null); + ContextCompat.registerReceiver(this, keyEventReceiver, filter, KeyCachingService.KEY_PERMISSION, null, ContextCompat.RECEIVER_NOT_EXPORTED); } private void unregisterKeyEventReceiver() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/NotificationsSettingsFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/NotificationsSettingsFragment.kt index f648cfa7fb..6fd7be9775 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/NotificationsSettingsFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/NotificationsSettingsFragment.kt @@ -18,6 +18,7 @@ import androidx.annotation.RequiresApi import androidx.core.content.ContextCompat import androidx.lifecycle.ViewModelProvider import androidx.navigation.fragment.findNavController +import com.google.android.material.dialog.MaterialAlertDialogBuilder import org.signal.core.util.getParcelableExtraCompat import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.R @@ -276,6 +277,25 @@ class NotificationsSettingsFragment : DSLSettingsFragment(R.string.preferences__ sectionHeaderPref(R.string.NotificationsSettingsFragment__notify_when) + switchPref( + title = DSLSettingsText.from(R.string.NotificationsSettingsFragment__new_activity_while_locked), + summary = DSLSettingsText.from(R.string.NotificationsSettingsFragment__receive_notifications_for_messages_or_missed_calls_when_the_app_is_locked), + isChecked = state.notifyWhileLocked, + onToggle = { isChecked -> + if (isChecked && !state.canEnableNotifyWhileLocked) { + MaterialAlertDialogBuilder(requireContext()) + .setTitle(R.string.NotificationsSettingsFragment__push_notifications_unavailable) + .setMessage(R.string.NotificationsSettingsFragment__sorry_this_feature_requires_push_notifications_delivered_via_fcm_or_unifiedpush) + .setPositiveButton(android.R.string.ok, null) + .show() + false + } else { + viewModel.setNotifyWhileLocked(isChecked) + true + } + } + ) + switchPref( title = DSLSettingsText.from(R.string.NotificationsSettingsFragment__contact_joins_signal), isChecked = state.notifyWhenContactJoinsSignal, diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/NotificationsSettingsState.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/NotificationsSettingsState.kt index 97b6595cd1..f4a18d7d9a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/NotificationsSettingsState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/NotificationsSettingsState.kt @@ -5,6 +5,8 @@ import android.net.Uri data class NotificationsSettingsState( val messageNotificationsState: MessageNotificationsState, val callNotificationsState: CallNotificationsState, + val notifyWhileLocked: Boolean, + val canEnableNotifyWhileLocked: Boolean, val notifyWhenContactJoinsSignal: Boolean ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/NotificationsSettingsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/NotificationsSettingsViewModel.kt index caf8d925cf..2840341443 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/NotificationsSettingsViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/NotificationsSettingsViewModel.kt @@ -1,5 +1,6 @@ package org.thoughtcrime.securesms.components.settings.app.notifications +import android.app.Application import android.content.SharedPreferences import android.net.Uri import android.os.Build @@ -17,6 +18,8 @@ class NotificationsSettingsViewModel(private val sharedPreferences: SharedPrefer private val store = Store(getState()) + private val application: Application = ApplicationDependencies.getApplication() + val state: LiveData = store.stateLiveData init { @@ -96,6 +99,11 @@ class NotificationsSettingsViewModel(private val sharedPreferences: SharedPrefer refresh() } + fun setNotifyWhileLocked(enabled: Boolean) { + TextSecurePreferences.setPassphraseLockNotificationsEnabled(application, enabled) + refresh() + } + fun setNotifyWhenContactJoinsSignal(enabled: Boolean) { SignalStore.settings().isNotifyWhenContactJoinsSignal = enabled refresh() @@ -117,7 +125,7 @@ class NotificationsSettingsViewModel(private val sharedPreferences: SharedPrefer inChatSoundsEnabled = SignalStore.settings().isMessageNotificationsInChatSoundsEnabled, repeatAlerts = SignalStore.settings().messageNotificationsRepeatAlerts, messagePrivacy = SignalStore.settings().messageNotificationsPrivacy.toString(), - priority = TextSecurePreferences.getNotificationPriority(ApplicationDependencies.getApplication()), + priority = TextSecurePreferences.getNotificationPriority(application), ), callNotificationsState = CallNotificationsState( notificationsEnabled = SignalStore.settings().isCallNotificationsEnabled && canEnableNotifications(), @@ -125,6 +133,8 @@ class NotificationsSettingsViewModel(private val sharedPreferences: SharedPrefer ringtone = SignalStore.settings().callRingtone, vibrateEnabled = SignalStore.settings().isCallVibrateEnabled ), + notifyWhileLocked = TextSecurePreferences.isPassphraseLockNotificationsEnabled(application) && SignalStore.account().pushAvailable, + canEnableNotifyWhileLocked = SignalStore.account().pushAvailable, notifyWhenContactJoinsSignal = SignalStore.settings().isNotifyWhenContactJoinsSignal ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/gcm/FcmFetchManager.kt b/app/src/main/java/org/thoughtcrime/securesms/gcm/FcmFetchManager.kt index 58a57aee13..124ecadab6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/gcm/FcmFetchManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/gcm/FcmFetchManager.kt @@ -7,6 +7,7 @@ import android.content.Intent import android.os.Build import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat +import androidx.core.content.ContextCompat import org.signal.core.util.PendingIntentFlags.mutable import org.signal.core.util.concurrent.SignalExecutors import org.signal.core.util.logging.Log @@ -70,13 +71,18 @@ object FcmFetchManager { } } - private fun postMayHaveMessagesNotification(context: Context) { - if (FeatureFlags.fcmMayHaveMessagesNotificationKillSwitch()) { - Log.w(TAG, "May have messages notification kill switch") + @JvmStatic + fun postMayHaveMessagesNotification(context: Context) { + val notificationManager = NotificationManagerCompat.from(context) + + if (notificationManager.getNotificationChannel(NotificationChannels.ADDITIONAL_MESSAGE_NOTIFICATIONS) == null) { + Log.e(TAG, "Notification channel for MAY_HAVE_MESSAGES_NOTIFICATION does not exist.") return } - val mayHaveMessagesNotification: Notification = NotificationCompat.Builder(context, NotificationChannels.getInstance().ADDITIONAL_MESSAGE_NOTIFICATIONS) + + val mayHaveMessagesNotification: Notification = NotificationCompat.Builder(context, NotificationChannels.ADDITIONAL_MESSAGE_NOTIFICATIONS) .setSmallIcon(R.drawable.ic_notification) + .setColor(ContextCompat.getColor(context, R.color.core_ultramarine)) .setContentTitle(context.getString(R.string.FcmFetchManager__you_may_have_messages)) .setCategory(NotificationCompat.CATEGORY_MESSAGE) .setContentIntent(PendingIntent.getActivity(context, 0, MainActivity.clearTop(context), mutable())) @@ -84,7 +90,7 @@ object FcmFetchManager { .setOnlyAlertOnce(true) .build() - NotificationManagerCompat.from(context) + notificationManager .notify(NotificationIds.MAY_HAVE_MESSAGES_NOTIFICATION_ID, mayHaveMessagesNotification) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/gcm/FcmReceiveService.java b/app/src/main/java/org/thoughtcrime/securesms/gcm/FcmReceiveService.java index de58878c3d..206b912446 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/gcm/FcmReceiveService.java +++ b/app/src/main/java/org/thoughtcrime/securesms/gcm/FcmReceiveService.java @@ -18,6 +18,7 @@ import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.util.NetworkUtil; import org.thoughtcrime.securesms.util.SignalLocalMetrics; +import org.thoughtcrime.securesms.util.TextSecurePreferences; import java.util.Locale; @@ -26,8 +27,13 @@ public class FcmReceiveService extends FirebaseMessagingService { private static final String TAG = Log.tag(FcmReceiveService.class); @Override - public void onMessageReceived(RemoteMessage remoteMessage) { + public void onMessageReceived(@NonNull RemoteMessage remoteMessage) { if (KeyCachingService.isLocked()) { + if (remoteMessage.getPriority() == RemoteMessage.PRIORITY_HIGH && + TextSecurePreferences.isPassphraseLockNotificationsEnabled(this)) { + Log.d(TAG, "New urgent message received while app is locked."); + FcmFetchManager.postMayHaveMessagesNotification(this); + } return; } @@ -63,7 +69,7 @@ public void onDeletedMessages() { } @Override - public void onNewToken(String token) { + public void onNewToken(@NonNull String token) { Log.i(TAG, "onNewToken()"); if (KeyCachingService.isLocked()) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt index dc336874b1..a7c8738e52 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt @@ -292,6 +292,10 @@ internal class AccountValues internal constructor(store: KeyValueStore) : Signal @get:JvmName("isFcmEnabled") var fcmEnabled: Boolean by booleanValue(KEY_FCM_ENABLED, false) + @get:JvmName("isPushAvailable") + val pushAvailable: Boolean + get() = fcmEnabled + /** The FCM token, which allows the server to send us FCM messages. */ var fcmToken: String? get() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/MessageNotifier.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/MessageNotifier.java index 5e64c9edaa..8fe32177ba 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/MessageNotifier.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/MessageNotifier.java @@ -29,7 +29,7 @@ public interface MessageNotifier { void updateNotification(@NonNull Context context, @NonNull ConversationId conversationId, @NonNull BubbleUtil.BubbleState defaultBubbleState); void updateNotification(@NonNull Context context, @NonNull ConversationId conversationId, boolean signal); void updateNotification(@NonNull Context context, @Nullable ConversationId conversationId, boolean signal, int reminderCount, @NonNull BubbleUtil.BubbleState defaultBubbleState); - void clearNotifications(@NonNull Context context); + boolean clearNotifications(@NonNull Context context); void clearReminder(@NonNull Context context); void addStickyThread(@NonNull ConversationId conversationId, long earliestTimestamp); void removeStickyThread(@NonNull ConversationId conversationId); diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java index 5b2fdad258..1caa2b58ac 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java @@ -80,7 +80,7 @@ private static class Version { public final String BACKGROUND = "background_connection"; public final String CALL_STATUS = "call_status"; public final String APP_ALERTS = "app_alerts"; - public final String ADDITIONAL_MESSAGE_NOTIFICATIONS = "additional_message_notifications"; + public static String ADDITIONAL_MESSAGE_NOTIFICATIONS = "additional_message_notifications"; private static volatile NotificationChannels instance; diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/OptimizedMessageNotifier.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/OptimizedMessageNotifier.java index a649d40ddb..bf35b0f944 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/OptimizedMessageNotifier.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/OptimizedMessageNotifier.java @@ -122,8 +122,8 @@ public void updateNotification(@NonNull Context context, @Nullable ConversationI } @Override - public void clearNotifications(@NonNull Context context) { - getNotifier().clearNotifications(context); + public boolean clearNotifications(@NonNull Context context) { + return getNotifier().clearNotifications(context); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/DefaultMessageNotifier.kt b/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/DefaultMessageNotifier.kt index fc7f37eeba..e7da3a9588 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/DefaultMessageNotifier.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/DefaultMessageNotifier.kt @@ -241,19 +241,23 @@ class DefaultMessageNotifier(context: Application) : MessageNotifier { if (Build.VERSION.SDK_INT >= 24) { val ids = state.conversations.filter { it.thread != visibleThread }.map { it.notificationId } + stickyThreads.map { (_, stickyThread) -> stickyThread.notificationId } - val notShown = ids - ServiceUtil.getNotificationManager(context).getDisplayedNotificationIds().getOrDefault(emptySet()) + val notShown = ids - getDisplayedNotificationIds(context) if (notShown.isNotEmpty()) { Log.e(TAG, "Notifications should be showing but are not for ${notShown.size} threads") } } } - override fun clearNotifications(context: Context) { - NotificationCancellationHelper.cancelAllMessageNotifications(context, stickyThreads.map { it.value.notificationId }.toSet()) + override fun clearNotifications(context: Context): Boolean { + val activeNotifications = getDisplayedNotificationIds(context) + NotificationCancellationHelper.cancelAllMessageNotifications(context) updateBadge(context, 0) clearReminderInternal(context) + return activeNotifications.isNotEmpty() } + private fun getDisplayedNotificationIds(context: Context) = ServiceUtil.getNotificationManager(context).getDisplayedNotificationIds().getOrDefault(emptySet()) + override fun clearReminder(context: Context) { // Intentionally left blank } diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/KeyCachingService.java b/app/src/main/java/org/thoughtcrime/securesms/service/KeyCachingService.java index 7a0d46f1ee..a0d52db376 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/KeyCachingService.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/KeyCachingService.java @@ -40,7 +40,6 @@ import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.migrations.ApplicationMigrations; -import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.notifications.NotificationChannels; import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.ServiceUtil; @@ -66,6 +65,8 @@ public class KeyCachingService extends Service { public static final String CLEAR_KEY_ACTION = BuildConfig.APPLICATION_ID + ".service.action.CLEAR_KEY"; public static final String LOCALE_CHANGE_EVENT = BuildConfig.APPLICATION_ID + ".service.action.LOCALE_CHANGE_EVENT"; + public static final String EXTRA_KEY_EXPIRED = "extra.key_expired"; + private DynamicLanguage dynamicLanguage = new DynamicLanguage(); private final IBinder binder = new KeySetBinder(); @@ -110,9 +111,9 @@ public int onStartCommand(Intent intent, int flags, int startId) { if (intent.getAction() != null) { switch (intent.getAction()) { - case CLEAR_KEY_ACTION: handleClearKey(); break; - case PASSPHRASE_EXPIRED_EVENT: handleClearKey(); break; - case LOCALE_CHANGE_EVENT: handleLocaleChanged(); break; + case CLEAR_KEY_ACTION -> handleClearKey(false); + case PASSPHRASE_EXPIRED_EVENT -> handleClearKey(true); + case LOCALE_CHANGE_EVENT -> handleLocaleChanged(); } } else { handleCacheKey(); @@ -165,8 +166,8 @@ private void handleCacheKey() { }); } - private void handleClearKey() { - Log.i(TAG, "handleClearKey"); + private void handleClearKey(boolean keyExpired) { + Log.d(TAG, "handleClearKey() keyExpired: " + keyExpired); cancelTimeout(); @@ -178,13 +179,12 @@ private void handleClearKey() { KeyCachingService.locking = true; - sendPackageBroadcast(CLEAR_KEY_EVENT); + Log.i(TAG, "Broadcasting " + CLEAR_KEY_EVENT); - SignalExecutors.BOUNDED.execute(() -> { - MessageNotifier messageNotifier = ApplicationDependencies.getMessageNotifier(); - messageNotifier.cancelDelayedNotifications(); - messageNotifier.clearNotifications(KeyCachingService.this); - }); + Intent intent = new Intent(CLEAR_KEY_EVENT); + intent.putExtra(EXTRA_KEY_EXPIRED, keyExpired); + intent.setPackage(getPackageName()); + sendBroadcast(intent, KEY_PERMISSION); } private void handleLocaleChanged() { @@ -252,18 +252,9 @@ private void foregroundService() { startForeground(SERVICE_RUNNING_ID, builder.build()); } - private void sendPackageBroadcast(String action) { - Log.i(TAG, "Broadcasting " + action); - - Intent intent = new Intent(action); - intent.setPackage(getApplicationContext().getPackageName()); - - sendBroadcast(intent, KEY_PERMISSION); - } - private PendingIntent buildLockIntent() { Intent intent = new Intent(this, KeyCachingService.class); - intent.setAction(PASSPHRASE_EXPIRED_EVENT); + intent.setAction(CLEAR_KEY_ACTION); return PendingIntent.getService(getApplicationContext(), 0, intent, getPendingIntentFlags()); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/WipeMemoryService.java b/app/src/main/java/org/thoughtcrime/securesms/service/WipeMemoryService.java index 696086c51b..17a23ff6d1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/WipeMemoryService.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/WipeMemoryService.java @@ -5,7 +5,6 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; -import android.os.Build; import android.os.PowerManager; import androidx.annotation.Nullable; @@ -16,8 +15,8 @@ import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.MainActivity; import org.thoughtcrime.securesms.R; +import org.thoughtcrime.securesms.gcm.FcmFetchManager; import org.thoughtcrime.securesms.jobs.ForegroundServiceUtil; -import org.thoughtcrime.securesms.jobs.UnableToStartException; import org.thoughtcrime.securesms.notifications.NotificationChannels; import org.thoughtcrime.securesms.util.ServiceUtil; import org.thoughtcrime.securesms.util.WakeLockUtil; @@ -64,20 +63,8 @@ public class WipeMemoryService extends IntentService { public static void run(Context context, boolean restartApp) { restart = restartApp; - startForegroundService(context); - } - - private static void startForegroundService(Context context) { Intent intent = new Intent(context, WipeMemoryService.class); - if (Build.VERSION.SDK_INT >= 26) { - try { - ForegroundServiceUtil.startWhenCapable(context, intent); - } catch (UnableToStartException e) { - Log.e(TAG, "Unable to start foreground service", e); - } - } else { - context.startService(intent); - } + ForegroundServiceUtil.startWhenCapableOrThrow(context, intent); } public WipeMemoryService() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java b/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java index 3db4c87768..bb3c9cc85a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java @@ -569,13 +569,6 @@ public static boolean callingFieldTrialAnyAddressPortsKillSwitch() { return getBoolean(ANY_ADDRESS_PORTS_KILL_SWITCH, false); } - /** - * Enable/disable for notification when we cannot fetch messages despite receiving an urgent push. - */ - public static boolean fcmMayHaveMessagesNotificationKillSwitch() { - return getBoolean(FCM_MAY_HAVE_MESSAGES_KILL_SWITCH, false); - } - public static boolean editMessageSending() { return getBoolean(EDIT_MESSAGE_SEND, false); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/SecurePreferenceManager.java b/app/src/main/java/org/thoughtcrime/securesms/util/SecurePreferenceManager.java index 6536a63f90..9f64c41ce9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/SecurePreferenceManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/SecurePreferenceManager.java @@ -29,6 +29,7 @@ private static SharedPreferences createSecurePreferences(Context context) { case TextSecurePreferences.THEME_PREF: case TextSecurePreferences.LANGUAGE_PREF: case TextSecurePreferences.PASSPHRASE_LOCK: + case TextSecurePreferences.PASSPHRASE_LOCK_NOTIFICATIONS: case TextSecurePreferences.BIOMETRIC_SCREEN_LOCK: case TextSecurePreferences.FIRST_INSTALL_VERSION: case TextSecurePreferences.SYSTEM_EMOJI_PREF: diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/TextSecurePreferences.java b/app/src/main/java/org/thoughtcrime/securesms/util/TextSecurePreferences.java index 7fef3fd5da..4518808187 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/TextSecurePreferences.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/TextSecurePreferences.java @@ -47,7 +47,6 @@ public class TextSecurePreferences { private static final String TAG = Log.tag(TextSecurePreferences.class); - public static final String CHANGE_PASSPHRASE_PREF = "pref_change_passphrase"; public static final String THEME_PREF = "pref_theme"; public static final String LANGUAGE_PREF = "pref_language"; @@ -109,10 +108,11 @@ public class TextSecurePreferences { public static final String TRANSFER = "pref_transfer"; - public static final String PASSPHRASE_LOCK = "pref_passphrase_lock"; - public static final String PASSPHRASE_LOCK_TIMEOUT = "pref_passphrase_lock_timeout"; - public static final String PASSPHRASE_LOCK_TRIGGER = "pref_passphrase_lock_trigger"; - public static final String BIOMETRIC_SCREEN_LOCK = "pref_biometric_screen_lock"; + public static final String PASSPHRASE_LOCK = "pref_passphrase_lock"; + public static final String PASSPHRASE_LOCK_TIMEOUT = "pref_passphrase_lock_timeout"; + public static final String PASSPHRASE_LOCK_TRIGGER = "pref_passphrase_lock_trigger"; + public static final String PASSPHRASE_LOCK_NOTIFICATIONS = "pref_passphrase_lock_notifications"; + public static final String BIOMETRIC_SCREEN_LOCK = "pref_biometric_screen_lock"; private static final String NETWORK_CONFIG_SEEN = "pref_network_config_seen"; @@ -220,6 +220,7 @@ public static void setGoogleMapType(Context context, String value) { UPDATE_APK_INCLUDE_BETA, BLOCK_UNKNOWN, BIOMETRIC_SCREEN_LOCK, + PASSPHRASE_LOCK_NOTIFICATIONS, }; private static final String[] stringSetPreferencesToBackupMolly = {PASSPHRASE_LOCK_TRIGGER}; @@ -372,6 +373,14 @@ public static long getPassphraseLockTimeout(@NonNull Context context) { return getLongPreference(context, PASSPHRASE_LOCK_TIMEOUT, 0); } + public static boolean isPassphraseLockNotificationsEnabled(@NonNull Context context) { + return getBooleanPreference(context, PASSPHRASE_LOCK_NOTIFICATIONS, true); + } + + public static void setPassphraseLockNotificationsEnabled(@NonNull Context context, boolean value) { + setBooleanPreference(context, PASSPHRASE_LOCK_NOTIFICATIONS, value); + } + public static void setHasSeenNetworkConfig(Context context, boolean value) { setBooleanPreference(context, NETWORK_CONFIG_SEEN, value); } diff --git a/app/src/main/res/values/strings2.xml b/app/src/main/res/values/strings2.xml index 146ea57be3..ade1580fc5 100644 --- a/app/src/main/res/values/strings2.xml +++ b/app/src/main/res/values/strings2.xml @@ -108,4 +108,8 @@ Timed out waiting for the primary device. Ready your device to scan the QR code, then try again Retry linking The provider has declined to send you a verification code, likely due to fraud prevention rules. + New activity while locked + Receive notifications for messages or missed calls when the app is locked. + Push notifications unavailable + Sorry, this feature requires push notifications delivered via FCM or UnifiedPush, which are currently unavailable. diff --git a/libfakegms/src/main/java/com/google/firebase/messaging/FirebaseMessagingService.java b/libfakegms/src/main/java/com/google/firebase/messaging/FirebaseMessagingService.java index 453fbfe975..54dd5f94c5 100644 --- a/libfakegms/src/main/java/com/google/firebase/messaging/FirebaseMessagingService.java +++ b/libfakegms/src/main/java/com/google/firebase/messaging/FirebaseMessagingService.java @@ -14,11 +14,11 @@ public IBinder onBind(Intent intent) { return null; } - public abstract void onMessageReceived(RemoteMessage remoteMessage); + public abstract void onMessageReceived(@NonNull RemoteMessage remoteMessage); public abstract void onDeletedMessages(); - public abstract void onNewToken(String token); + public abstract void onNewToken(@NonNull String token); public abstract void onMessageSent(@NonNull String s);