diff --git a/app-tracking-protection/vpn-impl/src/main/AndroidManifest.xml b/app-tracking-protection/vpn-impl/src/main/AndroidManifest.xml
index 789ad0ef9338..c7239be1ca5c 100644
--- a/app-tracking-protection/vpn-impl/src/main/AndroidManifest.xml
+++ b/app-tracking-protection/vpn-impl/src/main/AndroidManifest.xml
@@ -3,6 +3,9 @@
+
+
+
diff --git a/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/apps/NewAppBroadcastReceiver.kt b/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/apps/NewAppBroadcastReceiver.kt
index 92a6a706e805..9f9149b85630 100644
--- a/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/apps/NewAppBroadcastReceiver.kt
+++ b/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/apps/NewAppBroadcastReceiver.kt
@@ -23,6 +23,7 @@ import android.content.IntentFilter
import androidx.annotation.MainThread
import androidx.annotation.WorkerThread
import com.duckduckgo.common.utils.DispatcherProvider
+import com.duckduckgo.common.utils.extensions.registerExportedReceiver
import com.duckduckgo.di.scopes.AppScope
import com.duckduckgo.di.scopes.VpnScope
import com.duckduckgo.mobile.android.vpn.AppTpVpnFeature
@@ -81,7 +82,7 @@ class NewAppBroadcastReceiver @Inject constructor(
addAction(Intent.ACTION_PACKAGE_ADDED)
addDataScheme("package")
}.run {
- applicationContext.registerReceiver(this@NewAppBroadcastReceiver, this)
+ applicationContext.registerExportedReceiver(this@NewAppBroadcastReceiver, this)
}
}
diff --git a/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/debug/DeviceShieldNotificationsDebugReceiver.kt b/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/debug/DeviceShieldNotificationsDebugReceiver.kt
index 56dc167dcc90..ce9e8bae6d18 100644
--- a/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/debug/DeviceShieldNotificationsDebugReceiver.kt
+++ b/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/debug/DeviceShieldNotificationsDebugReceiver.kt
@@ -26,6 +26,8 @@ import com.duckduckgo.app.di.AppCoroutineScope
import com.duckduckgo.app.lifecycle.MainProcessLifecycleObserver
import com.duckduckgo.appbuildconfig.api.AppBuildConfig
import com.duckduckgo.common.utils.DispatcherProvider
+import com.duckduckgo.common.utils.extensions.registerNotExportedReceiver
+import com.duckduckgo.common.utils.notification.checkPermissionAndNotify
import com.duckduckgo.di.scopes.AppScope
import com.duckduckgo.mobile.android.vpn.ui.notification.*
import com.squareup.anvil.annotations.ContributesMultibinding
@@ -49,7 +51,7 @@ class DeviceShieldNotificationsDebugReceiver(
) : BroadcastReceiver() {
init {
- context.registerReceiver(this, IntentFilter(intentAction))
+ context.registerNotExportedReceiver(this, IntentFilter(intentAction))
}
override fun onReceive(
@@ -116,7 +118,7 @@ class DeviceShieldNotificationsDebugReceiverRegister @Inject constructor(
}
notification?.let {
- notificationManagerCompat.notify(DeviceShieldNotificationScheduler.VPN_WEEKLY_NOTIFICATION_ID, it)
+ notificationManagerCompat.checkPermissionAndNotify(context, DeviceShieldNotificationScheduler.VPN_WEEKLY_NOTIFICATION_ID, it)
}
}
}
diff --git a/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/debug/SendTrackerDebugReceiver.kt b/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/debug/SendTrackerDebugReceiver.kt
index 76cefe11cc4e..e108cd292870 100644
--- a/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/debug/SendTrackerDebugReceiver.kt
+++ b/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/debug/SendTrackerDebugReceiver.kt
@@ -22,6 +22,7 @@ import android.content.Intent
import android.content.IntentFilter
import com.duckduckgo.appbuildconfig.api.AppBuildConfig
import com.duckduckgo.common.utils.DispatcherProvider
+import com.duckduckgo.common.utils.extensions.registerNotExportedReceiver
import com.duckduckgo.common.utils.formatters.time.DatabaseDateFormatter
import com.duckduckgo.di.scopes.VpnScope
import com.duckduckgo.mobile.android.vpn.model.TrackingApp
@@ -66,7 +67,7 @@ class SendTrackerDebugReceiver @Inject constructor(
}
logcat { "Debug receiver SendTrackerDebugReceiver registered" }
- context.registerReceiver(this, IntentFilter(INTENT_ACTION))
+ context.registerNotExportedReceiver(this, IntentFilter(INTENT_ACTION))
}
private fun unregister() {
diff --git a/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/service/RestartReceiver.kt b/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/service/RestartReceiver.kt
index 1bb0c9ba754a..2a71939bede8 100644
--- a/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/service/RestartReceiver.kt
+++ b/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/service/RestartReceiver.kt
@@ -24,6 +24,7 @@ import com.duckduckgo.app.di.AppCoroutineScope
import com.duckduckgo.appbuildconfig.api.AppBuildConfig
import com.duckduckgo.appbuildconfig.api.isInternalBuild
import com.duckduckgo.common.utils.DispatcherProvider
+import com.duckduckgo.common.utils.extensions.registerNotExportedReceiver
import com.duckduckgo.di.scopes.VpnScope
import com.duckduckgo.mobile.android.vpn.state.VpnStateMonitor
import com.squareup.anvil.annotations.ContributesMultibinding
@@ -56,7 +57,7 @@ class RestartReceiver @Inject constructor(
if (appBuildConfig.isInternalBuild()) {
logcat { "Starting vpn-service receiver" }
unregister()
- context.registerReceiver(this, IntentFilter("vpn-service"))
+ context.registerNotExportedReceiver(this, IntentFilter("vpn-service"))
}
}
diff --git a/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/service/VpnReminderReceiverManager.kt b/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/service/VpnReminderReceiverManager.kt
index 23a79e3f2a6c..292cccbdb3ac 100644
--- a/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/service/VpnReminderReceiverManager.kt
+++ b/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/service/VpnReminderReceiverManager.kt
@@ -16,8 +16,11 @@
package com.duckduckgo.mobile.android.vpn.service
+import android.Manifest.permission
import android.content.Context
import android.content.SharedPreferences
+import android.content.pm.PackageManager
+import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.edit
import com.duckduckgo.common.utils.plugins.PluginPoint
@@ -50,18 +53,20 @@ class AndroidVpnReminderReceiverManager @Inject constructor(
logcat { "Vpn is already running, nothing to show" }
} else {
logcat { "Vpn is not running, showing reminder notification" }
- val notification = vpnReminderNotificationContentPluginPoint.getHighestPriorityPluginForType(DISABLED)?.getContent()?.let { content ->
- val actualContent = if (wasReminderNotificationShown()) {
- content.copy(true)
- } else {
- notificationWasShown()
- content.copy(false)
+ if (ActivityCompat.checkSelfPermission(context, permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
+ val notification = vpnReminderNotificationContentPluginPoint.getHighestPriorityPluginForType(DISABLED)?.getContent()?.let { content ->
+ val actualContent = if (wasReminderNotificationShown()) {
+ content.copy(true)
+ } else {
+ notificationWasShown()
+ content.copy(false)
+ }
+ vpnReminderNotificationBuilder.buildReminderNotification(actualContent)
+ }
+ if (notification != null) {
+ deviceShieldPixels.didShowReminderNotification()
+ notificationManager.notify(TrackerBlockingVpnService.VPN_REMINDER_NOTIFICATION_ID, notification)
}
- vpnReminderNotificationBuilder.buildReminderNotification(actualContent)
- }
- if (notification != null) {
- deviceShieldPixels.didShowReminderNotification()
- notificationManager.notify(TrackerBlockingVpnService.VPN_REMINDER_NOTIFICATION_ID, notification)
}
}
}
diff --git a/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/service/VpnTrackerNotificationUpdates.kt b/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/service/VpnTrackerNotificationUpdates.kt
index 8b01315bcd13..23ca9d65fde5 100644
--- a/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/service/VpnTrackerNotificationUpdates.kt
+++ b/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/service/VpnTrackerNotificationUpdates.kt
@@ -20,6 +20,7 @@ import android.content.Context
import androidx.core.app.NotificationManagerCompat
import com.duckduckgo.common.utils.ConflatedJob
import com.duckduckgo.common.utils.DispatcherProvider
+import com.duckduckgo.common.utils.notification.checkPermissionAndNotify
import com.duckduckgo.common.utils.plugins.PluginPoint
import com.duckduckgo.di.scopes.VpnScope
import com.duckduckgo.mobile.android.vpn.state.VpnStateMonitor.VpnStopReason
@@ -71,6 +72,6 @@ class VpnTrackerNotificationUpdates @Inject constructor(
vpnNotification: VpnEnabledNotificationContentPlugin.VpnEnabledNotificationContent,
) {
val notification = VpnEnabledNotificationBuilder.buildVpnEnabledUpdateNotification(context, vpnNotification)
- notificationManager.notify(TrackerBlockingVpnService.VPN_FOREGROUND_SERVICE_ID, notification)
+ notificationManager.checkPermissionAndNotify(context, TrackerBlockingVpnService.VPN_FOREGROUND_SERVICE_ID, notification)
}
}
diff --git a/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/ui/alwayson/AlwaysOnLockDownDetector.kt b/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/ui/alwayson/AlwaysOnLockDownDetector.kt
index 200333b75728..9aa5de8eef0d 100644
--- a/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/ui/alwayson/AlwaysOnLockDownDetector.kt
+++ b/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/ui/alwayson/AlwaysOnLockDownDetector.kt
@@ -22,6 +22,7 @@ import android.text.SpannableStringBuilder
import androidx.core.app.NotificationManagerCompat
import com.duckduckgo.common.utils.ConflatedJob
import com.duckduckgo.common.utils.DispatcherProvider
+import com.duckduckgo.common.utils.notification.checkPermissionAndNotify
import com.duckduckgo.di.scopes.VpnScope
import com.duckduckgo.mobile.android.app.tracking.AppTrackingProtection
import com.duckduckgo.mobile.android.app.tracking.ui.AppTrackingProtectionScreens.AppTrackerActivityWithEmptyParams
@@ -95,7 +96,7 @@ class AlwaysOnLockDownDetector @Inject constructor(
notification,
intent,
).also {
- notificationManagerCompat.notify(notificationId, it)
+ notificationManagerCompat.checkPermissionAndNotify(context, notificationId, it)
}
}
diff --git a/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/ui/notification/AppTPReminderNotificationScheduler.kt b/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/ui/notification/AppTPReminderNotificationScheduler.kt
index 9e5dd969ddd5..945373478826 100644
--- a/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/ui/notification/AppTPReminderNotificationScheduler.kt
+++ b/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/ui/notification/AppTPReminderNotificationScheduler.kt
@@ -26,6 +26,7 @@ import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import com.duckduckgo.common.utils.DispatcherProvider
+import com.duckduckgo.common.utils.notification.checkPermissionAndNotify
import com.duckduckgo.common.utils.plugins.PluginPoint
import com.duckduckgo.di.scopes.VpnScope
import com.duckduckgo.mobile.android.app.tracking.AppTrackingProtection
@@ -179,7 +180,8 @@ class AppTPReminderNotificationScheduler @Inject constructor(
vpnReminderNotificationContentPluginPoint.getHighestPriorityPluginForType(DISABLED)?.let {
it.getContent()?.let { content ->
logcat { "Showing disabled notification from $it" }
- notificationManager.notify(
+ notificationManager.checkPermissionAndNotify(
+ context,
TrackerBlockingVpnService.VPN_REMINDER_NOTIFICATION_ID,
vpnReminderNotificationBuilder.buildReminderNotification(content),
)
@@ -191,7 +193,8 @@ class AppTPReminderNotificationScheduler @Inject constructor(
vpnReminderNotificationContentPluginPoint.getHighestPriorityPluginForType(REVOKED)?.let {
it.getContent()?.let { content ->
logcat { "Showing revoked notification from $it" }
- notificationManager.notify(
+ notificationManager.checkPermissionAndNotify(
+ context,
TrackerBlockingVpnService.VPN_REMINDER_NOTIFICATION_ID,
vpnReminderNotificationBuilder.buildReminderNotification(content),
)
diff --git a/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/ui/notification/DeviceShieldNotificationScheduler.kt b/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/ui/notification/DeviceShieldNotificationScheduler.kt
index efa48e109449..10a2c4da4ec2 100644
--- a/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/ui/notification/DeviceShieldNotificationScheduler.kt
+++ b/app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/ui/notification/DeviceShieldNotificationScheduler.kt
@@ -16,7 +16,10 @@
package com.duckduckgo.mobile.android.vpn.ui.notification
+import android.Manifest.permission
import android.content.Context
+import android.content.pm.PackageManager
+import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationManagerCompat
import androidx.lifecycle.LifecycleOwner
import androidx.work.*
@@ -185,18 +188,20 @@ class DeviceShieldDailyNotificationWorker(
}
private suspend fun showNotification() {
- val deviceShieldNotification = deviceShieldNotificationFactory.createDailyDeviceShieldNotification().also {
- notificationPressedHandler.notificationVariant = it.notificationVariant
- }
+ if (ActivityCompat.checkSelfPermission(context, permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
+ val deviceShieldNotification = deviceShieldNotificationFactory.createDailyDeviceShieldNotification().also {
+ notificationPressedHandler.notificationVariant = it.notificationVariant
+ }
- if (!deviceShieldNotification.hidden) {
- val notification =
- deviceShieldAlertNotificationBuilder.buildStatusNotification(context, deviceShieldNotification, notificationPressedHandler)
- deviceShieldPixels.didShowDailyNotification(deviceShieldNotification.notificationVariant)
- notificationManager.notify(DeviceShieldNotificationScheduler.VPN_DAILY_NOTIFICATION_ID, notification)
- logcat { "Vpn Daily notification is now shown" }
- } else {
- logcat { "Vpn Daily notification won't be shown because there is no data to show" }
+ if (!deviceShieldNotification.hidden) {
+ val notification =
+ deviceShieldAlertNotificationBuilder.buildStatusNotification(context, deviceShieldNotification, notificationPressedHandler)
+ deviceShieldPixels.didShowDailyNotification(deviceShieldNotification.notificationVariant)
+ notificationManager.notify(DeviceShieldNotificationScheduler.VPN_DAILY_NOTIFICATION_ID, notification)
+ logcat { "Vpn Daily notification is now shown" }
+ } else {
+ logcat { "Vpn Daily notification won't be shown because there is no data to show" }
+ }
}
}
}
@@ -223,20 +228,21 @@ class DeviceShieldWeeklyNotificationWorker(
override suspend fun doWork(): Result {
logcat { "Vpn Weekly notification worker is now awake" }
+ if (ActivityCompat.checkSelfPermission(context, permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
+ val deviceShieldNotification = deviceShieldNotificationFactory.createWeeklyDeviceShieldNotification().also {
+ notificationPressedHandler.notificationVariant = it.notificationVariant
+ }
- val deviceShieldNotification = deviceShieldNotificationFactory.createWeeklyDeviceShieldNotification().also {
- notificationPressedHandler.notificationVariant = it.notificationVariant
- }
-
- if (!deviceShieldNotification.hidden) {
- logcat { "Vpn Daily notification won't be shown because there is no data to show" }
- val notification = deviceShieldAlertNotificationBuilder.buildStatusNotification(
- context,
- deviceShieldNotification,
- notificationPressedHandler,
- )
- deviceShieldPixels.didShowWeeklyNotification(deviceShieldNotification.notificationVariant)
- notificationManager.notify(Companion.VPN_WEEKLY_NOTIFICATION_ID, notification)
+ if (!deviceShieldNotification.hidden) {
+ logcat { "Vpn Daily notification won't be shown because there is no data to show" }
+ val notification = deviceShieldAlertNotificationBuilder.buildStatusNotification(
+ context,
+ deviceShieldNotification,
+ notificationPressedHandler,
+ )
+ deviceShieldPixels.didShowWeeklyNotification(deviceShieldNotification.notificationVariant)
+ notificationManager.notify(Companion.VPN_WEEKLY_NOTIFICATION_ID, notification)
+ }
}
return Result.success()
diff --git a/app-tracking-protection/vpn-impl/src/test/java/com/duckduckgo/mobile/android/vpn/service/RestartReceiverTest.kt b/app-tracking-protection/vpn-impl/src/test/java/com/duckduckgo/mobile/android/vpn/service/RestartReceiverTest.kt
index 328ff2738714..23590a281847 100644
--- a/app-tracking-protection/vpn-impl/src/test/java/com/duckduckgo/mobile/android/vpn/service/RestartReceiverTest.kt
+++ b/app-tracking-protection/vpn-impl/src/test/java/com/duckduckgo/mobile/android/vpn/service/RestartReceiverTest.kt
@@ -56,7 +56,7 @@ class RestartReceiverTest {
receiver.onVpnStarted(coroutineRule.testScope)
verify(context).unregisterReceiver(any())
- verify(context).registerReceiver(any(), any())
+ verify(context).registerReceiver(any(), any(), isNull(), isNull(), any())
}
@Test
@@ -66,7 +66,7 @@ class RestartReceiverTest {
receiver.onVpnStarted(coroutineRule.testScope)
verify(context, never()).unregisterReceiver(any())
- verify(context, never()).registerReceiver(any(), any())
+ verify(context, never()).registerReceiver(any(), any(), isNull(), isNull(), any())
}
@Test
@@ -76,7 +76,7 @@ class RestartReceiverTest {
receiver.onVpnStopped(coroutineRule.testScope, VpnStateMonitor.VpnStopReason.SELF_STOP())
verify(context).unregisterReceiver(any())
- verify(context, never()).registerReceiver(any(), any())
+ verify(context, never()).registerReceiver(any(), any(), isNull(), isNull(), any())
}
@Test
@@ -86,6 +86,6 @@ class RestartReceiverTest {
receiver.onVpnStopped(coroutineRule.testScope, VpnStateMonitor.VpnStopReason.SELF_STOP())
verify(context).unregisterReceiver(any())
- verify(context, never()).registerReceiver(any(), any())
+ verify(context, never()).registerReceiver(any(), any(), isNull(), isNull(), any())
}
}
diff --git a/app-tracking-protection/vpn-internal/src/main/java/com/duckduckgo/vpn/internal/feature/InternalFeatureReceiver.kt b/app-tracking-protection/vpn-internal/src/main/java/com/duckduckgo/vpn/internal/feature/InternalFeatureReceiver.kt
index 1ff72fb6803a..7f32fdf7231c 100644
--- a/app-tracking-protection/vpn-internal/src/main/java/com/duckduckgo/vpn/internal/feature/InternalFeatureReceiver.kt
+++ b/app-tracking-protection/vpn-internal/src/main/java/com/duckduckgo/vpn/internal/feature/InternalFeatureReceiver.kt
@@ -20,6 +20,7 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
+import com.duckduckgo.common.utils.extensions.registerNotExportedReceiver
/**
* Abstract class to create generic receivers for internal features accessible through
@@ -44,7 +45,7 @@ abstract class InternalFeatureReceiver(
fun register() {
unregister()
- context.registerReceiver(this, IntentFilter(intentAction()))
+ context.registerNotExportedReceiver(this, IntentFilter(intentAction()))
}
fun unregister() {
diff --git a/app-tracking-protection/vpn-internal/src/main/java/com/duckduckgo/vpn/internal/feature/rules/ExceptionRulesDebugReceiver.kt b/app-tracking-protection/vpn-internal/src/main/java/com/duckduckgo/vpn/internal/feature/rules/ExceptionRulesDebugReceiver.kt
index aa6347101253..bee5be79081c 100644
--- a/app-tracking-protection/vpn-internal/src/main/java/com/duckduckgo/vpn/internal/feature/rules/ExceptionRulesDebugReceiver.kt
+++ b/app-tracking-protection/vpn-internal/src/main/java/com/duckduckgo/vpn/internal/feature/rules/ExceptionRulesDebugReceiver.kt
@@ -21,6 +21,7 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import com.duckduckgo.common.utils.DispatcherProvider
+import com.duckduckgo.common.utils.extensions.registerNotExportedReceiver
import com.duckduckgo.di.scopes.VpnScope
import com.duckduckgo.mobile.android.vpn.service.VpnServiceCallbacks
import com.duckduckgo.mobile.android.vpn.state.VpnStateMonitor.VpnStopReason
@@ -48,7 +49,7 @@ class ExceptionRulesDebugReceiver(
init {
kotlin.runCatching { context.unregisterReceiver(this) }
- context.registerReceiver(this, IntentFilter(intentAction))
+ context.registerNotExportedReceiver(this, IntentFilter(intentAction))
}
override fun onReceive(
diff --git a/app/src/internal/java/com/duckduckgo/app/dev/settings/privacy/TrackerDataDevReceiver.kt b/app/src/internal/java/com/duckduckgo/app/dev/settings/privacy/TrackerDataDevReceiver.kt
index 560d06f2be25..268c762046bc 100644
--- a/app/src/internal/java/com/duckduckgo/app/dev/settings/privacy/TrackerDataDevReceiver.kt
+++ b/app/src/internal/java/com/duckduckgo/app/dev/settings/privacy/TrackerDataDevReceiver.kt
@@ -26,6 +26,7 @@ import androidx.lifecycle.LifecycleOwner
import com.duckduckgo.app.lifecycle.MainProcessLifecycleObserver
import com.duckduckgo.app.trackerdetection.api.TrackerDataDownloader
import com.duckduckgo.appbuildconfig.api.AppBuildConfig
+import com.duckduckgo.common.utils.extensions.registerNotExportedReceiver
import com.duckduckgo.di.scopes.AppScope
import com.squareup.anvil.annotations.ContributesMultibinding
import io.reactivex.android.schedulers.AndroidSchedulers
@@ -39,7 +40,7 @@ class TrackerDataDevReceiver(
private val receiver: (Intent) -> Unit,
) : BroadcastReceiver() {
init {
- context.registerReceiver(this, IntentFilter(intentAction))
+ context.registerNotExportedReceiver(this, IntentFilter(intentAction))
}
override fun onReceive(
diff --git a/app/src/main/java/com/duckduckgo/app/notification/AppNotificationSender.kt b/app/src/main/java/com/duckduckgo/app/notification/AppNotificationSender.kt
index da067b82346c..6b8caefe42d7 100644
--- a/app/src/main/java/com/duckduckgo/app/notification/AppNotificationSender.kt
+++ b/app/src/main/java/com/duckduckgo/app/notification/AppNotificationSender.kt
@@ -22,6 +22,7 @@ import com.duckduckgo.app.notification.db.NotificationDao
import com.duckduckgo.app.notification.model.Notification
import com.duckduckgo.app.notification.model.SchedulableNotification
import com.duckduckgo.app.notification.model.SchedulableNotificationPlugin
+import com.duckduckgo.common.utils.notification.checkPermissionAndNotify
import com.duckduckgo.common.utils.plugins.PluginPoint
import timber.log.Timber
@@ -54,7 +55,7 @@ class AppNotificationSender(
val cancelIntent = NotificationHandlerService.pendingCancelNotificationHandlerIntent(context, notification.javaClass)
val systemNotification = factory.createNotification(specification, launchIntent, cancelIntent)
notificationDao.insert(Notification(notification.id))
- manager.notify(specification.systemId, systemNotification)
+ manager.checkPermissionAndNotify(context, specification.systemId, systemNotification)
notificationPlugin.onNotificationShown()
}
diff --git a/app/src/main/java/com/duckduckgo/app/widget/WidgetAddedReceiver.kt b/app/src/main/java/com/duckduckgo/app/widget/WidgetAddedReceiver.kt
index 1070a1314c98..3ea7aee196df 100644
--- a/app/src/main/java/com/duckduckgo/app/widget/WidgetAddedReceiver.kt
+++ b/app/src/main/java/com/duckduckgo/app/widget/WidgetAddedReceiver.kt
@@ -26,6 +26,7 @@ import androidx.lifecycle.LifecycleOwner
import com.duckduckgo.app.browser.R
import com.duckduckgo.app.lifecycle.MainProcessLifecycleObserver
import com.duckduckgo.app.widget.AppWidgetManagerAddWidgetLauncher.Companion.ACTION_ADD_WIDGET
+import com.duckduckgo.common.utils.extensions.registerNotExportedReceiver
import com.duckduckgo.di.scopes.AppScope
import com.squareup.anvil.annotations.ContributesMultibinding
import dagger.SingleInstanceIn
@@ -46,7 +47,7 @@ class WidgetAddedReceiver @Inject constructor(
override fun onCreate(owner: LifecycleOwner) {
super.onCreate(owner)
- context.registerReceiver(this, IntentFilter(ACTION_ADD_WIDGET))
+ context.registerNotExportedReceiver(this, IntentFilter(ACTION_ADD_WIDGET))
}
override fun onDestroy(owner: LifecycleOwner) {
diff --git a/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/sync/CredentialsSyncFeatureListener.kt b/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/sync/CredentialsSyncFeatureListener.kt
index 5d36ad165bbe..8694138316a3 100644
--- a/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/sync/CredentialsSyncFeatureListener.kt
+++ b/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/sync/CredentialsSyncFeatureListener.kt
@@ -18,6 +18,7 @@ package com.duckduckgo.autofill.sync
import android.content.Context
import androidx.core.app.NotificationManagerCompat
+import com.duckduckgo.common.utils.notification.checkPermissionAndNotify
import com.duckduckgo.di.scopes.AppScope
import com.duckduckgo.sync.api.engine.FeatureSyncError
import com.duckduckgo.sync.api.engine.FeatureSyncError.COLLECTION_LIMIT_REACHED
@@ -65,7 +66,8 @@ class AppCredentialsSyncFeatureListener @Inject constructor(
}
private fun triggerNotification() {
- notificationManager.notify(
+ notificationManager.checkPermissionAndNotify(
+ context,
SYNC_PAUSED_CREDENTIALS_NOTIFICATION_ID,
notificationBuilder.buildRateLimitNotification(context),
)
diff --git a/build.gradle b/build.gradle
index 3b38c25c0c43..2acf28e1fd16 100644
--- a/build.gradle
+++ b/build.gradle
@@ -9,7 +9,7 @@ buildscript {
ksp_version = '1.9.20-1.0.14'
gradle_plugin = '8.1.2'
min_sdk = 23
- target_sdk = 33
+ target_sdk = 34
compile_sdk = 34
fladle_version = '0.17.4'
kotlinter_version = '3.12.0'
diff --git a/common/common-utils/src/main/AndroidManifest.xml b/common/common-utils/src/main/AndroidManifest.xml
index e74ca12e7141..efb7d866ea9d 100644
--- a/common/common-utils/src/main/AndroidManifest.xml
+++ b/common/common-utils/src/main/AndroidManifest.xml
@@ -22,5 +22,6 @@
android:targetPackage="com.duckduckgo.common.utils"
android:label="Test for common"
/>
+
\ No newline at end of file
diff --git a/common/common-utils/src/main/java/com/duckduckgo/common/utils/extensions/ContextExtensions.kt b/common/common-utils/src/main/java/com/duckduckgo/common/utils/extensions/ContextExtensions.kt
index 871171847f9b..bf2ccd135d35 100644
--- a/common/common-utils/src/main/java/com/duckduckgo/common/utils/extensions/ContextExtensions.kt
+++ b/common/common-utils/src/main/java/com/duckduckgo/common/utils/extensions/ContextExtensions.kt
@@ -16,9 +16,12 @@
package com.duckduckgo.common.utils.extensions
+import android.content.BroadcastReceiver
import android.content.Context
+import android.content.IntentFilter
import android.os.PowerManager
import android.provider.Settings
+import androidx.core.content.ContextCompat
import timber.log.Timber
fun Context.isPrivateDnsActive(): Boolean {
@@ -46,3 +49,17 @@ fun Context.isIgnoringBatteryOptimizations(): Boolean {
} ?: false
}.getOrDefault(false)
}
+
+fun Context.registerNotExportedReceiver(
+ receiver: BroadcastReceiver,
+ intentFilter: IntentFilter,
+) {
+ ContextCompat.registerReceiver(this, receiver, intentFilter, ContextCompat.RECEIVER_NOT_EXPORTED)
+}
+
+fun Context.registerExportedReceiver(
+ receiver: BroadcastReceiver,
+ intentFilter: IntentFilter,
+) {
+ ContextCompat.registerReceiver(this, receiver, intentFilter, ContextCompat.RECEIVER_EXPORTED)
+}
diff --git a/common/common-utils/src/main/java/com/duckduckgo/common/utils/notification/NotificationUtils.kt b/common/common-utils/src/main/java/com/duckduckgo/common/utils/notification/NotificationUtils.kt
new file mode 100644
index 000000000000..1a54e5ae056c
--- /dev/null
+++ b/common/common-utils/src/main/java/com/duckduckgo/common/utils/notification/NotificationUtils.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2024 DuckDuckGo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.duckduckgo.common.utils.notification
+
+import android.Manifest.permission.POST_NOTIFICATIONS
+import android.app.Notification
+import android.content.Context
+import android.content.pm.PackageManager.PERMISSION_GRANTED
+import androidx.core.app.ActivityCompat
+import androidx.core.app.NotificationManagerCompat
+
+fun NotificationManagerCompat.checkPermissionAndNotify(
+ context: Context,
+ id: Int,
+ notification: Notification,
+) {
+ if (ActivityCompat.checkSelfPermission(context, POST_NOTIFICATIONS) == PERMISSION_GRANTED) {
+ notify(id, notification)
+ }
+}
diff --git a/downloads/downloads-impl/src/main/java/com/duckduckgo/downloads/impl/DefaultFileDownloadNotificationManager.kt b/downloads/downloads-impl/src/main/java/com/duckduckgo/downloads/impl/DefaultFileDownloadNotificationManager.kt
index 6d36a9a4a743..f02668c9e35a 100644
--- a/downloads/downloads-impl/src/main/java/com/duckduckgo/downloads/impl/DefaultFileDownloadNotificationManager.kt
+++ b/downloads/downloads-impl/src/main/java/com/duckduckgo/downloads/impl/DefaultFileDownloadNotificationManager.kt
@@ -28,6 +28,7 @@ import androidx.core.app.NotificationManagerCompat
import androidx.core.content.FileProvider
import com.duckduckgo.appbuildconfig.api.AppBuildConfig
import com.duckduckgo.browser.api.BrowserLifecycleObserver
+import com.duckduckgo.common.utils.notification.checkPermissionAndNotify
import com.duckduckgo.di.scopes.AppScope
import com.duckduckgo.downloads.api.FileDownloadNotificationManager
import com.squareup.anvil.annotations.ContributesBinding
@@ -100,8 +101,8 @@ class DefaultFileDownloadNotificationManager @Inject constructor(
}
notificationManager.apply {
- notify(downloadId.toInt(), notification)
- notify(SUMMARY_ID, summary)
+ checkPermissionAndNotify(applicationContext, downloadId.toInt(), notification)
+ checkPermissionAndNotify(applicationContext, SUMMARY_ID, summary)
groupNotificationsCounter.atomicUpdateAndGet { it.plus(downloadId to filename) }
}
}
@@ -128,7 +129,7 @@ class DefaultFileDownloadNotificationManager @Inject constructor(
// we don't want to post any notification while the DDG application is closing
if (applicationClosing.get()) return
- notificationManager.notify(downloadId.toInt(), notification)
+ notificationManager.checkPermissionAndNotify(applicationContext, downloadId.toInt(), notification)
}
@AnyThread
@@ -158,7 +159,7 @@ class DefaultFileDownloadNotificationManager @Inject constructor(
// we don't want to post any notification while the DDG application is closing
if (applicationClosing.get()) return
- notificationManager.notify(downloadId.toInt(), notification)
+ notificationManager.checkPermissionAndNotify(applicationContext, downloadId.toInt(), notification)
}
@AnyThread
diff --git a/downloads/downloads-impl/src/main/java/com/duckduckgo/downloads/impl/FileDownloadNotificationActionReceiver.kt b/downloads/downloads-impl/src/main/java/com/duckduckgo/downloads/impl/FileDownloadNotificationActionReceiver.kt
index dce2ec71137f..64206f89639e 100644
--- a/downloads/downloads-impl/src/main/java/com/duckduckgo/downloads/impl/FileDownloadNotificationActionReceiver.kt
+++ b/downloads/downloads-impl/src/main/java/com/duckduckgo/downloads/impl/FileDownloadNotificationActionReceiver.kt
@@ -26,6 +26,7 @@ import com.duckduckgo.app.di.AppCoroutineScope
import com.duckduckgo.app.lifecycle.MainProcessLifecycleObserver
import com.duckduckgo.app.statistics.pixels.Pixel
import com.duckduckgo.common.utils.DispatcherProvider
+import com.duckduckgo.common.utils.extensions.registerNotExportedReceiver
import com.duckduckgo.di.scopes.AppScope
import com.duckduckgo.downloads.api.*
import com.duckduckgo.downloads.impl.pixels.DownloadsPixelName
@@ -55,7 +56,7 @@ class FileDownloadNotificationActionReceiver @Inject constructor(
override fun onCreate(owner: LifecycleOwner) {
super.onCreate(owner)
Timber.v("Registering file download notification action receiver")
- context.registerReceiver(this, IntentFilter(INTENT_DOWNLOADS_NOTIFICATION_ACTION))
+ context.registerNotExportedReceiver(this, IntentFilter(INTENT_DOWNLOADS_NOTIFICATION_ACTION))
// When the app process is killed and restarted, this onCreate method is called and we take the opportunity
// to clean up the pending downloads that were in progress and will be no longer downloading.
diff --git a/network-protection/network-protection-impl/src/main/java/com/duckduckgo/networkprotection/impl/notification/NetPDisabledNotificationScheduler.kt b/network-protection/network-protection-impl/src/main/java/com/duckduckgo/networkprotection/impl/notification/NetPDisabledNotificationScheduler.kt
index 12694ef64104..72394551ea2d 100644
--- a/network-protection/network-protection-impl/src/main/java/com/duckduckgo/networkprotection/impl/notification/NetPDisabledNotificationScheduler.kt
+++ b/network-protection/network-protection-impl/src/main/java/com/duckduckgo/networkprotection/impl/notification/NetPDisabledNotificationScheduler.kt
@@ -22,6 +22,7 @@ import android.content.pm.PackageManager
import androidx.core.app.NotificationManagerCompat
import com.duckduckgo.app.di.AppCoroutineScope
import com.duckduckgo.common.utils.DispatcherProvider
+import com.duckduckgo.common.utils.notification.checkPermissionAndNotify
import com.duckduckgo.di.scopes.VpnScope
import com.duckduckgo.mobile.android.vpn.service.VpnServiceCallbacks
import com.duckduckgo.mobile.android.vpn.state.VpnStateMonitor.VpnStopReason
@@ -108,7 +109,8 @@ class NetPDisabledNotificationScheduler @Inject constructor(
coroutineScope.launch(dispatcherProvider.io()) {
if (triggerAtMillis != 0L) {
if (!netPSettingsLocalConfig.vpnNotificationAlerts().isEnabled()) return@launch
- notificationManager.notify(
+ notificationManager.checkPermissionAndNotify(
+ context,
NETP_REMINDER_NOTIFICATION_ID,
netPDisabledNotificationBuilder.buildSnoozeNotification(context, triggerAtMillis),
)
@@ -122,7 +124,8 @@ class NetPDisabledNotificationScheduler @Inject constructor(
coroutineScope.launch(dispatcherProvider.io()) {
logcat { "Showing disabled notification for NetP" }
if (!netPSettingsLocalConfig.vpnNotificationAlerts().isEnabled()) return@launch
- notificationManager.notify(
+ notificationManager.checkPermissionAndNotify(
+ context,
NETP_REMINDER_NOTIFICATION_ID,
netPDisabledNotificationBuilder.buildDisabledNotification(context),
)
@@ -141,7 +144,8 @@ class NetPDisabledNotificationScheduler @Inject constructor(
coroutineScope.launch(dispatcherProvider.io()) {
logcat { "Showing disabled by vpn notification for NetP" }
if (!netPSettingsLocalConfig.vpnNotificationAlerts().isEnabled()) return@launch
- notificationManager.notify(
+ notificationManager.checkPermissionAndNotify(
+ context,
NETP_REMINDER_NOTIFICATION_ID,
netPDisabledNotificationBuilder.buildDisabledByVpnNotification(context),
)
diff --git a/network-protection/network-protection-impl/src/main/java/com/duckduckgo/networkprotection/impl/timezone/NetPTimezoneMonitor.kt b/network-protection/network-protection-impl/src/main/java/com/duckduckgo/networkprotection/impl/timezone/NetPTimezoneMonitor.kt
index 1086926d1a4f..4637bb3db267 100644
--- a/network-protection/network-protection-impl/src/main/java/com/duckduckgo/networkprotection/impl/timezone/NetPTimezoneMonitor.kt
+++ b/network-protection/network-protection-impl/src/main/java/com/duckduckgo/networkprotection/impl/timezone/NetPTimezoneMonitor.kt
@@ -20,6 +20,7 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
+import com.duckduckgo.common.utils.extensions.registerNotExportedReceiver
import com.duckduckgo.di.scopes.VpnScope
import com.duckduckgo.mobile.android.vpn.VpnFeaturesRegistry
import com.duckduckgo.mobile.android.vpn.service.VpnServiceCallbacks
@@ -76,7 +77,7 @@ class NetPTimezoneMonitor @Inject constructor(
IntentFilter().apply {
addAction(Intent.ACTION_TIMEZONE_CHANGED)
}.run {
- context.registerReceiver(this@NetPTimezoneMonitor, this)
+ context.registerNotExportedReceiver(this@NetPTimezoneMonitor, this)
}
}
diff --git a/network-protection/network-protection-internal/src/main/java/com/duckduckgo/networkprotection/internal/feature/InternalFeatureReceiver.kt b/network-protection/network-protection-internal/src/main/java/com/duckduckgo/networkprotection/internal/feature/InternalFeatureReceiver.kt
index da8e597bddb6..391112ac52ec 100644
--- a/network-protection/network-protection-internal/src/main/java/com/duckduckgo/networkprotection/internal/feature/InternalFeatureReceiver.kt
+++ b/network-protection/network-protection-internal/src/main/java/com/duckduckgo/networkprotection/internal/feature/InternalFeatureReceiver.kt
@@ -20,6 +20,7 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
+import com.duckduckgo.common.utils.extensions.registerNotExportedReceiver
/**
* Abstract class to create generic receivers for internal features accessible through
@@ -44,7 +45,7 @@ abstract class InternalFeatureReceiver(
fun register() {
unregister()
- context.registerReceiver(this, IntentFilter(intentAction()))
+ context.registerNotExportedReceiver(this, IntentFilter(intentAction()))
}
fun unregister() {
diff --git a/network-protection/network-protection-internal/src/main/java/com/duckduckgo/networkprotection/internal/feature/snooze/VpnCallStateReceiver.kt b/network-protection/network-protection-internal/src/main/java/com/duckduckgo/networkprotection/internal/feature/snooze/VpnCallStateReceiver.kt
index a740c1d73f98..91b7ee115567 100644
--- a/network-protection/network-protection-internal/src/main/java/com/duckduckgo/networkprotection/internal/feature/snooze/VpnCallStateReceiver.kt
+++ b/network-protection/network-protection-internal/src/main/java/com/duckduckgo/networkprotection/internal/feature/snooze/VpnCallStateReceiver.kt
@@ -27,6 +27,7 @@ import com.duckduckgo.app.di.AppCoroutineScope
import com.duckduckgo.app.di.ProcessName
import com.duckduckgo.app.lifecycle.MainProcessLifecycleObserver
import com.duckduckgo.common.utils.DispatcherProvider
+import com.duckduckgo.common.utils.extensions.registerNotExportedReceiver
import com.duckduckgo.di.scopes.AppScope
import com.duckduckgo.di.scopes.ReceiverScope
import com.duckduckgo.mobile.android.vpn.Vpn
@@ -75,7 +76,10 @@ class VpnCallStateReceiver @Inject constructor(
private val _listener: PhoneStateListener =
object : PhoneStateListener() {
@Deprecated("Deprecated in Java")
- override fun onCallStateChanged(state: Int, phoneNumber: String?) {
+ override fun onCallStateChanged(
+ state: Int,
+ phoneNumber: String?,
+ ) {
appCoroutineScope.launch(dispatcherProvider.io()) {
logcat { "Call state: $state" }
if (state == TelephonyManager.CALL_STATE_IDLE) {
@@ -128,12 +132,14 @@ class VpnCallStateReceiver @Inject constructor(
registerListener()
}
}
+
ACTION_UNREGISTER_STATE_CALL_LISTENER -> {
logcat { "ACTION_UNREGISTER_STATE_CALL_LISTENER" }
goAsync(pendingResult) {
unregisterListener()
}
}
+
else -> {
logcat { "Unknown action ${intent.action}" }
}
@@ -155,7 +161,7 @@ class VpnCallStateReceiver @Inject constructor(
private fun register() {
unregister()
logcat { "Registering vpn call state receiver" }
- context.registerReceiver(
+ context.registerNotExportedReceiver(
this,
IntentFilter().apply {
addAction(ACTION_REGISTER_STATE_CALL_LISTENER)
diff --git a/network-protection/network-protection-internal/src/main/java/com/duckduckgo/networkprotection/internal/rekey/DebugRekeyReceiver.kt b/network-protection/network-protection-internal/src/main/java/com/duckduckgo/networkprotection/internal/rekey/DebugRekeyReceiver.kt
index cc24e5972347..62c411aa7e70 100644
--- a/network-protection/network-protection-internal/src/main/java/com/duckduckgo/networkprotection/internal/rekey/DebugRekeyReceiver.kt
+++ b/network-protection/network-protection-internal/src/main/java/com/duckduckgo/networkprotection/internal/rekey/DebugRekeyReceiver.kt
@@ -23,6 +23,7 @@ import android.content.Intent
import android.content.IntentFilter
import com.duckduckgo.anvil.annotations.InjectWith
import com.duckduckgo.app.di.ProcessName
+import com.duckduckgo.common.utils.extensions.registerNotExportedReceiver
import com.duckduckgo.di.scopes.VpnScope
import com.duckduckgo.mobile.android.vpn.service.VpnServiceCallbacks
import com.duckduckgo.mobile.android.vpn.state.VpnStateMonitor
@@ -61,6 +62,7 @@ class DebugRekeyReceiver @Inject constructor(
rekeyer.forceRekey()
}
}
+
else -> {
logcat(LogPriority.WARN) { "Unknown action" }
pendingResult?.finish()
@@ -72,7 +74,10 @@ class DebugRekeyReceiver @Inject constructor(
register()
}
- override fun onVpnStopped(coroutineScope: CoroutineScope, vpnStopReason: VpnStateMonitor.VpnStopReason) {
+ override fun onVpnStopped(
+ coroutineScope: CoroutineScope,
+ vpnStopReason: VpnStateMonitor.VpnStopReason,
+ ) {
logcat { "Unregistering debug re-keying receiver" }
unregister()
}
@@ -81,7 +86,7 @@ class DebugRekeyReceiver @Inject constructor(
private fun register() {
unregister()
logcat { "Registering debug re-keying receiver" }
- context.registerReceiver(
+ context.registerNotExportedReceiver(
this,
IntentFilter().apply {
addAction(ACTION_FORCE_REKEY)
diff --git a/network-protection/network-protection-subscription-internal/src/main/java/com/duckduckgo/networkprotection/subscription/notification/NetpAccessRevokedNotificationScheduler.kt b/network-protection/network-protection-subscription-internal/src/main/java/com/duckduckgo/networkprotection/subscription/notification/NetpAccessRevokedNotificationScheduler.kt
index f6af67db886a..058c4e1f8f4e 100644
--- a/network-protection/network-protection-subscription-internal/src/main/java/com/duckduckgo/networkprotection/subscription/notification/NetpAccessRevokedNotificationScheduler.kt
+++ b/network-protection/network-protection-subscription-internal/src/main/java/com/duckduckgo/networkprotection/subscription/notification/NetpAccessRevokedNotificationScheduler.kt
@@ -19,6 +19,7 @@ package com.duckduckgo.networkprotection.subscription.notification
import android.content.Context
import androidx.core.app.NotificationManagerCompat
import com.duckduckgo.common.utils.DispatcherProvider
+import com.duckduckgo.common.utils.notification.checkPermissionAndNotify
import com.duckduckgo.di.scopes.VpnScope
import com.duckduckgo.mobile.android.vpn.service.VpnServiceCallbacks
import com.duckduckgo.mobile.android.vpn.state.VpnStateMonitor.VpnStopReason
@@ -49,7 +50,8 @@ class NetpAccessRevokedNotificationScheduler @Inject constructor(
override fun onVpnStartFailed(coroutineScope: CoroutineScope) {
if (networkProtectionRepository.vpnAccessRevoked) {
- notificationManager.notify(
+ notificationManager.checkPermissionAndNotify(
+ context,
NetPDisabledNotificationScheduler.NETP_REMINDER_NOTIFICATION_ID,
netpAccessRevokedNotificationBuilder.buildVpnAccessRevokedNotification(context),
)
diff --git a/saved-sites/saved-sites-impl/src/main/java/com/duckduckgo/savedsites/impl/sync/SavedSitesSyncFeatureListener.kt b/saved-sites/saved-sites-impl/src/main/java/com/duckduckgo/savedsites/impl/sync/SavedSitesSyncFeatureListener.kt
index 971387214dca..5223d32b71e4 100644
--- a/saved-sites/saved-sites-impl/src/main/java/com/duckduckgo/savedsites/impl/sync/SavedSitesSyncFeatureListener.kt
+++ b/saved-sites/saved-sites-impl/src/main/java/com/duckduckgo/savedsites/impl/sync/SavedSitesSyncFeatureListener.kt
@@ -18,6 +18,7 @@ package com.duckduckgo.savedsites.impl.sync
import android.content.Context
import androidx.core.app.NotificationManagerCompat
+import com.duckduckgo.common.utils.notification.checkPermissionAndNotify
import com.duckduckgo.di.scopes.AppScope
import com.duckduckgo.sync.api.engine.FeatureSyncError
import com.duckduckgo.sync.api.engine.FeatureSyncError.COLLECTION_LIMIT_REACHED
@@ -65,7 +66,8 @@ class AppSavedSitesSyncFeatureListener @Inject constructor(
}
private fun triggerNotification() {
- notificationManager.notify(
+ notificationManager.checkPermissionAndNotify(
+ context,
SYNC_PAUSED_SAVED_SITES_NOTIFICATION_ID,
notificationBuilder.buildRateLimitNotification(context),
)
diff --git a/sync/sync-impl/src/main/java/com/duckduckgo/sync/impl/SyncFeatureToggle.kt b/sync/sync-impl/src/main/java/com/duckduckgo/sync/impl/SyncFeatureToggle.kt
index dcbf3e3cf170..f3c8533f69d8 100644
--- a/sync/sync-impl/src/main/java/com/duckduckgo/sync/impl/SyncFeatureToggle.kt
+++ b/sync/sync-impl/src/main/java/com/duckduckgo/sync/impl/SyncFeatureToggle.kt
@@ -23,6 +23,7 @@ import com.duckduckgo.appbuildconfig.api.AppBuildConfig
import com.duckduckgo.appbuildconfig.api.isInternalBuild
import com.duckduckgo.common.utils.DefaultDispatcherProvider
import com.duckduckgo.common.utils.DispatcherProvider
+import com.duckduckgo.common.utils.notification.checkPermissionAndNotify
import com.duckduckgo.di.scopes.AppScope
import com.duckduckgo.feature.toggles.api.Toggle
import com.duckduckgo.privacy.config.api.PrivacyConfigCallbackPlugin
@@ -135,7 +136,8 @@ class SyncRemoteFeatureToggle @Inject constructor(
private fun triggerNotification() {
val showSync = showSync()
- notificationManager.notify(
+ notificationManager.checkPermissionAndNotify(
+ context,
SYNC_PAUSED_NOTIFICATION_ID,
syncNotificationBuilder.buildSyncPausedNotification(context, addNavigationIntent = showSync),
)
diff --git a/versions.properties b/versions.properties
index 0ff7a4230e76..ce854160dfe6 100644
--- a/versions.properties
+++ b/versions.properties
@@ -23,7 +23,7 @@ version.androidx.localbroadcastmanager=1.1.0
version.androidx.recyclerview=1.3.2
-version.androidx.core=1.8.0
+version.androidx.core=1.12.0
version.androidx.fragment=1.5.2