From 6d8dcc8fe7ba26708e2151c0d4cd5927263795e6 Mon Sep 17 00:00:00 2001
From: Alex Ning <chineseperson5@gmail.com>
Date: Wed, 9 Sep 2020 15:26:02 +0800
Subject: Add PullNotificationAlarmReceiver, another implementation of pull
 notifications. Fix a bug in NotificationPreferenceFragment.

---
 app/src/main/AndroidManifest.xml                   |   4 +
 .../infinityforreddit/Activity/MainActivity.java   |   6 ++
 .../infinityforreddit/AppComponent.java            |   2 +
 .../infinityforreddit/NotificationUtils.java       |  88 -----------------
 .../PullNotificationAlarmReceiver.java             | 106 +++++++++++++++++++++
 .../infinityforreddit/PullNotificationWorker.java  |  17 +++-
 .../Service/DownloadMediaService.java              |   2 +-
 .../Service/DownloadRedditVideoService.java        |   2 +-
 .../Service/SubmitPostService.java                 |   2 +-
 .../DownloadLocationPreferenceFragment.java        |   5 +-
 .../Settings/NotificationPreferenceFragment.java   |   5 +-
 .../infinityforreddit/Utils/NotificationUtils.java |  91 ++++++++++++++++++
 12 files changed, 236 insertions(+), 94 deletions(-)
 delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/NotificationUtils.java
 create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationAlarmReceiver.java
 create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Utils/NotificationUtils.java

(limited to 'app/src/main')

diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 684a33d2..fd4695f7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -14,6 +14,8 @@
 
     <uses-permission-sdk-23 android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+
     <application
         android:name=".Infinity"
         android:allowBackup="true"
@@ -345,6 +347,8 @@
             android:name=".Service.SubmitPostService"
             android:enabled="true"
             android:exported="false" />
+
+        <receiver android:process=":remote" android:name=".PullNotificationAlarmReceiver" />
     </application>
 
 </manifest>
\ No newline at end of file
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java
index d86168ee..d8904a69 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java
@@ -335,6 +335,7 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb
                         }
 
                         if (enableNotification) {
+                            //PullNotificationAlarmReceiver.setNotificationAlarm(this, notificationInterval);
                             Constraints constraints = new Constraints.Builder()
                                     .setRequiredNetworkType(NetworkType.CONNECTED)
                                     .build();
@@ -348,6 +349,7 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb
                             workManager.enqueueUniquePeriodicWork(PullNotificationWorker.UNIQUE_WORKER_NAME,
                                     ExistingPeriodicWorkPolicy.KEEP, pullNotificationRequest);
                         } else {
+                            //PullNotificationAlarmReceiver.cancelAlarm(this);
                             workManager.cancelUniqueWork(PullNotificationWorker.UNIQUE_WORKER_NAME);
                         }
 
@@ -361,6 +363,7 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb
                     mKarma = account.getKarma();
 
                     if (enableNotification) {
+                        //PullNotificationAlarmReceiver.setNotificationAlarm(this, notificationInterval);
                         Constraints constraints = new Constraints.Builder()
                                 .setRequiredNetworkType(NetworkType.CONNECTED)
                                 .build();
@@ -374,6 +377,7 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb
                         workManager.enqueueUniquePeriodicWork(PullNotificationWorker.UNIQUE_WORKER_NAME,
                                 ExistingPeriodicWorkPolicy.KEEP, pullNotificationRequest);
                     } else {
+                        //PullNotificationAlarmReceiver.cancelAlarm(this);
                         workManager.cancelUniqueWork(PullNotificationWorker.UNIQUE_WORKER_NAME);
                     }
 
@@ -391,6 +395,7 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb
                 }
 
                 if (enableNotification) {
+                    //PullNotificationAlarmReceiver.setNotificationAlarm(this, notificationInterval);
                     Constraints constraints = new Constraints.Builder()
                             .setRequiredNetworkType(NetworkType.CONNECTED)
                             .build();
@@ -404,6 +409,7 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb
                     workManager.enqueueUniquePeriodicWork(PullNotificationWorker.UNIQUE_WORKER_NAME,
                             ExistingPeriodicWorkPolicy.KEEP, pullNotificationRequest);
                 } else {
+                    //PullNotificationAlarmReceiver.cancelAlarm(this);
                     workManager.cancelUniqueWork(PullNotificationWorker.UNIQUE_WORKER_NAME);
                 }
 
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java
index 34695608..606d9d2c 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java
@@ -197,4 +197,6 @@ public interface AppComponent {
     void inject(DownloadLocationPreferenceFragment downloadLocationPreferenceFragment);
 
     void inject(SubmitCrosspostActivity submitCrosspostActivity);
+
+    void inject(PullNotificationAlarmReceiver pullNotificationAlarmReceiver);
 }
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/NotificationUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/NotificationUtils.java
deleted file mode 100644
index c0935772..00000000
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/NotificationUtils.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package ml.docilealligator.infinityforreddit;
-
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.content.Context;
-
-import androidx.core.app.NotificationCompat;
-import androidx.core.app.NotificationManagerCompat;
-
-public class NotificationUtils {
-    public static final String CHANNEL_SUBMIT_POST = "Submit Post";
-    static final String CHANNEL_ID_NEW_MESSAGES = "new_messages";
-    static final String CHANNEL_NEW_MESSAGES = "New Messages";
-    public static final String CHANNEL_ID_DOWNLOAD_REDDIT_VIDEO = "download_reddit_video";
-    public static final String CHANNEL_DOWNLOAD_REDDIT_VIDEO = "Download Reddit Video";
-    public static final String CHANNEL_ID_DOWNLOAD_VIDEO = "download_video";
-    public static final String CHANNEL_DOWNLOAD_VIDEO = "Download Video";
-    public static final String CHANNEL_ID_DOWNLOAD_IMAGE = "download_image";
-    public static final String CHANNEL_DOWNLOAD_IMAGE = "Download Image";
-    public static final String CHANNEL_ID_DOWNLOAD_GIF = "download_gif";
-    public static final String CHANNEL_DOWNLOAD_GIF = "Download Gif";
-    public static final int SUBMIT_POST_SERVICE_NOTIFICATION_ID = 10000;
-    public static final int DOWNLOAD_REDDIT_VIDEO_NOTIFICATION_ID = 20000;
-    public static final int DOWNLOAD_VIDEO_NOTIFICATION_ID = 30000;
-    public static final int DOWNLOAD_IMAGE_NOTIFICATION_ID = 40000;
-    public static final int DOWNLOAD_GIF_NOTIFICATION_ID = 50000;
-
-    private static final int SUMMARY_BASE_ID_UNREAD_MESSAGE = 0;
-    private static final int NOTIFICATION_BASE_ID_UNREAD_MESSAGE = 1;
-
-    private static final String GROUP_USER_BASE = "ml.docilealligator.infinityforreddit.";
-
-    static NotificationCompat.Builder buildNotification(NotificationManagerCompat notificationManager,
-                                                        Context context, String title, String content,
-                                                        String summary, String channelId, String channelName,
-                                                        String group, int color) {
-        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
-            NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT);
-            notificationManager.createNotificationChannel(channel);
-        }
-
-        return new NotificationCompat.Builder(context.getApplicationContext(), channelId)
-                .setContentTitle(title)
-                .setContentText(content)
-                .setSmallIcon(R.drawable.ic_notification)
-                .setColor(color)
-                .setStyle(new NotificationCompat.BigTextStyle()
-                        .setSummaryText(summary)
-                        .bigText(content))
-                .setGroup(group)
-                .setAutoCancel(true);
-    }
-
-    static NotificationCompat.Builder buildSummaryNotification(Context context, NotificationManagerCompat notificationManager,
-                                                               String title, String content, String channelId,
-                                                               String channelName, String group, int color) {
-        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
-            NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT);
-            notificationManager.createNotificationChannel(channel);
-        }
-
-        return new NotificationCompat.Builder(context, channelId)
-                .setContentTitle(title)
-                //set content text to support devices running API level < 24
-                .setContentText(content)
-                .setSmallIcon(R.drawable.ic_notification)
-                .setColor(color)
-                .setGroup(group)
-                .setGroupSummary(true)
-                .setAutoCancel(true);
-    }
-
-    static NotificationManagerCompat getNotificationManager(Context context) {
-        return NotificationManagerCompat.from(context);
-    }
-
-    static String getAccountGroupName(String accountName) {
-        return GROUP_USER_BASE + accountName;
-    }
-
-    static int getSummaryIdUnreadMessage(int accountIndex) {
-        return SUMMARY_BASE_ID_UNREAD_MESSAGE + accountIndex * 1000;
-    }
-
-    static int getNotificationIdUnreadMessage(int accountIndex, int messageIndex) {
-        return NOTIFICATION_BASE_ID_UNREAD_MESSAGE + accountIndex * 1000 + messageIndex;
-    }
-}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationAlarmReceiver.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationAlarmReceiver.java
new file mode 100644
index 00000000..2a12f7a1
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationAlarmReceiver.java
@@ -0,0 +1,106 @@
+package ml.docilealligator.infinityforreddit;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.graphics.Color;
+import android.os.PowerManager;
+import android.util.Log;
+
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationManagerCompat;
+import androidx.work.Constraints;
+import androidx.work.ExistingWorkPolicy;
+import androidx.work.NetworkType;
+import androidx.work.OneTimeWorkRequest;
+import androidx.work.WorkManager;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.Utils.NotificationUtils;
+import retrofit2.Retrofit;
+
+public class PullNotificationAlarmReceiver extends BroadcastReceiver {
+
+    @Inject
+    @Named("oauth_without_authenticator")
+    Retrofit mOauthWithoutAuthenticatorRetrofit;
+    @Inject
+    @Named("no_oauth")
+    Retrofit mRetrofit;
+    @Inject
+    RedditDataRoomDatabase mRedditDataRoomDatabase;
+    @Inject
+    @Named("default")
+    SharedPreferences mSharedPreferences;
+    @Inject
+    CustomThemeWrapper mCustomThemeWrapper;
+
+    @Override
+    public void onReceive(Context context, Intent receivedIntent) {
+        ((Infinity) context.getApplicationContext()).getAppComponent().inject(this);
+
+        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+        PowerManager.WakeLock wl = null;
+        if (pm != null) {
+            wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ml.docilealligator.infinityforreddit:notification");
+            wl.acquire(2*60*1000L /*2 minutes*/);
+        }
+
+        Log.i("asasdfsdaf", "time: " + System.currentTimeMillis());
+
+        NotificationManagerCompat testNotificationManager = NotificationUtils.getNotificationManager(context);
+
+        NotificationCompat.Builder testSummaryBuilder = NotificationUtils.buildSummaryNotification(context,
+                testNotificationManager, "test",
+                Long.toString(System.currentTimeMillis()),
+                NotificationUtils.CHANNEL_ID_NEW_MESSAGES, NotificationUtils.CHANNEL_NEW_MESSAGES,
+                NotificationUtils.getAccountGroupName("test"), Color.BLACK);
+        testNotificationManager.notify(NotificationUtils.getSummaryIdUnreadMessage(12), testSummaryBuilder.build());
+
+        WorkManager workManager = WorkManager.getInstance(context);
+
+        Constraints constraints = new Constraints.Builder()
+                .setRequiredNetworkType(NetworkType.CONNECTED)
+                .build();
+
+        OneTimeWorkRequest pullNotificationRequest =
+                new OneTimeWorkRequest.Builder(PullNotificationWorker.class)
+                        .setConstraints(constraints)
+                        .build();
+
+        workManager.enqueueUniqueWork(PullNotificationWorker.UNIQUE_WORKER_NAME,
+                ExistingWorkPolicy.KEEP, pullNotificationRequest);
+
+        if (wl != null) {
+            wl.release();
+        }
+    }
+
+    public static void setNotificationAlarm(Context context, long notificationInterval) {
+        AlarmManager am =(AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+        if (am != null) {
+            Intent intent = new Intent(context, PullNotificationAlarmReceiver.class);
+            PendingIntent pendingIntent = PendingIntent.getBroadcast(context, NotificationUtils.PULL_NOTIFICATION_ALARM_RECEIVER_REQUEST_CODE, intent, 0);
+            if ((notificationInterval == 15 || notificationInterval == 30)) {
+                am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, 60 * 1000, 1000 * 60 * notificationInterval, pendingIntent); // Millisec * Second * Minute
+            } else {
+                am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, 60 * 1000, 1000 * 60 * 60 * notificationInterval, pendingIntent); // Millisec * Second * Minute
+            }
+        }
+    }
+
+    public static void cancelAlarm(Context context) {
+        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+        if (alarmManager != null) {
+            Intent intent = new Intent(context, AlarmManager.class);
+            PendingIntent pendingIntent = PendingIntent.getBroadcast(context, NotificationUtils.PULL_NOTIFICATION_ALARM_RECEIVER_REQUEST_CODE, intent, 0);
+            alarmManager.cancel(pendingIntent);
+        }
+    }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java
index ad25f171..75a9d4f0 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java
@@ -4,7 +4,9 @@ import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.graphics.Color;
 import android.net.Uri;
+import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.core.app.NotificationCompat;
@@ -22,6 +24,7 @@ import java.util.Calendar;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Random;
 
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -36,6 +39,7 @@ import ml.docilealligator.infinityforreddit.Message.Message;
 import ml.docilealligator.infinityforreddit.Message.ParseMessage;
 import ml.docilealligator.infinityforreddit.Utils.APIUtils;
 import ml.docilealligator.infinityforreddit.Utils.JSONUtils;
+import ml.docilealligator.infinityforreddit.Utils.NotificationUtils;
 import ml.docilealligator.infinityforreddit.Utils.SharedPreferencesUtils;
 import retrofit2.Call;
 import retrofit2.Response;
@@ -67,6 +71,17 @@ public class PullNotificationWorker extends Worker {
     @NonNull
     @Override
     public Result doWork() {
+        Log.i("asasdfsdaf", "time: " + System.currentTimeMillis());
+
+        NotificationManagerCompat testNotificationManager = NotificationUtils.getNotificationManager(context);
+
+        NotificationCompat.Builder testSummaryBuilder = NotificationUtils.buildSummaryNotification(context,
+                testNotificationManager, "test",
+                context.getString(R.string.notification_new_messages, 12),
+                NotificationUtils.CHANNEL_ID_NEW_MESSAGES, NotificationUtils.CHANNEL_NEW_MESSAGES,
+                NotificationUtils.getAccountGroupName("test"), Color.BLACK);
+        testNotificationManager.notify(new Random().nextInt(10000), testSummaryBuilder.build());
+
         try {
             List<Account> accounts = mRedditDataRoomDatabase.accountDao().getAllAccounts();
             int color = mCustomThemeWrapper.getColorPrimaryLightTheme();
@@ -202,7 +217,7 @@ public class PullNotificationWorker extends Worker {
             return Result.retry();
         } catch (JSONException e) {
             e.printStackTrace();
-            return Result.failure();
+            return Result.retry();
         }
         return Result.success();
     }
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadMediaService.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadMediaService.java
index fd552784..de89e476 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadMediaService.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadMediaService.java
@@ -38,7 +38,7 @@ import ml.docilealligator.infinityforreddit.API.DownloadFile;
 import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper;
 import ml.docilealligator.infinityforreddit.Event.DownloadMediaEvent;
 import ml.docilealligator.infinityforreddit.Infinity;
-import ml.docilealligator.infinityforreddit.NotificationUtils;
+import ml.docilealligator.infinityforreddit.Utils.NotificationUtils;
 import ml.docilealligator.infinityforreddit.R;
 import ml.docilealligator.infinityforreddit.Utils.SharedPreferencesUtils;
 import okhttp3.ResponseBody;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadRedditVideoService.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadRedditVideoService.java
index 2e08b0f6..71931b82 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadRedditVideoService.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadRedditVideoService.java
@@ -44,7 +44,7 @@ import ml.docilealligator.infinityforreddit.API.DownloadFile;
 import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper;
 import ml.docilealligator.infinityforreddit.Event.DownloadRedditVideoEvent;
 import ml.docilealligator.infinityforreddit.Infinity;
-import ml.docilealligator.infinityforreddit.NotificationUtils;
+import ml.docilealligator.infinityforreddit.Utils.NotificationUtils;
 import ml.docilealligator.infinityforreddit.R;
 import ml.docilealligator.infinityforreddit.Utils.SharedPreferencesUtils;
 import okhttp3.ResponseBody;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Service/SubmitPostService.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Service/SubmitPostService.java
index c65196d8..9f539d65 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/Service/SubmitPostService.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Service/SubmitPostService.java
@@ -40,7 +40,7 @@ import ml.docilealligator.infinityforreddit.Event.SubmitTextOrLinkPostEvent;
 import ml.docilealligator.infinityforreddit.Event.SubmitVideoOrGifPostEvent;
 import ml.docilealligator.infinityforreddit.Flair;
 import ml.docilealligator.infinityforreddit.Infinity;
-import ml.docilealligator.infinityforreddit.NotificationUtils;
+import ml.docilealligator.infinityforreddit.Utils.NotificationUtils;
 import ml.docilealligator.infinityforreddit.Post.Post;
 import ml.docilealligator.infinityforreddit.Post.SubmitPost;
 import ml.docilealligator.infinityforreddit.R;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/DownloadLocationPreferenceFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/DownloadLocationPreferenceFragment.java
index 50c436eb..61163598 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/DownloadLocationPreferenceFragment.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/DownloadLocationPreferenceFragment.java
@@ -87,18 +87,21 @@ public class DownloadLocationPreferenceFragment extends PreferenceFragmentCompat
     @Override
     public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
-        if (resultCode == Activity.RESULT_OK && data != null) {
+        if (resultCode == Activity.RESULT_OK && data != null && data.getData() != null) {
             if (requestCode == IMAGE_DOWNLOAD_LOCATION_REQUEST_CODE) {
+                activity.getContentResolver().takePersistableUriPermission(data.getData(), Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                 sharedPreferences.edit().putString(SharedPreferencesUtils.IMAGE_DOWNLOAD_LOCATION, data.getDataString()).apply();
                 if (imageDownloadLocationPreference != null) {
                     imageDownloadLocationPreference.setSummary(data.getDataString());
                 }
             } else if (requestCode == GIF_DOWNLOAD_LOCATION_REQUEST_CODE) {
+                activity.getContentResolver().takePersistableUriPermission(data.getData(), Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                 sharedPreferences.edit().putString(SharedPreferencesUtils.GIF_DOWNLOAD_LOCATION, data.getDataString()).apply();
                 if (gifDownloadLocationPreference != null) {
                     gifDownloadLocationPreference.setSummary(data.getDataString());
                 }
             } else if (requestCode == VIDEO_DOWNLOAD_LOCATION_REQUEST_CODE) {
+                activity.getContentResolver().takePersistableUriPermission(data.getData(), Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                 sharedPreferences.edit().putString(SharedPreferencesUtils.VIDEO_DOWNLOAD_LOCATION, data.getDataString()).apply();
                 if (videoDownloadLocationPreference != null) {
                     videoDownloadLocationPreference.setSummary(data.getDataString());
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/NotificationPreferenceFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/NotificationPreferenceFragment.java
index 3060be41..141e4ea4 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/NotificationPreferenceFragment.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/NotificationPreferenceFragment.java
@@ -53,7 +53,6 @@ public class NotificationPreferenceFragment extends PreferenceFragmentCompat {
 
         enableNotification = sharedPreferences.getBoolean(SharedPreferencesUtils.ENABLE_NOTIFICATION_KEY, true);
         notificationInterval = Long.parseLong(sharedPreferences.getString(SharedPreferencesUtils.NOTIFICATION_INTERVAL_KEY, "1"));
-        TimeUnit timeUnit = (notificationInterval == 15 || notificationInterval == 30) ? TimeUnit.MINUTES : TimeUnit.HOURS;
 
         if (enableNotification) {
             if (notificationIntervalListPreference != null) {
@@ -69,6 +68,8 @@ public class NotificationPreferenceFragment extends PreferenceFragmentCompat {
                 }
 
                 if (enableNotification) {
+                    TimeUnit timeUnit = (notificationInterval == 15 || notificationInterval == 30) ? TimeUnit.MINUTES : TimeUnit.HOURS;
+
                     Constraints constraints = new Constraints.Builder()
                             .setRequiredNetworkType(NetworkType.CONNECTED)
                             .build();
@@ -94,6 +95,8 @@ public class NotificationPreferenceFragment extends PreferenceFragmentCompat {
                 notificationInterval = Long.parseLong((String) newValue);
 
                 if (enableNotification) {
+                    TimeUnit timeUnit = (notificationInterval == 15 || notificationInterval == 30) ? TimeUnit.MINUTES : TimeUnit.HOURS;
+
                     Constraints constraints = new Constraints.Builder()
                             .setRequiredNetworkType(NetworkType.CONNECTED)
                             .build();
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/NotificationUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/NotificationUtils.java
new file mode 100644
index 00000000..1d5a3f6f
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/NotificationUtils.java
@@ -0,0 +1,91 @@
+package ml.docilealligator.infinityforreddit.Utils;
+
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationManagerCompat;
+
+import ml.docilealligator.infinityforreddit.R;
+
+public class NotificationUtils {
+    public static final String CHANNEL_SUBMIT_POST = "Submit Post";
+    public static final String CHANNEL_ID_NEW_MESSAGES = "new_messages";
+    public static final String CHANNEL_NEW_MESSAGES = "New Messages";
+    public static final String CHANNEL_ID_DOWNLOAD_REDDIT_VIDEO = "download_reddit_video";
+    public static final String CHANNEL_DOWNLOAD_REDDIT_VIDEO = "Download Reddit Video";
+    public static final String CHANNEL_ID_DOWNLOAD_VIDEO = "download_video";
+    public static final String CHANNEL_DOWNLOAD_VIDEO = "Download Video";
+    public static final String CHANNEL_ID_DOWNLOAD_IMAGE = "download_image";
+    public static final String CHANNEL_DOWNLOAD_IMAGE = "Download Image";
+    public static final String CHANNEL_ID_DOWNLOAD_GIF = "download_gif";
+    public static final String CHANNEL_DOWNLOAD_GIF = "Download Gif";
+    public static final int SUBMIT_POST_SERVICE_NOTIFICATION_ID = 10000;
+    public static final int DOWNLOAD_REDDIT_VIDEO_NOTIFICATION_ID = 20000;
+    public static final int DOWNLOAD_VIDEO_NOTIFICATION_ID = 30000;
+    public static final int DOWNLOAD_IMAGE_NOTIFICATION_ID = 40000;
+    public static final int DOWNLOAD_GIF_NOTIFICATION_ID = 50000;
+    public static final int PULL_NOTIFICATION_ALARM_RECEIVER_REQUEST_CODE = 12;
+
+    private static final int SUMMARY_BASE_ID_UNREAD_MESSAGE = 0;
+    private static final int NOTIFICATION_BASE_ID_UNREAD_MESSAGE = 1;
+
+    private static final String GROUP_USER_BASE = "ml.docilealligator.infinityforreddit.";
+
+    public static NotificationCompat.Builder buildNotification(NotificationManagerCompat notificationManager,
+                                                               Context context, String title, String content,
+                                                               String summary, String channelId, String channelName,
+                                                               String group, int color) {
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
+            NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT);
+            notificationManager.createNotificationChannel(channel);
+        }
+
+        return new NotificationCompat.Builder(context.getApplicationContext(), channelId)
+                .setContentTitle(title)
+                .setContentText(content)
+                .setSmallIcon(R.drawable.ic_notification)
+                .setColor(color)
+                .setStyle(new NotificationCompat.BigTextStyle()
+                        .setSummaryText(summary)
+                        .bigText(content))
+                .setGroup(group)
+                .setAutoCancel(true);
+    }
+
+    public static NotificationCompat.Builder buildSummaryNotification(Context context, NotificationManagerCompat notificationManager,
+                                                                      String title, String content, String channelId,
+                                                                      String channelName, String group, int color) {
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
+            NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT);
+            notificationManager.createNotificationChannel(channel);
+        }
+
+        return new NotificationCompat.Builder(context, channelId)
+                .setContentTitle(title)
+                //set content text to support devices running API level < 24
+                .setContentText(content)
+                .setSmallIcon(R.drawable.ic_notification)
+                .setColor(color)
+                .setGroup(group)
+                .setGroupSummary(true)
+                .setAutoCancel(true);
+    }
+
+    public static NotificationManagerCompat getNotificationManager(Context context) {
+        return NotificationManagerCompat.from(context);
+    }
+
+    public static String getAccountGroupName(String accountName) {
+        return GROUP_USER_BASE + accountName;
+    }
+
+    public static int getSummaryIdUnreadMessage(int accountIndex) {
+        return SUMMARY_BASE_ID_UNREAD_MESSAGE + accountIndex * 1000;
+    }
+
+    public static int getNotificationIdUnreadMessage(int accountIndex, int messageIndex) {
+        return NOTIFICATION_BASE_ID_UNREAD_MESSAGE + accountIndex * 1000 + messageIndex;
+    }
+}
-- 
cgit v1.2.3