RaiseToAnswer icon indicating copy to clipboard operation
RaiseToAnswer copied to clipboard

App not compatible with Android 12

Open TheLastProject opened this issue 2 years ago • 11 comments

After updating targetSdkVersion to 31, the app crashes on an incoming call.

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: me.hackerchick.raisetoanswer, PID: 6271
    java.lang.RuntimeException: Unable to start receiver me.hackerchick.raisetoanswer.RaiseToAnswerCallReceiver: android.app.ForegroundServiceStartNotAllowedException: startForegroundService() not allowed due to mAllowStartForeground false: service me.hackerchick.raisetoanswer/.RaiseToAnswerSensorEventListener
        at android.app.ActivityThread.handleReceiver(ActivityThread.java:4357)
        at android.app.ActivityThread.access$1600(ActivityThread.java:256)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2101)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7842)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
     Caused by: android.app.ForegroundServiceStartNotAllowedException: startForegroundService() not allowed due to mAllowStartForeground false: service me.hackerchick.raisetoanswer/.RaiseToAnswerSensorEventListener
        at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:54)
        at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:50)
        at android.os.Parcel.readParcelable(Parcel.java:3333)
        at android.os.Parcel.createExceptionOrNull(Parcel.java:2420)
        at android.os.Parcel.createException(Parcel.java:2409)
        at android.os.Parcel.readException(Parcel.java:2392)
        at android.os.Parcel.readException(Parcel.java:2334)
        at android.app.IActivityManager$Stub$Proxy.startService(IActivityManager.java:6028)
        at java.lang.reflect.Method.invoke(Native Method)
        at leakcanary.ServiceWatcher$install$4$2.invoke(ServiceWatcher.kt:93)
        at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
        at $Proxy3.startService(Unknown Source)
        at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1847)
        at android.app.ContextImpl.startForegroundService(ContextImpl.java:1823)
        at android.content.ContextWrapper.startForegroundService(ContextWrapper.java:779)
        at android.content.ContextWrapper.startForegroundService(ContextWrapper.java:779)
        at me.hackerchick.raisetoanswer.Util$Companion.startSensorListener(Util.kt:176)
        at me.hackerchick.raisetoanswer.RaiseToAnswerCallReceiver.onReceive(RaiseToAnswerCallReceiver.kt:18)
        at android.app.ActivityThread.handleReceiver(ActivityThread.java:4348)
        at android.app.ActivityThread.access$1600(ActivityThread.java:256) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2101) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loopOnce(Looper.java:201) 
        at android.os.Looper.loop(Looper.java:288) 
        at android.app.ActivityThread.main(ActivityThread.java:7842) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003) 
     Caused by: android.os.RemoteException: Remote stack trace:
        at com.android.server.am.ActiveServices.startServiceLocked(ActiveServices.java:692)
        at com.android.server.am.ActiveServices.startServiceLocked(ActiveServices.java:617)
        at com.android.server.am.ActivityManagerService.startService(ActivityManagerService.java:11876)
        at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:2542)
        at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2516)

TheLastProject avatar Apr 29 '22 13:04 TheLastProject

This will prevent updating on Google Play starting November 1st, 2022 and completely block new installs on Google Play starting November 1st, 2023 as per https://support.google.com/googleplay/android-developer/answer/11926878.

https://github.com/TheLastProject/RaiseToAnswer/issues/34 might be the best fix.

TheLastProject avatar May 02 '22 15:05 TheLastProject

Hey I think I can help you with this issue, can you assign this to me ?

dinesh-thiyagarajan avatar Oct 22 '22 03:10 dinesh-thiyagarajan

Sure, good luck! I've gotten fairly stuck with this issue myself so hopefully you'll fare better :)

TheLastProject avatar Oct 22 '22 10:10 TheLastProject

Hey @TheLastProject I ran the app and tested in Android 13 but the app is not crashing.Tried for both background and foreground mode as well. Its working well :)

dinesh-thiyagarajan avatar Oct 22 '22 11:10 dinesh-thiyagarajan

The problem is that it's running in compatibility mode (targetSdk 30, so Android 11). Running it natively on Android 12 (by increasing targetSdk in app/build.gradle) makes it crash. Running in compatibility mode, even though it works fine, is not allowed on Google Play and will get the app removed (see the link posted above). It needs to be made to natively work with newer versions.

TheLastProject avatar Oct 22 '22 11:10 TheLastProject

Cool got it !!

dinesh-thiyagarajan avatar Oct 22 '22 11:10 dinesh-thiyagarajan

Hey, I tried converting the foreground service into work manager due to the foreground service restrictions on android 12, but workmanager comes with certain conditions to be satisfied for the system to allow it to keep running, ex: battery level, charging status etc.. which won't be suitable for our case in which the work needs to run indefinitely and keep listening to incoming calls.

And as you mentioned implementing the IncallService will be a good idea, but then that needs the app to be converted to a dialler app. which must fully implement the InCallService API and provide both an incoming call UI, as well as an ongoing call UI. Im not sure if that's what you wanted to do. @TheLastProject

dinesh-thiyagarajan avatar Oct 24 '22 13:10 dinesh-thiyagarajan

So there's no way to start a workmanager when the PHONE_STATE intent gets delivered?

Having to build a full new UI seems like quite overkill and like it will just make the app worse for everyone. If you feel like it you're free to try and I'll take a look and mark it hacktoberfest-accepted if the code is decent, but I'm not quite sure if I'll release it (maybe just keep it ready until it's about to get kicked out of Google Play and release it on F-Droid as a non-recommended version)

I guess Google has really actively killed the one API that made apps like this useful :(

TheLastProject avatar Oct 24 '22 17:10 TheLastProject

@TheLastProject We can start the work manager immediately once we receive the broadcast which is working fine while the app is in the foreground (tested in android 13 as well 😃), but the problem is once the app goes into the background according to the documentation

On devices running Android 9 (API level 28) or higher, apps running in the background have the following restrictions:

Sensors that use the continuous reporting mode, such as accelerometers and gyroscopes, don't receive events. Sensors that use the on-change or one-shot reporting modes don't receive events. Given these restrictions, it's best to detect sensor events either when your app is in the foreground or as part of a foreground service.

So we are not receiving on-change events if the app is in the background. I tried setting up the workManager with setForeground method, but that as well didn't work :( will see if its possible to get sensor events inside a workManager while app being in the background and raise a PR if it works

dinesh-thiyagarajan avatar Oct 26 '22 09:10 dinesh-thiyagarajan

If moving to the foreground doesn't work, I guess it would be possible to keep a "Raise To Answer is watching for phone calls" notification visible 24/7 and explain users when they tap it why it exists. It sucks both UI-wise and battery usage-wise (because now Raise To Answer has to run 24/7 instead of activating when a call comes in), but well, this is what Google has forced upon apps then.

TheLastProject avatar Oct 26 '22 16:10 TheLastProject

@TheLastProject Hey have raised a PR for this bug with a fix.

By asking the user to exclude the app from battery optimisations, which enabled the existing foreground service to be initiated from the background. I feel this maybe a better fix since we don't keep the service running indefinitely in the background and only start it on receiving the broadcast and stop it on pickup or decline.

however there is a catch

Google Play policies prohibit apps from requesting direct exemption from Power Management features in Android 6.0+ (Doze and App Standby) unless the core function of the app is adversely affected.

If google reaches out we should be able to explain that without this fix the core functionality of the app will be affected, you can check the documentation here for details. and these are the acceptable usecases where we can use ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS

I hope this helps :)

dinesh-thiyagarajan avatar Oct 27 '22 03:10 dinesh-thiyagarajan