ChristopherRogers1991 / ExerciseReminders

Android notifications to do simple exercises at regular intervals
GNU General Public License v3.0
3 stars 0 forks source link

App crashes on licence agreement #8

Closed fangly closed 2 weeks ago

fangly commented 3 weeks ago

When the licence agreement dialog opens and I press on "I agree", the app closes/crashes. I am running version 1.7.0 of the app, on a Samsung Galaxy A52S using Android 14.

ChristopherRogers1991 commented 3 weeks ago

Hello @fangly,

Thank you for reporting the issue. I checked the Google Play console, and do not see any crashes listed there, so I assume you have installed via an alternative means, such as the F-Droid store, or using the APK directly. Is that correct?

If so, would you be willing to install LogCat Reader, and send me the logs from a crash? You can filter the logs to just those referencing 'exercisereminders', and upload them here.

I am also on Android 14, but am unable to reproduce the issue, so to troubleshoot/fix, I will need your logs.

-Chris

fangly commented 3 weeks ago

Yes, I installed the app using F-Droid. Here are the logs: logcat_06-16-2024_15-34-23.txt

ChristopherRogers1991 commented 3 weeks ago

Thanks! Here's the exception I see:

FATAL EXCEPTION: main
Process: nodo.crogers.exercisereminders, PID: 16700
java.lang.RuntimeException: Unable to start receiver nodo.crogers.exercisereminders.BootReceiver: java.lang.SecurityException: Caller nodo.crogers.exercisereminders needs to hold android.permission.SCHEDULE_EXACT_ALARM or android.permission.USE_EXACT_ALARM to set exact alarms.
    at android.app.ActivityThread.handleReceiver(ActivityThread.java:4905)
    at android.app.ActivityThread.-$$Nest$mhandleReceiver(Unknown Source:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2498)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:230)
    at android.os.Looper.loop(Looper.java:319)
    at android.app.ActivityThread.main(ActivityThread.java:8893)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
Caused by: java.lang.SecurityException: Caller nodo.crogers.exercisereminders needs to hold android.permission.SCHEDULE_EXACT_ALARM or android.permission.USE_EXACT_ALARM to set exact alarms.
    at android.os.Parcel.createExceptionOrNull(Parcel.java:3069)
    at android.os.Parcel.createException(Parcel.java:3053)
    at android.os.Parcel.readException(Parcel.java:3036)
    at android.os.Parcel.readException(Parcel.java:2978)
    at android.app.IAlarmManager$Stub$Proxy.set(IAlarmManager.java:347)
    at android.app.AlarmManager.setImpl(AlarmManager.java:1113)
    at android.app.AlarmManager.setImpl(AlarmManager.java:1073)
    at android.app.AlarmManager.setExactAndAllowWhileIdle(AlarmManager.java:1341)
    at nodo.crogers.exercisereminders.ExerciseAlarm.scheduleNext(ExerciseAlarm.java:104)
    at nodo.crogers.exercisereminders.BootReceiver.onReceive(BootReceiver.java:11)
    at android.app.ActivityThread.handleReceiver(ActivityThread.java:4896)
    ... 9 more

The specific line that matters is:

java.lang.SecurityException: Caller nodo.crogers.exercisereminders needs to hold android.permission.SCHEDULE_EXACT_ALARM or android.permission.USE_EXACT_ALARM to set exact alarms.

It's complaining about not having permission to set alarms for exact times, but that permission is actually specified in the manifest:

https://github.com/ChristopherRogers1991/ExerciseReminders/blob/818fdda421159a45dc0544248aaa9179b0d99ccf/app/src/main/AndroidManifest.xml#L8

Note that 'alarm' just means scheduled code execution - not necessarily a ringing of the device. In this app's case, it just selects an exercise and shows you a notification on a schedule - it doesn't ever blast your alarm ringer.

The permission in the manifest has been there since before version 1.0.0, so I don't think it's related to the version (1.7.0 is the latest, if you do care to check).

My phone (I just confirmed again that it is running Android 14) has never had a problem with this app, but according to this article, there may have been a change in Android that requires asking the user for this permission (vs having the system grant it, simply for having it in the manifest). Could you check the app's permissions in the settings, and see if there is a toggle related to setting alarms?

If so, if you could toggle it on and try again, I think that would resolve the issue. If that works, I can update the app to add a permissions request pop-up on first launch, so future users don't have to go to the settings.

If there is no alarm permission toggle:

Can I ask what type of phone you are using? Some manufacturers make tweaks to the way alarms work, in an attempt to squeeze out as much battery life as possible. If I know the exact type of phone, I might be able to find a workaround.


As a note, android provides a way to schedule inexact alarms that does not require special permissions. This is how I initially wrote the code, but on my Samsung Galaxy phone, the (non-configurable) Samsung battery optimizations meant the phone never woke up to deliver the notification. It was only when the phone was manually woken up (e.g. via pressing the power button) that I would see the notifications had been delivered. This was the forcing function to require the extra permission, and use the exact alarm functionality. The irony that the Samsung optimizations break the default Android optimizations, and ultimately require the use of something less battery efficient* is frustrating, to say the least.

*Note the app won't wake the device up more than the schedule set by you, so the battery hit is extremely minimal, and unlikely to be noticed. For each notification, I would expect the battery hit to be less than receiving a text message.

ChristopherRogers1991 commented 3 weeks ago

I created a new emulator, with a higher SDK version, and was able to reproduce the issue. It looks like it is probably that the app relied on the implicit grant of the permission, which Google has now changed to require user approval. My phone probably did not have a problem because it upgraded to Android 14 after I had already installed the app, and it had already been granted the permission.

I'm working to see if I can resolve it, such that it asks the user for permission, but this seems to be handled differently than other permissions, so the workflow I am used to does not work.

Through some more research and testing, I found that the permission can be manually granted, but not in the normal app permissions settings - if you'd like to set it, open your settings, and search for 'alarm'. There should be an 'Alarms & Reminders' section in the 'Special App Access' section. If you click that, you can manually grant the app the permission it needs. The screenshots below show the process:





fangly commented 3 weeks ago

Hi Chris, I edited my first post to mention my device and the app version. But as you found out by yourself, it is a permission issue. I followed the procedure you described for 'Special App Access' and this fixed the issue. Thanks! Ironically, out of all the apps listed under this section, only 'Exercise Reminders' was unchecked. Best, Florent

ChristopherRogers1991 commented 2 weeks ago

Thanks! I just tagged a release (https://github.com/ChristopherRogers1991/ExerciseReminders/releases/tag/1.7.1) that should handle this correctly for users going forward. Users on versions of android supporting API levels >= 33 should now get an additional pop-up alerting them they need to grant permission to schedule exact reminders, and then will be taken to the settings to enable it (for whatever reason, this is a special permission that can't be handled in the app, in the same way as the notifications permission).

I've pushed the release to Google, and F-Droid should pick it up automatically. Both should be live within about a week.

Thanks very much for your help, @fangly. I really appreciate you reporting the issue, and testing the work around.