fix(android): improve exact alarm permission check with fallback strategies
Fix reflection-based permission check that was failing with NoSuchMethodException. Add multiple fallback strategies to ensure permission check works reliably. Changes: - Add getDeclaredMethod() fallback when getMethod() fails - Add heuristic fallback: if exact alarms not allowed, assume they can be requested - Improve error handling: catch NoSuchMethodException separately from other exceptions - Add debug logging to track which reflection path is taken - Change reflection failure log level from ERROR to WARNING (we have fallback) The heuristic fallback is safe because: - If exact alarms are not currently allowed, we should try to request them - Only edge case is permanently denied (rare), worst case is unnecessary Settings redirect - Better than failing silently or blocking permission requests Fixes reflection failures seen in logcat where Settings.canRequestScheduleExactAlarms() method lookup was failing, causing unnecessary Settings redirects.
This commit is contained in:
@@ -823,8 +823,10 @@ open class DailyNotificationPlugin : Plugin() {
|
|||||||
* Check if exact alarm permission can be requested
|
* Check if exact alarm permission can be requested
|
||||||
* Helper method that handles API level differences
|
* Helper method that handles API level differences
|
||||||
*
|
*
|
||||||
* Uses reflection to call Settings.canRequestScheduleExactAlarms() on Android 13+
|
* On Android 12 (API 31-32): Permission can always be requested
|
||||||
* to avoid compilation issues with newer APIs.
|
* On Android 13+ (API 33+): Uses reflection to call Settings.canRequestScheduleExactAlarms()
|
||||||
|
* If reflection fails, falls back to heuristic: if exact alarms are not currently allowed,
|
||||||
|
* we assume they can be requested (safe default).
|
||||||
*
|
*
|
||||||
* @param context Application context
|
* @param context Application context
|
||||||
* @return true if permission can be requested, false if permanently denied
|
* @return true if permission can be requested, false if permanently denied
|
||||||
@@ -833,17 +835,39 @@ open class DailyNotificationPlugin : Plugin() {
|
|||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
// Android 12+ (API 31+)
|
// Android 12+ (API 31+)
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
// Android 13+ (API 33+) - use reflection to call canRequestScheduleExactAlarms
|
// Android 13+ (API 33+) - try reflection to call canRequestScheduleExactAlarms
|
||||||
try {
|
try {
|
||||||
|
// Try getMethod first (for public static methods)
|
||||||
val method = Settings::class.java.getMethod(
|
val method = Settings::class.java.getMethod(
|
||||||
"canRequestScheduleExactAlarms",
|
"canRequestScheduleExactAlarms",
|
||||||
Context::class.java
|
Context::class.java
|
||||||
)
|
)
|
||||||
method.invoke(null, context) as Boolean
|
val result = method.invoke(null, context) as Boolean
|
||||||
|
Log.d(TAG, "canRequestScheduleExactAlarms() returned: $result")
|
||||||
|
return result
|
||||||
|
} catch (e: NoSuchMethodException) {
|
||||||
|
// Method not found - try getDeclaredMethod as fallback
|
||||||
|
try {
|
||||||
|
val method = Settings::class.java.getDeclaredMethod(
|
||||||
|
"canRequestScheduleExactAlarms",
|
||||||
|
Context::class.java
|
||||||
|
)
|
||||||
|
method.isAccessible = true
|
||||||
|
val result = method.invoke(null, context) as Boolean
|
||||||
|
Log.d(TAG, "canRequestScheduleExactAlarms() (via getDeclaredMethod) returned: $result")
|
||||||
|
return result
|
||||||
|
} catch (e2: Exception) {
|
||||||
|
Log.w(TAG, "Failed to check exact alarm permission using reflection, using heuristic", e2)
|
||||||
|
// Fallback heuristic: if exact alarms are not currently allowed,
|
||||||
|
// assume we can request them (safe default)
|
||||||
|
// Only case where we can't request is if permanently denied, which is rare
|
||||||
|
return !canScheduleExactAlarms(context)
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Failed to check exact alarm permission using reflection", e)
|
Log.w(TAG, "Failed to invoke canRequestScheduleExactAlarms(), using heuristic", e)
|
||||||
// Fallback to allowing request (safe default)
|
// Fallback heuristic: if exact alarms are not currently allowed,
|
||||||
true
|
// assume we can request them (safe default)
|
||||||
|
return !canScheduleExactAlarms(context)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Android 12 (API 31-32) - permission can always be requested
|
// Android 12 (API 31-32) - permission can always be requested
|
||||||
|
|||||||
Reference in New Issue
Block a user