From 633f5a8bd7c8059552f91216aa383df675d720e8 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Wed, 1 Aug 2018 16:42:08 -0300 Subject: [PATCH] Adapt foreground notification when locked and show LOCK button --- .../bramble/account/BriarAccountManager.java | 12 +++- .../AndroidNotificationManagerImpl.java | 66 +++++++++++++++++-- .../briar/android/BriarService.java | 28 ++------ .../briar/android/login/UnlockActivity.java | 9 ++- .../android/navdrawer/NavDrawerActivity.java | 4 ++ .../android/AndroidNotificationManager.java | 7 ++ briar-android/src/main/res/values/strings.xml | 2 + 7 files changed, 101 insertions(+), 27 deletions(-) diff --git a/briar-android/src/main/java/org/briarproject/bramble/account/BriarAccountManager.java b/briar-android/src/main/java/org/briarproject/bramble/account/BriarAccountManager.java index eb1e2faaa..00bc97430 100644 --- a/briar-android/src/main/java/org/briarproject/bramble/account/BriarAccountManager.java +++ b/briar-android/src/main/java/org/briarproject/bramble/account/BriarAccountManager.java @@ -9,16 +9,26 @@ import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.briar.R; import org.briarproject.briar.android.Localizer; import org.briarproject.briar.android.util.UiUtils; +import org.briarproject.briar.api.android.AndroidNotificationManager; import javax.inject.Inject; class BriarAccountManager extends AndroidAccountManager { + private final AndroidNotificationManager notificationManager; + @Inject BriarAccountManager(DatabaseConfig databaseConfig, CryptoComponent crypto, IdentityManager identityManager, SharedPreferences prefs, - Application app) { + Application app, AndroidNotificationManager notificationManager) { super(databaseConfig, crypto, identityManager, prefs, app); + this.notificationManager = notificationManager; + } + + @Override + public void setLocked(boolean locked) { + super.setLocked(locked); + notificationManager.updateForegroundNotification(true, locked); } @Override diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AndroidNotificationManagerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/AndroidNotificationManagerImpl.java index d3ee12a94..8bedb0173 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/AndroidNotificationManagerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/AndroidNotificationManagerImpl.java @@ -2,6 +2,7 @@ package org.briarproject.briar.android; import android.annotation.TargetApi; import android.app.Application; +import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; @@ -12,7 +13,6 @@ import android.support.annotation.StringRes; import android.support.annotation.UiThread; import android.support.v4.app.NotificationCompat; import android.support.v4.app.TaskStackBuilder; -import android.support.v4.content.ContextCompat; import org.briarproject.bramble.api.Multiset; import org.briarproject.bramble.api.contact.ContactId; @@ -35,6 +35,7 @@ import org.briarproject.briar.R; import org.briarproject.briar.android.contact.ConversationActivity; import org.briarproject.briar.android.forum.ForumActivity; import org.briarproject.briar.android.login.SignInReminderReceiver; +import org.briarproject.briar.android.login.UnlockActivity; import org.briarproject.briar.android.navdrawer.NavDrawerActivity; import org.briarproject.briar.android.privategroup.conversation.GroupActivity; import org.briarproject.briar.android.splash.SplashScreenActivity; @@ -65,7 +66,6 @@ import javax.inject.Inject; import static android.app.Notification.DEFAULT_LIGHTS; import static android.app.Notification.DEFAULT_SOUND; import static android.app.Notification.DEFAULT_VIBRATE; -import static android.app.Notification.VISIBILITY_SECRET; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.content.Context.NOTIFICATION_SERVICE; @@ -73,8 +73,12 @@ import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.os.Build.VERSION.SDK_INT; import static android.support.v4.app.NotificationCompat.CATEGORY_MESSAGE; +import static android.support.v4.app.NotificationCompat.CATEGORY_SERVICE; import static android.support.v4.app.NotificationCompat.CATEGORY_SOCIAL; import static android.support.v4.app.NotificationCompat.PRIORITY_LOW; +import static android.support.v4.app.NotificationCompat.PRIORITY_MIN; +import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET; +import static android.support.v4.content.ContextCompat.getColor; import static java.util.logging.Level.WARNING; import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID; @@ -174,7 +178,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager, nc.enableVibration(true); nc.enableLights(true); nc.setLightColor( - ContextCompat.getColor(appContext, R.color.briar_green_light)); + getColor(appContext, R.color.briar_green_light)); notificationManager.createNotificationChannel(nc); } @@ -271,6 +275,60 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager, }); } + @UiThread + @Override + public Notification getForegroundNotification() { + return getForegroundNotification(false, false); + } + + @UiThread + private Notification getForegroundNotification(boolean lockable, + boolean locked) { + int title = locked ? R.string.lock_is_locked : + R.string.ongoing_notification_title; + int text = locked ? R.string.lock_tap_to_unlock : + R.string.ongoing_notification_text; + // Ongoing foreground notification that shows BriarService is running + NotificationCompat.Builder b = + new NotificationCompat.Builder(appContext, ONGOING_CHANNEL_ID); + b.setSmallIcon(R.drawable.notification_ongoing); + b.setColor(getColor(appContext, R.color.briar_primary)); + b.setContentTitle(appContext.getText(title)); + b.setContentText(appContext.getText(text)); + b.setWhen(0); // Don't show the time + b.setOngoing(true); + Intent i = new Intent(appContext, NavDrawerActivity.class); + i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP); + b.setContentIntent(PendingIntent.getActivity(appContext, 0, i, 0)); + if (SDK_INT >= 21) { + b.setCategory(CATEGORY_SERVICE); + b.setVisibility(VISIBILITY_SECRET); + } + b.setPriority(PRIORITY_MIN); + + // Add a 'Lock' action + if (lockable && !locked) { + String actionTitle = appContext.getString(R.string.lock_lock); + Intent i1 = new Intent(appContext, UnlockActivity.class); + i1.setAction(ACTION_LOCK); + PendingIntent actionIntent = + PendingIntent.getActivity(appContext, 0, i1, 0); + b.addAction(R.drawable.startup_lock, actionTitle, actionIntent); + } + return b.build(); + } + + @UiThread + @Override + public void updateForegroundNotification(boolean lockable, + boolean locked) { + NotificationManager nm = (NotificationManager) appContext + .getSystemService(NOTIFICATION_SERVICE); + assert nm != null; + Notification n = getForegroundNotification(lockable, locked); + nm.notify(ONGOING_NOTIFICATION_ID, n); + } + private void showContactNotification(ContactId c) { androidExecutor.runOnUiThread(() -> { if (blockContacts) return; @@ -636,7 +694,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager, NotificationCompat.Builder b = new NotificationCompat.Builder(appContext, REMINDER_CHANNEL_ID); b.setSmallIcon(R.drawable.ic_signout); - b.setColor(ContextCompat.getColor(appContext, R.color.briar_primary)); + b.setColor(getColor(appContext, R.color.briar_primary)); b.setContentTitle( appContext.getText(R.string.reminder_notification_title)); b.setContentText( diff --git a/briar-android/src/main/java/org/briarproject/briar/android/BriarService.java b/briar-android/src/main/java/org/briarproject/briar/android/BriarService.java index 022fa3195..7aa0371fe 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/BriarService.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/BriarService.java @@ -2,6 +2,7 @@ package org.briarproject.briar.android; import android.app.ActivityManager; import android.app.ActivityManager.RunningAppProcessInfo; +import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; @@ -15,7 +16,6 @@ import android.content.ServiceConnection; import android.os.Binder; import android.os.IBinder; import android.support.v4.app.NotificationCompat; -import android.support.v4.content.ContextCompat; import org.briarproject.bramble.api.account.AccountManager; import org.briarproject.bramble.api.crypto.SecretKey; @@ -25,6 +25,7 @@ import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.briar.R; import org.briarproject.briar.android.logout.HideUiActivity; import org.briarproject.briar.android.navdrawer.NavDrawerActivity; +import org.briarproject.briar.api.android.AndroidNotificationManager; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; @@ -44,8 +45,6 @@ import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION; import static android.os.Build.VERSION.SDK_INT; -import static android.support.v4.app.NotificationCompat.CATEGORY_SERVICE; -import static android.support.v4.app.NotificationCompat.PRIORITY_MIN; import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; @@ -74,6 +73,8 @@ public class BriarService extends Service { @Nullable private BroadcastReceiver receiver = null; + @Inject + AndroidNotificationManager notificationManager; @Inject AccountManager accountManager; @@ -121,24 +122,9 @@ public class BriarService extends Service { failureChannel.setLockscreenVisibility(VISIBILITY_SECRET); nm.createNotificationChannel(failureChannel); } - // Show an ongoing notification that the service is running - NotificationCompat.Builder b = - new NotificationCompat.Builder(this, ONGOING_CHANNEL_ID); - b.setSmallIcon(R.drawable.notification_ongoing); - b.setColor(ContextCompat.getColor(this, R.color.briar_primary)); - b.setContentTitle(getText(R.string.ongoing_notification_title)); - b.setContentText(getText(R.string.ongoing_notification_text)); - b.setWhen(0); // Don't show the time - b.setOngoing(true); - Intent i = new Intent(this, NavDrawerActivity.class); - i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP); - b.setContentIntent(PendingIntent.getActivity(this, 0, i, 0)); - if (SDK_INT >= 21) { - b.setCategory(CATEGORY_SERVICE); - b.setVisibility(VISIBILITY_SECRET); - } - b.setPriority(PRIORITY_MIN); - startForeground(ONGOING_NOTIFICATION_ID, b.build()); + Notification foregroundNotification = + notificationManager.getForegroundNotification(); + startForeground(ONGOING_NOTIFICATION_ID, foregroundNotification); // Start the services in a background thread new Thread(() -> { StartResult result = lifecycleManager.startServices(dbKey); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/UnlockActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/login/UnlockActivity.java index bc2129ab3..16ff7d1fa 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/login/UnlockActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/login/UnlockActivity.java @@ -21,6 +21,7 @@ import java.util.logging.Logger; import javax.inject.Inject; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_UNLOCK; +import static org.briarproject.briar.api.android.AndroidNotificationManager.ACTION_LOCK; @RequiresApi(21) @MethodsNotNullByDefault @@ -44,7 +45,13 @@ public class UnlockActivity extends BaseActivity { Button button = findViewById(R.id.unlock); button.setOnClickListener(view -> requestKeyguardUnlock()); - requestKeyguardUnlock(); + + Intent intent = getIntent(); + if (intent != null && ACTION_LOCK.equals(intent.getAction())) { + accountManager.setLocked(true); + } else { + requestKeyguardUnlock(); + } } @Override diff --git a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java index d75ee60ee..6750cba71 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java @@ -42,6 +42,7 @@ import org.briarproject.briar.android.logout.SignOutFragment; import org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning; import org.briarproject.briar.android.privategroup.list.GroupListFragment; import org.briarproject.briar.android.settings.SettingsActivity; +import org.briarproject.briar.api.android.AndroidNotificationManager; import java.util.ArrayList; import java.util.List; @@ -81,6 +82,8 @@ public class NavDrawerActivity extends BriarActivity implements NavDrawerController controller; @Inject LifecycleManager lifecycleManager; + @Inject + AndroidNotificationManager notificationManager; private DrawerLayout drawerLayout; private NavigationView navigation; @@ -320,6 +323,7 @@ public class NavDrawerActivity extends BriarActivity implements private void setLockVisible(boolean visible) { MenuItem item = navigation.getMenu().findItem(R.id.nav_btn_lock); if (item != null) item.setVisible(visible); + notificationManager.updateForegroundNotification(visible, false); } @SuppressWarnings("ConstantConditions") diff --git a/briar-android/src/main/java/org/briarproject/briar/api/android/AndroidNotificationManager.java b/briar-android/src/main/java/org/briarproject/briar/api/android/AndroidNotificationManager.java index 5de4b066f..c1cbe8b61 100644 --- a/briar-android/src/main/java/org/briarproject/briar/api/android/AndroidNotificationManager.java +++ b/briar-android/src/main/java/org/briarproject/briar/api/android/AndroidNotificationManager.java @@ -1,5 +1,7 @@ package org.briarproject.briar.api.android; +import android.app.Notification; + import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.sync.GroupId; @@ -51,6 +53,11 @@ public interface AndroidNotificationManager { // Actions for pending intents String ACTION_DISMISS_REMINDER = "dismissReminder"; + String ACTION_LOCK = "lock"; + + Notification getForegroundNotification(); + + void updateForegroundNotification(boolean lockable, boolean locked); void clearContactNotification(ContactId c); diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml index 5b2f13a03..1a84c847f 100644 --- a/briar-android/src/main/res/values/strings.xml +++ b/briar-android/src/main/res/values/strings.xml @@ -453,5 +453,7 @@ Briar is locked Tap to unlock Only available on Android 5 or newer and when a system screen lock is set + + Lock