RxPermissions: Crash on rotation
Hey there,
First of all nice work. Sadly I have to say that your solution currently does not work with rotation changes. Simply press “Enable Camera”, rotate your device and press “DENY” on the popup. This will result in the following crash:
"09-30 23:42:06.090 31948-31948/com.tbruyelle.rxpermissions.sample E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.tbruyelle.rxpermissions.sample, PID: 31948
java.lang.RuntimeException: Failure delivering result ResultInfo{who=@android:requestPermissions:, request=463403621, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }} to activity {com.tbruyelle.rxpermissions.sample/com.tbruyelle.rxpermissions.sample.MainActivity}: java.lang.IllegalStateException: RxPermission.onRequestPermissionsResult invoked but didn't find the corresponding permission request.
at android.app.ActivityThread.deliverResults(ActivityThread.java:3699)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
at android.app.ActivityThread.-wrap16(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.IllegalStateException: RxPermission.onRequestPermissionsResult invoked but didn't find the corresponding permission request.
at com.tbruyelle.rxpermissions.RxPermissions.onRequestPermissionsResult(RxPermissions.java:123)
at com.tbruyelle.rxpermissions.sample.MainActivity.onRequestPermissionsResult(MainActivity.java:36)
at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:6553)
at android.app.Activity.dispatchActivityResult(Activity.java:6432)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3695)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
at android.app.ActivityThread.-wrap16(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Do you have any ideas how to tackle this problem?
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Comments: 47 (20 by maintainers)
@dlew Actually with the shadow activity introduced in version 0.2.0, we have such tool ! Nice.
About 3, I have no control on the runtime permission request (other than create a new one), I can’t cancel or resume it. The permission request is resumed automatically after a configuration change.
Anyway, a solution begins to take shape :
RxPermissionsregisters a subject associated with that permission and requests the framework : the runtime permission popup appears.RxPermissionsunsubscribes all registered subjects, but keeps in memory the pending requests. It will survive the configuration change because it’s a singleton since 0.2.0. The runtime permissions popup is paused and will be resumed automatically.RxPermissionsremembers a pending request has been done for this permission, and registers a new subject for it, but doesn’t request the framework a second time (otherwise the result would be another runtime permissions popup). The runtime permissions popup is resumed and displayed again.RxPermissions.onRequestPermissionsResultis invoked, the lib finds the corresponding subject and emits the user response.That sounds not bad…
IMO, if you want an
Observable-based solution, there are two things you’ll need to do:onSaveInstanceState()(in aParcelableor similar) and restore it again inonCreate().If you do the first step, then you can skip having to store the
Observablealtogether since you could just create a new one on recreation. It also gets rid of the need for a singleton.As for why the second is necessary: The core problem is that you want a
Subscriptionto outlast theActivitylifecycle, which just isn’t going to happen. Even if you persist theObservable, theSubscriptionwill necessarily need to be recreated along with the newActivity, since the oldSubscriberwill have no references to the newActivity.(You could try to reattach the
Subscriberto the newActivitybut in what way is that better than simply recreating theSubscription?)Of course this comes with all sorts of anti-fun changes to this lib, since users would have to implement
onSaveInstanceState()and resubscription themselves.FWIW, this is why I ended up not going the
Observableroute for my own permission handling code. I’m not saying this library isn’t feasible, but there’s a lot of plumbing necessary due to the lack of goodActivity/Fragmentlifecycle listeners.