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)

Most upvoted comments

@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 :

  1. a permission request is triggered : RxPermissions registers a subject associated with that permission and requests the framework : the runtime permission popup appears.
  2. a configuration change occurs : RxPermissions unsubscribes 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.
  3. the app restarts : The permission request is redone by the app (this is actually the only requirement, but as @dlew said it’s a logical outcome), RxPermissions remembers 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.
  4. user answers to the permission request : RxPermissions.onRequestPermissionsResult is 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:

  1. Persist request state in onSaveInstanceState() (in a Parcelable or similar) and restore it again in onCreate().
  2. Require re-subscription on recreation.

If you do the first step, then you can skip having to store the Observable altogether 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 Subscription to outlast the Activity lifecycle, which just isn’t going to happen. Even if you persist the Observable, the Subscription will necessarily need to be recreated along with the new Activity, since the old Subscriber will have no references to the new Activity.

(You could try to reattach the Subscriber to the new Activity but in what way is that better than simply recreating the Subscription?)


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 Observable route 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 good Activity/Fragment lifecycle listeners.