diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 8dac39682..a8c5bbf06 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -184,12 +184,17 @@ public class MainActivity extends AppCompatActivity { } openMiniPlayerUponPlayerStarted(); - if (PermissionHelper.checkPostNotificationsPermission(this, - PermissionHelper.POST_NOTIFICATIONS_REQUEST_CODE)) { - // Schedule worker for checking for new streams and creating corresponding notifications - // if this is enabled by the user. - NotificationWorker.initialize(this); - } + PermissionHelper.checkPostNotificationsPermissionOnStartup( + this, + notificationAllowed -> { + // Schedule worker for checking for new streams and creating corresponding + // notifications if this is enabled by the user. + if (Boolean.TRUE.equals(notificationAllowed)) { + NotificationWorker.initialize(this); + } + } + ); + if (!UpdateSettingsFragment.wasUserAskedForConsent(this) && !App.getApp().isFirstRun() && ReleaseVersionUtil.INSTANCE.isReleaseApk()) { diff --git a/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java b/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java index 2785afab0..e377679a0 100644 --- a/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java @@ -1,10 +1,12 @@ package org.schabi.newpipe.util; import android.Manifest; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; @@ -12,14 +14,21 @@ import android.provider.Settings; import android.text.Html; import android.widget.Toast; +import androidx.activity.ComponentActivity; +import androidx.activity.result.ActivityResultCallback; +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.RequiresApi; import androidx.appcompat.app.AlertDialog; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; +import androidx.preference.PreferenceManager; import org.schabi.newpipe.R; import org.schabi.newpipe.settings.NewPipeSettings; +import java.util.function.Consumer; + public final class PermissionHelper { public static final int POST_NOTIFICATIONS_REQUEST_CODE = 779; public static final int DOWNLOAD_DIALOG_REQUEST_CODE = 778; @@ -83,17 +92,59 @@ public final class PermissionHelper { return true; } - public static boolean checkPostNotificationsPermission(final Activity activity, - final int requestCode) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU - && ContextCompat.checkSelfPermission(activity, - Manifest.permission.POST_NOTIFICATIONS) - != PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions(activity, - new String[] {Manifest.permission.POST_NOTIFICATIONS}, requestCode); - return false; + + /** + * Check that we have the notification permission or ask the user for permission. + * + * @param activity main activity + * @param userChoice a callback that gets called with the user choice + */ + public static void checkPostNotificationsPermissionOnStartup( + final ComponentActivity activity, + final Consumer userChoice) { + + // On Android before TIRAMISU, notifications are always allowed to be sent + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { + userChoice.accept(true); + return; } - return true; + + // if we have the permission already, continue + if (ContextCompat.checkSelfPermission(activity, Manifest.permission.POST_NOTIFICATIONS) + == PackageManager.PERMISSION_GRANTED) { + userChoice.accept(true); + return; + } + + // if we already asked the user, don’t ask again + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity); + final String wasAskedKey = activity.getString( + R.string.user_was_asked_notification_permission_on_startup_key); + if (prefs.getBoolean(wasAskedKey, false)) { + userChoice.accept(false); + return; + } + + // else let’s ask the user for permission + @SuppressLint("ApplySharedPref") + final ActivityResultCallback cb = isGranted -> { + // first make sure that we only ever ask the user once on startup + final SharedPreferences prefs2 = + PreferenceManager.getDefaultSharedPreferences(activity); + // commit setting before doing anything else + prefs2.edit().putBoolean(wasAskedKey, true).commit(); + + // forward the user choice + userChoice.accept(isGranted); + }; + + final ActivityResultLauncher notificationRequestReference = + activity.registerForActivityResult( + new ActivityResultContracts.RequestPermission(), + cb + ); + + notificationRequestReference.launch(Manifest.permission.POST_NOTIFICATIONS); } /** diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index 352e4cec1..f7c9538e2 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -1443,6 +1443,7 @@ recaptcha_cookies_key + user_was_asked_notification_permission_on_startup enable_streams_notifications streams_notifications_interval 14400