-
-
Notifications
You must be signed in to change notification settings - Fork 799
Handle notification permission in BaseActivity #6440
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 9 commits
0e7ba3d
0bab39f
43f4387
fe84ce4
623dc18
8c54ac9
9ecc93d
8cec53e
22431de
4fb129e
9b0da9d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,6 +2,7 @@ package org.wikipedia.activity | |||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.content.Intent | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.graphics.drawable.ColorDrawable | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.os.Build | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.os.Bundle | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.view.MenuItem | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.view.MotionEvent | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -79,7 +80,25 @@ abstract class BaseActivity : AppCompatActivity(), ConnectionStateMonitor.Callba | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private val notificationPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted -> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // TODO: Show message(s) to the user if they deny the permission | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if(!granted){ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.O){ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if(ActivityCompat.shouldShowRequestPermissionRationale(this,android.Manifest.permission.POST_NOTIFICATIONS)){ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //User denied once->Show Snackbar | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| FeedbackUtil.makeSnackbar(this, getString(R.string.notification_permission_rationale)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .setAction(R.string.notification_permission_rationale_action){ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DeviceUtil.openNotificationSettings(this) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .show() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }else{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //User denied (with "Don't Ask Again") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| FeedbackUtil.makeSnackbar(this, getString(R.string.notification_permission_denied)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .setAction(R.string.app_settings){ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+83
to
+95
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if(!granted){ | |
| if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.O){ | |
| if(ActivityCompat.shouldShowRequestPermissionRationale(this,android.Manifest.permission.POST_NOTIFICATIONS)){ | |
| //User denied once->Show Snackbar | |
| FeedbackUtil.makeSnackbar(this, getString(R.string.notification_permission_rationale)) | |
| .setAction(R.string.notification_permission_rationale_action){ | |
| DeviceUtil.openNotificationSettings(this) | |
| } | |
| .show() | |
| }else{ | |
| //User denied (with "Don't Ask Again") | |
| FeedbackUtil.makeSnackbar(this, getString(R.string.notification_permission_denied)) | |
| .setAction(R.string.app_settings){ | |
| if (!granted) { | |
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | |
| if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.POST_NOTIFICATIONS)) { | |
| //User denied once->Show Snackbar | |
| FeedbackUtil.makeSnackbar(this, getString(R.string.notification_permission_rationale)) | |
| .setAction(R.string.notification_permission_rationale_action) { | |
| DeviceUtil.openNotificationSettings(this) | |
| } | |
| .show() | |
| } else { | |
| //User denied (with "Don't Ask Again") | |
| FeedbackUtil.makeSnackbar(this, getString(R.string.notification_permission_denied)) | |
| .setAction(R.string.app_settings) { |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,12 +2,14 @@ package org.wikipedia.util | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.app.Activity | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.content.Context | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.content.Intent | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.content.res.Configuration | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.content.res.Resources | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.graphics.Color | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.net.ConnectivityManager | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.os.Build | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.os.Handler | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.provider.Settings | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.view.KeyCharacterMap | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.view.KeyEvent | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.view.View | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -107,6 +109,19 @@ object DeviceUtil { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WindowCompat.getInsetsController(activity.window, activity.window.decorView).isAppearanceLightStatusBars = !WikipediaApp.instance.currentTheme.isDark | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fun openNotificationSettings(context: Context){ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val intent= if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+112
to
+113
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| putExtra(Settings.EXTRA_APP_PACKAGE,context.packageName) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }else{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data = android.net.Uri.fromParts("package", context.packageName, null) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+112
to
+121
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| context.startActivity(intent as? Intent) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+112
to
+122
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fun openNotificationSettings(context: Context){ | |
| val intent= if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | |
| Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { | |
| putExtra(Settings.EXTRA_APP_PACKAGE,context.packageName) | |
| } | |
| }else{ | |
| Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { | |
| data = android.net.Uri.fromParts("package", context.packageName, null) | |
| } | |
| } | |
| context.startActivity(intent as? Intent) | |
| fun openNotificationSettings(context: Context) { | |
| val intent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | |
| Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { | |
| putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName) | |
| } | |
| } else { | |
| // Try the dedicated app notification settings screen on pre-O, if available, | |
| // and fall back to the generic app details screen otherwise. | |
| Intent("android.settings.APP_NOTIFICATION_SETTINGS").apply { | |
| putExtra("app_package", context.packageName) | |
| putExtra("app_uid", context.applicationInfo.uid) | |
| }.takeIf { it.resolveActivity(context.packageManager) != null } | |
| ?: Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { | |
| data = android.net.Uri.fromParts("package", context.packageName, null) | |
| } | |
| } | |
| context.startActivity(intent) |
Copilot
AI
Apr 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
context.startActivity(intent as? Intent) is unnecessary and makes the call nullable; if that cast were ever to fail it would pass null and crash at runtime. Use context.startActivity(intent) and either (a) require an Activity parameter, or (b) add FLAG_ACTIVITY_NEW_TASK when context isn’t an Activity, since Context can be an application context.
| context.startActivity(intent as? Intent) | |
| if (context !is Activity) { | |
| intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) | |
| } | |
| context.startActivity(intent) |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -825,6 +825,9 @@ | |||||
| <string name="notifications_all_types_text">All types</string> | ||||||
| <string name="notifications_menu_user_talk_page">%s\'s talk page</string> | ||||||
| <string name="notifications_offline_disable_message">The function is not available while offline.</string> | ||||||
| <string name="notification_permission_rationale">Enable Notification to stay updated</string> | ||||||
|
||||||
| <string name="notification_permission_rationale">Enable Notification to stay updated</string> | |
| <string name="notification_permission_rationale">Enable notifications to stay up to date.</string> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The permission being handled here is
POST_NOTIFICATIONS, which only exists as a runtime permission on API 33+ (TIRAMISU). TheSDK_INT >= Ogate is misleading and could mask future changes (e.g., if the launcher were ever invoked on 26–32). Consider gating this logic withBuild.VERSION_CODES.TIRAMISU(or removing the version check entirely, since the launcher is already only triggered on 33+ inNotificationPresenter.maybeRequestPermission).