commit 9c39e6bdb79a92f8c3c76f1be90f6ef04a410968 Author: Hashik Donthineni HashikDonthineni@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>
tor-commits@lists.torproject.org