Fix exact alarm permission on Android 14 (#298)
This commit is contained in:
@@ -1,12 +1,17 @@
|
|||||||
package com.github.gotify.init
|
package com.github.gotify.init
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
|
import android.app.AlarmManager
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.github.gotify.NotificationSupport
|
import com.github.gotify.NotificationSupport
|
||||||
@@ -34,6 +39,12 @@ internal class InitializationActivity : AppCompatActivity() {
|
|||||||
private lateinit var settings: Settings
|
private lateinit var settings: Settings
|
||||||
private var splashScreenActive = true
|
private var splashScreenActive = true
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.S)
|
||||||
|
private val activityResultLauncher =
|
||||||
|
registerForActivityResult(StartActivityForResult()) {
|
||||||
|
requestAlarmPermissionOrAuthenticate()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
Log.init(this)
|
Log.init(this)
|
||||||
@@ -54,14 +65,30 @@ internal class InitializationActivity : AppCompatActivity() {
|
|||||||
installSplashScreen().setKeepOnScreenCondition { splashScreenActive }
|
installSplashScreen().setKeepOnScreenCondition { splashScreenActive }
|
||||||
|
|
||||||
if (settings.tokenExists()) {
|
if (settings.tokenExists()) {
|
||||||
runWithNeededPermissions {
|
runWithPostNotificationsPermission {
|
||||||
tryAuthenticate()
|
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
// Android 14 and above
|
||||||
|
requestAlarmPermissionOrAuthenticate()
|
||||||
|
} else {
|
||||||
|
// Android 13 and below
|
||||||
|
tryAuthenticate()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
showLogin()
|
showLogin()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.S)
|
||||||
|
private fun requestAlarmPermissionOrAuthenticate() {
|
||||||
|
val manager = ContextCompat.getSystemService(this, AlarmManager::class.java)
|
||||||
|
if (manager?.canScheduleExactAlarms() == true) {
|
||||||
|
tryAuthenticate()
|
||||||
|
} else {
|
||||||
|
alarmDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun showLogin() {
|
private fun showLogin() {
|
||||||
splashScreenActive = false
|
splashScreenActive = false
|
||||||
startActivity(Intent(this, LoginActivity::class.java))
|
startActivity(Intent(this, LoginActivity::class.java))
|
||||||
@@ -109,6 +136,22 @@ internal class InitializationActivity : AppCompatActivity() {
|
|||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.S)
|
||||||
|
private fun alarmDialog() {
|
||||||
|
MaterialAlertDialogBuilder(this)
|
||||||
|
.setMessage(getString(R.string.permissions_alarm_prompt))
|
||||||
|
.setPositiveButton(getString(R.string.permissions_dialog_grant)) { _, _ ->
|
||||||
|
Intent(
|
||||||
|
android.provider.Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM,
|
||||||
|
Uri.parse("package:$packageName")
|
||||||
|
).apply {
|
||||||
|
activityResultLauncher.launch(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.setCancelable(false)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
private fun authenticated(user: User) {
|
private fun authenticated(user: User) {
|
||||||
Log.i("Authenticated as ${user.name}")
|
Log.i("Authenticated as ${user.name}")
|
||||||
|
|
||||||
@@ -146,8 +189,9 @@ internal class InitializationActivity : AppCompatActivity() {
|
|||||||
.enqueue(Callback.callInUI(this, callback, errorCallback))
|
.enqueue(Callback.callInUI(this, callback, errorCallback))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runWithNeededPermissions(action: () -> Unit) {
|
private fun runWithPostNotificationsPermission(action: () -> Unit) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
// Android 13 and above
|
||||||
val quickPermissionsOption = QuickPermissionsOptions(
|
val quickPermissionsOption = QuickPermissionsOptions(
|
||||||
handleRationale = true,
|
handleRationale = true,
|
||||||
handlePermanentlyDenied = true,
|
handlePermanentlyDenied = true,
|
||||||
@@ -155,31 +199,20 @@ internal class InitializationActivity : AppCompatActivity() {
|
|||||||
permissionsDeniedMethod = { req -> processPermissionRationale(req) },
|
permissionsDeniedMethod = { req -> processPermissionRationale(req) },
|
||||||
permanentDeniedMethod = { req -> processPermissionsPermanentDenied(req) }
|
permanentDeniedMethod = { req -> processPermissionsPermanentDenied(req) }
|
||||||
)
|
)
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
runWithPermissions(
|
||||||
// Android 13 and above
|
Manifest.permission.POST_NOTIFICATIONS,
|
||||||
runWithPermissions(
|
options = quickPermissionsOption,
|
||||||
Manifest.permission.SCHEDULE_EXACT_ALARM,
|
callback = action
|
||||||
Manifest.permission.POST_NOTIFICATIONS,
|
)
|
||||||
options = quickPermissionsOption,
|
|
||||||
callback = action
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
// Android 12 and Android 12L
|
|
||||||
runWithPermissions(
|
|
||||||
Manifest.permission.SCHEDULE_EXACT_ALARM,
|
|
||||||
options = quickPermissionsOption,
|
|
||||||
callback = action
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Android 11 and below
|
// Android 12 and below
|
||||||
action()
|
action()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processPermissionRationale(req: QuickPermissionsRequest) {
|
private fun processPermissionRationale(req: QuickPermissionsRequest) {
|
||||||
MaterialAlertDialogBuilder(this)
|
MaterialAlertDialogBuilder(this)
|
||||||
.setMessage(getString(R.string.permissions_denied_temp))
|
.setMessage(getString(R.string.permissions_notification_denied_temp))
|
||||||
.setPositiveButton(getString(R.string.permissions_dialog_grant)) { _, _ ->
|
.setPositiveButton(getString(R.string.permissions_dialog_grant)) { _, _ ->
|
||||||
req.proceed()
|
req.proceed()
|
||||||
}
|
}
|
||||||
@@ -189,7 +222,7 @@ internal class InitializationActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private fun processPermissionsPermanentDenied(req: QuickPermissionsRequest) {
|
private fun processPermissionsPermanentDenied(req: QuickPermissionsRequest) {
|
||||||
MaterialAlertDialogBuilder(this)
|
MaterialAlertDialogBuilder(this)
|
||||||
.setMessage(getString(R.string.permissions_denied_permanent))
|
.setMessage(getString(R.string.permissions_notification_denied_permanent))
|
||||||
.setPositiveButton(getString(R.string.permissions_dialog_grant)) { _, _ ->
|
.setPositiveButton(getString(R.string.permissions_dialog_grant)) { _, _ ->
|
||||||
req.openAppSettings()
|
req.openAppSettings()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,8 +46,9 @@
|
|||||||
<string name="login">Login</string>
|
<string name="login">Login</string>
|
||||||
<string name="check_url">Check URL</string>
|
<string name="check_url">Check URL</string>
|
||||||
<string name="permissions_dialog_grant">Grant</string>
|
<string name="permissions_dialog_grant">Grant</string>
|
||||||
<string name="permissions_denied_temp">Gotify requires permission to display push notifications.</string>
|
<string name="permissions_notification_denied_temp">Gotify requires permission to display push notifications.</string>
|
||||||
<string name="permissions_denied_permanent">Gotify requires permission to display push notifications. Please grant the required permission in the settings.</string>
|
<string name="permissions_notification_denied_permanent">Gotify requires permission to display push notifications. Please grant the required permission in the settings.</string>
|
||||||
|
<string name="permissions_alarm_prompt">Gotify requires permission to schedule reconnecting after connection is lost.</string>
|
||||||
<string name="gotify_logo">Gotify logo</string>
|
<string name="gotify_logo">Gotify logo</string>
|
||||||
<string name="refresh_all">Refresh all</string>
|
<string name="refresh_all">Refresh all</string>
|
||||||
<string name="logout_confirm">Do you really want to logout?</string>
|
<string name="logout_confirm">Do you really want to logout?</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user