From c31d38905b61529044bfc9906ebcea7f4ddb590c Mon Sep 17 00:00:00 2001 From: Moez Bhatti Date: Wed, 14 Dec 2022 17:01:56 -0500 Subject: [PATCH] Ensure exact alarm permission before sending scheduled/delayed messages --- .../QKSMS/manager/PermissionManagerImpl.kt | 10 +++++++ .../moez/QKSMS/manager/PermissionManager.kt | 2 ++ .../java/com/moez/QKSMS/common/Navigator.kt | 8 +++++ .../QKSMS/feature/compose/ComposeViewModel.kt | 29 ++++++++++++++----- 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/data/src/main/java/com/moez/QKSMS/manager/PermissionManagerImpl.kt b/data/src/main/java/com/moez/QKSMS/manager/PermissionManagerImpl.kt index f7baa995..93c3b1e1 100644 --- a/data/src/main/java/com/moez/QKSMS/manager/PermissionManagerImpl.kt +++ b/data/src/main/java/com/moez/QKSMS/manager/PermissionManagerImpl.kt @@ -19,6 +19,7 @@ package com.moez.QKSMS.manager import android.Manifest +import android.app.AlarmManager import android.app.NotificationManager import android.app.role.RoleManager import android.content.Context @@ -71,6 +72,15 @@ class PermissionManagerImpl @Inject constructor(private val context: Context) : return hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) } + override fun hasExactAlarms(): Boolean { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { + return true + } + + val alarmManager = context.getSystemService(AlarmManager::class.java) + return alarmManager.canScheduleExactAlarms() + } + private fun hasPermission(permission: String): Boolean { return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED } diff --git a/domain/src/main/java/com/moez/QKSMS/manager/PermissionManager.kt b/domain/src/main/java/com/moez/QKSMS/manager/PermissionManager.kt index 256fa910..f53ea5b4 100644 --- a/domain/src/main/java/com/moez/QKSMS/manager/PermissionManager.kt +++ b/domain/src/main/java/com/moez/QKSMS/manager/PermissionManager.kt @@ -36,4 +36,6 @@ interface PermissionManager { fun hasStorage(): Boolean + fun hasExactAlarms(): Boolean + } diff --git a/presentation/src/main/java/com/moez/QKSMS/common/Navigator.kt b/presentation/src/main/java/com/moez/QKSMS/common/Navigator.kt index b55b495a..d9adb09f 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/Navigator.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/Navigator.kt @@ -309,4 +309,12 @@ class Navigator @Inject constructor( } } + fun showExactAlarmsSettings() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + val intent = Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM) + .setData(Uri.parse("package:${context.packageName}")) + startActivity(intent) + } + } + } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt index ba601f2f..9afc1772 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt @@ -634,23 +634,36 @@ class ComposeViewModel @Inject constructor( // Send a message when the send button is clicked, and disable editing mode if it's enabled view.sendIntent - .filter { permissionManager.isDefaultSms().also { if (!it) view.requestDefaultSms() } } - .filter { permissionManager.hasSendSms().also { if (!it) view.requestSmsPermission() } } - .withLatestFrom(view.textChangedIntent) { _, body -> body } - .map { body -> body.toString() } + .withLatestFrom(view.textChangedIntent) { _, body -> body.toString() } .withLatestFrom(state, attachments, conversation, selectedChips) { body, state, attachments, conversation, chips -> - val subId = state.subscription?.subscriptionId ?: -1 - val addresses = when (conversation.recipients.isNotEmpty()) { - true -> conversation.recipients.map { it.address } - false -> chips.map { chip -> chip.address } + if (!permissionManager.isDefaultSms()) { + view.requestDefaultSms() + return@withLatestFrom } + + if (!permissionManager.hasSendSms()) { + view.requestSmsPermission() + return@withLatestFrom + } + val delay = when (prefs.sendDelay.get()) { Preferences.SEND_DELAY_SHORT -> 3000 Preferences.SEND_DELAY_MEDIUM -> 5000 Preferences.SEND_DELAY_LONG -> 10000 else -> 0 } + + if ((delay != 0 || state.scheduled != 0L) && !permissionManager.hasExactAlarms()) { + navigator.showExactAlarmsSettings() + return@withLatestFrom + } + + val subId = state.subscription?.subscriptionId ?: -1 + val addresses = when (conversation.recipients.isNotEmpty()) { + true -> conversation.recipients.map { it.address } + false -> chips.map { chip -> chip.address } + } val sendAsGroup = !state.editingMode || state.sendAsGroup when {