From 1b7007d4ef0101cd314b5b3b363905123adb565a Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Mon, 10 May 2021 14:41:37 -0300 Subject: [PATCH] Show notification while hotspot is active --- .../AndroidNotificationManagerImpl.java | 54 +++++++++++++++---- .../android/hotspot/AbstractTabsFragment.java | 7 ++- .../android/hotspot/HotspotActivity.java | 12 +++++ .../android/hotspot/HotspotIntroFragment.java | 1 + .../android/hotspot/HotspotViewModel.java | 21 +++++++- .../android/AndroidNotificationManager.java | 8 +++ briar-android/src/main/res/values/strings.xml | 2 + 7 files changed, 91 insertions(+), 14 deletions(-) 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 f7a175805..1cd973ab8 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 @@ -30,6 +30,7 @@ import org.briarproject.bramble.util.StringUtils; import org.briarproject.briar.R; import org.briarproject.briar.android.conversation.ConversationActivity; import org.briarproject.briar.android.forum.ForumActivity; +import org.briarproject.briar.android.hotspot.HotspotActivity; import org.briarproject.briar.android.login.SignInReminderReceiver; import org.briarproject.briar.android.navdrawer.NavDrawerActivity; import org.briarproject.briar.android.privategroup.conversation.GroupActivity; @@ -63,9 +64,11 @@ import static android.app.Notification.DEFAULT_SOUND; import static android.app.Notification.DEFAULT_VIBRATE; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.IMPORTANCE_LOW; +import static android.app.PendingIntent.getActivity; import static android.content.Context.NOTIFICATION_SERVICE; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; +import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP; import static android.os.Build.VERSION.SDK_INT; import static androidx.core.app.NotificationCompat.CATEGORY_MESSAGE; import static androidx.core.app.NotificationCompat.CATEGORY_SERVICE; @@ -274,7 +277,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager, b.setWhen(0); // Don't show the time b.setOngoing(true); Intent i = new Intent(appContext, SplashScreenActivity.class); - b.setContentIntent(PendingIntent.getActivity(appContext, 0, i, 0)); + b.setContentIntent(getActivity(appContext, 0, i, 0)); if (SDK_INT >= 21) { b.setCategory(CATEGORY_SERVICE); b.setVisibility(VISIBILITY_SECRET); @@ -619,13 +622,11 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager, public void showSignInNotification() { if (blockSignInReminder) return; if (SDK_INT >= 26) { - NotificationChannel channel = - new NotificationChannel(REMINDER_CHANNEL_ID, appContext - .getString( - R.string.reminder_notification_channel_title), - IMPORTANCE_LOW); - channel.setLockscreenVisibility( - NotificationCompat.VISIBILITY_SECRET); + NotificationChannel channel = new NotificationChannel( + REMINDER_CHANNEL_ID, appContext + .getString(R.string.reminder_notification_channel_title), + IMPORTANCE_LOW); + channel.setLockscreenVisibility(VISIBILITY_SECRET); notificationManager.createNotificationChannel(channel); } @@ -652,7 +653,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager, Intent i = new Intent(appContext, SplashScreenActivity.class); i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP); - b.setContentIntent(PendingIntent.getActivity(appContext, 0, i, 0)); + b.setContentIntent(getActivity(appContext, 0, i, 0)); notificationManager.notify(REMINDER_NOTIFICATION_ID, b.build()); } @@ -720,4 +721,39 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager, public void unblockAllBlogPostNotifications() { androidExecutor.runOnUiThread((Runnable) () -> blockBlogs = false); } + + @Override + public void showHotspotNotification() { + if (SDK_INT >= 26) { + String channelTitle = appContext + .getString(R.string.hotspot_notification_channel_title); + NotificationChannel channel = new NotificationChannel( + HOTSPOT_CHANNEL_ID, channelTitle, IMPORTANCE_LOW); + channel.setLockscreenVisibility(VISIBILITY_SECRET); + notificationManager.createNotificationChannel(channel); + } + BriarNotificationBuilder b = + new BriarNotificationBuilder(appContext, HOTSPOT_CHANNEL_ID); + b.setSmallIcon(R.drawable.ic_wifi_tethering); + b.setColorRes(R.color.briar_brand_green); + b.setContentTitle( + appContext.getText(R.string.hotspot_notification_title)); + b.setNotificationCategory(CATEGORY_SERVICE); + b.setOngoing(true); + b.setShowWhen(true); + + String actionTitle = + appContext.getString(R.string.hotspot_button_stop_sharing); + Intent i = new Intent(appContext, HotspotActivity.class); + i.addFlags(FLAG_ACTIVITY_SINGLE_TOP); + i.setAction(ACTION_STOP_HOTSPOT); + PendingIntent actionIntent = getActivity(appContext, 0, i, 0); + b.addAction(R.drawable.ic_portable_wifi_off, actionTitle, actionIntent); + notificationManager.notify(HOTSPOT_NOTIFICATION_ID, b.build()); + } + + @Override + public void clearHotspotNotification() { + notificationManager.cancel(HOTSPOT_NOTIFICATION_ID); + } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/hotspot/AbstractTabsFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/hotspot/AbstractTabsFragment.java index 982d538b9..2056f0002 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/hotspot/AbstractTabsFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/hotspot/AbstractTabsFragment.java @@ -9,7 +9,6 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.Button; -import android.widget.Toast; import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayoutMediator; @@ -28,7 +27,7 @@ import androidx.lifecycle.ViewModelProvider; import androidx.viewpager2.adapter.FragmentStateAdapter; import androidx.viewpager2.widget.ViewPager2; -import static android.widget.Toast.LENGTH_SHORT; +import static androidx.core.app.ActivityCompat.finishAfterTransition; import static org.briarproject.briar.android.AppModule.getAndroidComponent; @MethodsNotNullByDefault @@ -81,8 +80,8 @@ public abstract class AbstractTabsFragment extends Fragment { stopButton = view.findViewById(R.id.stopButton); stopButton.setOnClickListener(v -> { - Toast.makeText(requireContext(), "Not yet implemented", - LENGTH_SHORT).show(); + // also clears hotspot + finishAfterTransition(requireActivity()); }); connectedButton = view.findViewById(R.id.connectedButton); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/hotspot/HotspotActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/hotspot/HotspotActivity.java index 28d643d9e..cde183485 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/hotspot/HotspotActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/hotspot/HotspotActivity.java @@ -1,5 +1,6 @@ package org.briarproject.briar.android.hotspot; +import android.content.Intent; import android.os.Bundle; import android.view.MenuItem; @@ -16,6 +17,8 @@ import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBar; import androidx.lifecycle.ViewModelProvider; +import static org.briarproject.briar.api.android.AndroidNotificationManager.ACTION_STOP_HOTSPOT; + @MethodsNotNullByDefault @ParametersNotNullByDefault public class HotspotActivity extends BriarActivity { @@ -61,4 +64,13 @@ public class HotspotActivity extends BriarActivity { return super.onOptionsItemSelected(item); } + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + if (ACTION_STOP_HOTSPOT.equals(intent.getAction())) { + // also closes hotspot + supportFinishAfterTransition(); + } + } + } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/hotspot/HotspotIntroFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/hotspot/HotspotIntroFragment.java index 58ce3d323..ab32ac6c6 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/hotspot/HotspotIntroFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/hotspot/HotspotIntroFragment.java @@ -61,6 +61,7 @@ public class HotspotIntroFragment extends Fragment { progressTextView.setVisibility(VISIBLE); // TODO remove below, tell viewModel to start hotspot instead v.postDelayed(() -> { + viewModel.startHotspot(); getParentFragmentManager().beginTransaction() .setCustomAnimations(R.anim.step_next_in, R.anim.step_previous_out, diff --git a/briar-android/src/main/java/org/briarproject/briar/android/hotspot/HotspotViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/hotspot/HotspotViewModel.java index 60b006377..4dfc3c733 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/hotspot/HotspotViewModel.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/hotspot/HotspotViewModel.java @@ -8,6 +8,7 @@ import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.briar.android.viewmodel.DbViewModel; +import org.briarproject.briar.api.android.AndroidNotificationManager; import java.util.concurrent.Executor; @@ -16,13 +17,31 @@ import javax.inject.Inject; @NotNullByDefault class HotspotViewModel extends DbViewModel { + private final AndroidNotificationManager notificationManager; + @Inject HotspotViewModel(Application application, @DatabaseExecutor Executor dbExecutor, LifecycleManager lifecycleManager, TransactionManager db, - AndroidExecutor androidExecutor) { + AndroidExecutor androidExecutor, + AndroidNotificationManager notificationManager) { super(application, dbExecutor, lifecycleManager, db, androidExecutor); + this.notificationManager = notificationManager; + } + + void startHotspot() { + notificationManager.showHotspotNotification(); + } + + private void stopHotspot() { + notificationManager.clearHotspotNotification(); + } + + @Override + protected void onCleared() { + super.onCleared(); + stopHotspot(); } // TODO copy actual code from Offline Hotspot app 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 765425720..908b27322 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 @@ -31,6 +31,7 @@ public interface AndroidNotificationManager { int FORUM_POST_NOTIFICATION_ID = 6; int BLOG_POST_NOTIFICATION_ID = 7; int CONTACT_ADDED_NOTIFICATION_ID = 8; + int HOTSPOT_NOTIFICATION_ID = 9; // Channel IDs String CONTACT_CHANNEL_ID = "contacts"; @@ -42,12 +43,15 @@ public interface AndroidNotificationManager { String ONGOING_CHANNEL_OLD_ID = "zForegroundService"; String ONGOING_CHANNEL_ID = "zForegroundService2"; String REMINDER_CHANNEL_ID = "zSignInReminder"; + String HOTSPOT_CHANNEL_ID = "zHotspot"; + // This channel is no longer used - keep the ID so we can remove the // channel from existing installations String FAILURE_CHANNEL_ID = "zStartupFailure"; // Actions for pending intents String ACTION_DISMISS_REMINDER = "dismissReminder"; + String ACTION_STOP_HOTSPOT = "stopHotspot"; Notification getForegroundNotification(); @@ -96,4 +100,8 @@ public interface AndroidNotificationManager { void blockAllBlogPostNotifications(); void unblockAllBlogPostNotifications(); + + void showHotspotNotification(); + + void clearHotspotNotification(); } diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml index 616909ba7..763954acb 100644 --- a/briar-android/src/main/res/values/strings.xml +++ b/briar-android/src/main/res/values/strings.xml @@ -699,6 +699,8 @@ Start sharing Stop sharing Setting up hotspot… + Wi-Fi hotspot + Sharing Briar offline Confirm connection Manual To download the app on another phone, please connect to this Wi-Fi network: