[tor-commits] [snowflake-mobile/master] Added notification and notification channel

cohosh at torproject.org cohosh at torproject.org
Fri Jun 5 17:49:16 UTC 2020


commit 9c39e6bdb79a92f8c3c76f1be90f6ef04a410968
Author: Hashik Donthineni <HashikDonthineni at gmail.com>
Date:   Fri Jun 5 03:38:03 2020 +0530

    Added notification and notification channel
---
 .../org/torproject/snowflake/MainActivity.java     | 31 ++++++++++
 .../torproject/snowflake/MyPersistentService.java  | 68 ++++++++++++++++++++++
 .../constants/ForegroundServiceConstants.java      |  4 ++
 app/src/main/res/values/strings.xml                |  5 +-
 4 files changed, 107 insertions(+), 1 deletion(-)

diff --git a/app/src/main/java/org/torproject/snowflake/MainActivity.java b/app/src/main/java/org/torproject/snowflake/MainActivity.java
index 188eb57..b4ebcd8 100644
--- a/app/src/main/java/org/torproject/snowflake/MainActivity.java
+++ b/app/src/main/java/org/torproject/snowflake/MainActivity.java
@@ -1,7 +1,11 @@
 package org.torproject.snowflake;
 
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.graphics.Color;
 import android.os.Build;
 import android.os.Bundle;
 import android.widget.Button;
@@ -21,8 +25,16 @@ public class MainActivity extends AppCompatActivity {
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
+
         sharedPreferences = getSharedPreferences(getString(R.string.sharedpreference_file), MODE_PRIVATE);
 
+        //Creating notification channel if app is being run for the first time
+        if (sharedPreferences.getBoolean(getString(R.string.initial_run_boolean), true)) {
+            createNotificationChannel();
+            //Setting initial run to false.
+            sharedPreferences.edit().putBoolean(getString(R.string.initial_run_boolean), false).apply();
+        }
+
         Button startButton = findViewById(R.id.start_button);
         startButton.setOnClickListener(v -> {
             if (isServiceRunning()) //Toggling the service.
@@ -57,4 +69,23 @@ public class MainActivity extends AppCompatActivity {
     private boolean isServiceRunning() {
         return sharedPreferences.getBoolean(getString(R.string.is_service_running_bool), false);
     }
+
+    /**
+     * Used to create a new notification channel if app is started for the first time on a device.
+     */
+    private void createNotificationChannel() {
+        //Versions after Android Oreo mandates the use of notification channels.
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+
+            NotificationChannel channel = new NotificationChannel(ForegroundServiceConstants.NOTIFICATION_CHANNEL_ID,
+                    getString(R.string.not_channel_name),
+                    NotificationManager.IMPORTANCE_HIGH);
+            channel.setDescription(getString(R.string.not_channel_desc));
+            channel.enableLights(true);
+            channel.setLightColor(Color.RED);
+            channel.setSound(null, null);
+            notificationManager.createNotificationChannel(channel);
+        }
+    }
 }
diff --git a/app/src/main/java/org/torproject/snowflake/MyPersistentService.java b/app/src/main/java/org/torproject/snowflake/MyPersistentService.java
index cc4806d..5d6c03e 100644
--- a/app/src/main/java/org/torproject/snowflake/MyPersistentService.java
+++ b/app/src/main/java/org/torproject/snowflake/MyPersistentService.java
@@ -1,16 +1,84 @@
 package org.torproject.snowflake;
 
+import android.app.Notification;
+import android.app.PendingIntent;
 import android.app.Service;
 import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Build;
 import android.os.IBinder;
+import android.util.Log;
 
 import androidx.annotation.Nullable;
 
+import org.torproject.snowflake.constants.ForegroundServiceConstants;
+
 //Main foreground service to handle network calls and to relay the data in the back ground.
 public class MyPersistentService extends Service {
+    private static final String TAG = "MyPersistentService";
+    private SharedPreferences sharedPreferences;
+
     @Nullable
     @Override
     public IBinder onBind(Intent intent) {
         return null;
     }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        Log.d(TAG, "onCreate: Service Created");
+
+        sharedPreferences = getSharedPreferences(getString(R.string.sharedpreference_file), MODE_PRIVATE);
+        sharedPreferencesHelper(ForegroundServiceConstants.SERVICE_RUNNING);
+        Notification notification = createPersistentNotification(false, null);
+        startForeground(ForegroundServiceConstants.DEF_NOTIFICATION_ID, notification);
+    }
+
+    private void sharedPreferencesHelper(final int setState) {
+        Log.d(TAG, "sharedPreferencesHelper: Setting Shared Preference Running To: " + setState);
+        SharedPreferences.Editor editor = sharedPreferences.edit();
+
+        if (setState == ForegroundServiceConstants.SERVICE_RUNNING) {
+            editor.putBoolean(getString(R.string.is_service_running_bool), true);
+        } else {
+            editor.putBoolean(getString(R.string.is_service_running_bool), false);
+        }
+        editor.apply();
+    }
+
+    /**
+     * Create a new persistent notification
+     *
+     * @param isUpdate is this new notification an update to current one?
+     * @param update String that is to be updated will current. Send "null" if isUpdate is false.
+     * @return New Notification with given parameters.
+     */
+    private Notification createPersistentNotification(final boolean isUpdate, final String update) {
+        Intent persistentNotIntent = new Intent(this, MyPersistentService.class);
+        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, persistentNotIntent, 0);
+
+        Notification.Builder builder;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+            builder = new Notification.Builder(this, ForegroundServiceConstants.NOTIFICATION_CHANNEL_ID);
+        else
+            builder = new Notification.Builder(this);
+
+        builder
+                .setContentTitle("Snowflake Service")
+                .setContentIntent(pendingIntent)
+                .setSmallIcon(R.mipmap.ic_launcher)
+                .setPriority(Notification.PRIORITY_HIGH); // Android 26 and above needs priority.
+
+        //If it's a notification update. Set the text to updated notification.
+        if (isUpdate) {
+            builder.setContentText(update)
+                    .setTicker(update);
+        } else {
+            builder.setContentText("Snowflake Proxy Running")
+                    .setTicker("Snowflake Proxy Running");
+        }
+
+        return builder.build();
+    }
 }
diff --git a/app/src/main/java/org/torproject/snowflake/constants/ForegroundServiceConstants.java b/app/src/main/java/org/torproject/snowflake/constants/ForegroundServiceConstants.java
index b446f0e..6438b6c 100644
--- a/app/src/main/java/org/torproject/snowflake/constants/ForegroundServiceConstants.java
+++ b/app/src/main/java/org/torproject/snowflake/constants/ForegroundServiceConstants.java
@@ -7,4 +7,8 @@ public class ForegroundServiceConstants {
     //Shared Preferences State
     public static final int SERVICE_RUNNING = 1;
     public static final int SERVICE_STOPPED = 0;
+
+    //Notification Constants
+    public static final String NOTIFICATION_CHANNEL_ID = "SNOWFLAKE_ENDLESS_SERVICE";
+    public static final int DEF_NOTIFICATION_ID = 555;
 }
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 85551fb..7448d1e 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,5 +1,8 @@
 <resources>
-    <string name="app_name">Snowflake</string>
+    <string name="app_name">TestFlake</string>
     <string name="sharedpreference_file">org.torproject.snowflake.snowflake_preferences</string>
     <string name="is_service_running_bool">is_service_running</string>
+    <string name="not_channel_desc">This Channel should not be muted. The Android system will consider Snowflake not import and will kill the service if it\'s muted.</string>
+    <string name="initial_run_boolean">initial_run</string>
+    <string name="not_channel_name">Snowflake Service</string>
 </resources>





More information about the tor-commits mailing list