Fix upcoming lesson notifications on Android 12 (#1650)

This commit is contained in:
Mikołaj Pich
2021-11-18 20:22:15 +01:00
committed by GitHub
parent 2874a7495e
commit 88b893e6c0
13 changed files with 73 additions and 22 deletions

View File

@ -105,7 +105,10 @@ class PreferencesRepository @Inject constructor(
val isUpcomingLessonsNotificationsEnableKey =
context.getString(R.string.pref_key_notifications_upcoming_lessons_enable)
val isUpcomingLessonsNotificationsEnable: Boolean
var isUpcomingLessonsNotificationsEnable: Boolean
set(value) {
sharedPref.edit { putBoolean(isUpcomingLessonsNotificationsEnableKey, value) }
}
get() = getBoolean(
isUpcomingLessonsNotificationsEnableKey,
R.bool.pref_default_notification_upcoming_lessons_enable

View File

@ -5,6 +5,7 @@ import android.app.AlarmManager.RTC_WAKEUP
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.core.app.AlarmManagerCompat
import androidx.core.app.NotificationManagerCompat
import dagger.hilt.android.qualifiers.ApplicationContext
@ -91,6 +92,12 @@ class TimetableNotificationSchedulerHelper @Inject constructor(
return cancelScheduled(lessons, student)
}
if (!canScheduleExactAlarms()) {
Timber.w("Exact alarms are disabled by user")
preferencesRepository.isUpcomingLessonsNotificationsEnable = false
return
}
if (lessons.firstOrNull()?.date?.isAfter(LocalDate.now().plusDays(2)) == true) {
Timber.d("Timetable notification scheduling skipped - lessons are too far")
return
@ -169,8 +176,18 @@ class TimetableNotificationSchedulerHelper @Inject constructor(
intent.getStringExtra(LESSON_TITLE)
}, start: $time, student: $studentId"
)
} catch (e: IllegalStateException) {
} catch (e: Throwable) {
Timber.e(e)
}
}
fun canScheduleExactAlarms(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
try {
alarmManager.canScheduleExactAlarms()
} catch (e: Throwable) {
false
}
} else true
}
}

View File

@ -1,5 +1,6 @@
package io.github.wulkanowy.ui.modules.settings.notifications
import android.annotation.SuppressLint
import android.content.Intent
import android.content.SharedPreferences
import android.net.Uri
@ -50,10 +51,14 @@ class NotificationsFragment : PreferenceFragmentCompat(),
return appPackageName in packageNameList
}
private val notificationSettingsContract =
private val notificationSettingsPiggybackContract =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
presenter.onNotificationPiggybackPermissionResult()
}
presenter.onNotificationPermissionResult()
private val notificationSettingsExactAlarmsContract =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
presenter.onNotificationExactAlarmPermissionResult()
}
override fun initView(showDebugNotificationSwitch: Boolean) {
@ -136,7 +141,7 @@ class NotificationsFragment : PreferenceFragmentCompat(),
.setTitle(R.string.pref_notify_fix_sync_issues)
.setMessage(R.string.pref_notify_fix_sync_issues_message)
.setNegativeButton(android.R.string.cancel) { _, _ -> }
.setPositiveButton(R.string.pref_notify_fix_sync_issues_settings_button) { _, _ ->
.setPositiveButton(R.string.pref_notify_open_system_settings) { _, _ ->
try {
AppKillerManager.doActionPowerSaving(requireContext())
AppKillerManager.doActionAutoStart(requireContext())
@ -151,6 +156,7 @@ class NotificationsFragment : PreferenceFragmentCompat(),
.show()
}
@SuppressLint("InlinedApi")
override fun openSystemSettings() {
val intent = if (appInfo.systemVersion >= Build.VERSION_CODES.O) {
Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply {
@ -172,8 +178,8 @@ class NotificationsFragment : PreferenceFragmentCompat(),
AlertDialog.Builder(requireContext())
.setTitle(getString(R.string.pref_notification_piggyback_popup_title))
.setMessage(getString(R.string.pref_notification_piggyback_popup_description))
.setPositiveButton(getString(R.string.pref_notification_piggyback_popup_positive)) { _, _ ->
notificationSettingsContract.launch(Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"))
.setPositiveButton(getString(R.string.pref_notification_go_to_settings)) { _, _ ->
notificationSettingsPiggybackContract.launch(Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"))
}
.setNegativeButton(android.R.string.cancel) { _, _ ->
setNotificationPiggybackPreferenceChecked(false)
@ -182,11 +188,30 @@ class NotificationsFragment : PreferenceFragmentCompat(),
.show()
}
override fun openNotificationExactAlarmSettings() {
AlertDialog.Builder(requireContext())
.setTitle(getString(R.string.pref_notification_exact_alarm_popup_title))
.setMessage(getString(R.string.pref_notification_exact_alarm_popup_descriptions))
.setPositiveButton(getString(R.string.pref_notification_go_to_settings)) { _, _ ->
notificationSettingsExactAlarmsContract.launch(Intent("android.settings.REQUEST_SCHEDULE_EXACT_ALARM"))
}
.setNegativeButton(android.R.string.cancel) { _, _ ->
setUpcomingLessonsNotificationPreferenceChecked(false)
}
.setOnDismissListener { setUpcomingLessonsNotificationPreferenceChecked(false) }
.show()
}
override fun setNotificationPiggybackPreferenceChecked(isChecked: Boolean) {
findPreference<SwitchPreferenceCompat>(getString(R.string.pref_key_notifications_piggyback))?.isChecked =
isChecked
}
override fun setUpcomingLessonsNotificationPreferenceChecked(isChecked: Boolean) {
findPreference<SwitchPreferenceCompat>(getString(R.string.pref_key_notifications_upcoming_lessons_enable))?.isChecked =
isChecked
}
override fun onResume() {
super.onResume()
preferenceScreen.sharedPreferences.registerOnSharedPreferenceChangeListener(this)

View File

@ -45,6 +45,8 @@ class NotificationsPresenter @Inject constructor(
isUpcomingLessonsNotificationsEnableKey, isUpcomingLessonsNotificationsPersistentKey -> {
if (!isUpcomingLessonsNotificationsEnable) {
timetableNotificationHelper.cancelNotification()
} else if (!timetableNotificationHelper.canScheduleExactAlarms()) {
view?.openNotificationExactAlarmSettings()
}
}
isDebugNotificationEnableKey -> {
@ -68,12 +70,16 @@ class NotificationsPresenter @Inject constructor(
view?.openSystemSettings()
}
fun onNotificationPermissionResult() {
fun onNotificationPiggybackPermissionResult() {
view?.run {
setNotificationPiggybackPreferenceChecked(isNotificationPermissionGranted)
}
}
fun onNotificationExactAlarmPermissionResult() {
view?.setUpcomingLessonsNotificationPreferenceChecked(timetableNotificationHelper.canScheduleExactAlarms())
}
private fun checkNotificationPiggybackState() {
if (preferencesRepository.isNotificationPiggybackEnabled) {
view?.run {

View File

@ -16,5 +16,9 @@ interface NotificationsView : BaseView {
fun openNotificationPermissionDialog()
fun openNotificationExactAlarmSettings()
fun setNotificationPiggybackPreferenceChecked(isChecked: Boolean)
fun setUpcomingLessonsNotificationPreferenceChecked(isChecked: Boolean)
}