diff --git a/android/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.kt b/android/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.kt index 10a6fcf..6f0846c 100644 --- a/android/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.kt +++ b/android/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.kt @@ -823,8 +823,10 @@ open class DailyNotificationPlugin : Plugin() { * Check if exact alarm permission can be requested * Helper method that handles API level differences * - * Uses reflection to call Settings.canRequestScheduleExactAlarms() on Android 13+ - * to avoid compilation issues with newer APIs. + * On Android 12 (API 31-32): Permission can always be requested + * 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 * @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) { // Android 12+ (API 31+) 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 getMethod first (for public static methods) val method = Settings::class.java.getMethod( "canRequestScheduleExactAlarms", 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) { - Log.e(TAG, "Failed to check exact alarm permission using reflection", e) - // Fallback to allowing request (safe default) - true + Log.w(TAG, "Failed to invoke canRequestScheduleExactAlarms(), using heuristic", e) + // Fallback heuristic: if exact alarms are not currently allowed, + // assume we can request them (safe default) + return !canScheduleExactAlarms(context) } } else { // Android 12 (API 31-32) - permission can always be requested