tbruyelle / RxPermissions

Android runtime permissions powered by RxJava2
Apache License 2.0
10.48k stars 1.31k forks source link

W/System.err: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState #249

Open pradipawasthi opened 6 years ago

pradipawasthi commented 6 years ago

09-15 13:31:03.381 15829-15829/com.doubtnutapp W/System.err: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at androidx.fragment.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:2091) at androidx.fragment.app.FragmentManagerImpl.ensureExecReady(FragmentManager.java:2229) at androidx.fragment.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:2249) at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:648) 09-15 13:31:03.382 15829-15829/com.doubtnutapp W/System.err: at com.tbruyelle.rxpermissions2.RxPermissions.getRxPermissionsFragment(RxPermissions.java:77) at com.tbruyelle.rxpermissions2.RxPermissions.access$000(RxPermissions.java:36) at com.tbruyelle.rxpermissions2.RxPermissions$1.get(RxPermissions.java:61) at com.tbruyelle.rxpermissions2.RxPermissions$1.get(RxPermissions.java:54) at com.tbruyelle.rxpermissions2.RxPermissions.pending(RxPermissions.java:211) at com.tbruyelle.rxpermissions2.RxPermissions.request(RxPermissions.java:200) at com.tbruyelle.rxpermissions2.RxPermissions.access$100(RxPermissions.java:36) at com.tbruyelle.rxpermissions2.RxPermissions$2.apply(RxPermissions.java:102) at io.reactivex.Observable.compose(Observable.java:6283) at com.tbruyelle.rxpermissions2.RxPermissions.request(RxPermissions.java:176) at com.doubtnutapp.ui.splash.SplashActivity.requestPermission(SplashActivity.kt:143) at com.doubtnutapp.ui.splash.SplashActivity$onStart$1.onInitFinished(SplashActivity.kt:131) at io.branch.referral.ServerRequestRegisterInstall.onRequestSucceeded(ServerRequestRegisterInstall.java:106) at io.branch.referral.Branch$BranchPostTask.onPostExecute(Branch.java:2937) at io.branch.referral.Branch$BranchPostTask.onPostExecute(Branch.java:2799) at android.os.AsyncTask.finish(AsyncTask.java:660) at android.os.AsyncTask.-wrap1(AsyncTask.java) at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:677) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:165) at android.app.ActivityThread.main(ActivityThread.java:6365) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:883) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)

Edwhis commented 6 years ago

A lot of my app users have same problem and I don't know what to do...

lovejjfg commented 6 years ago

Maybe it's better to call commitAllowingStateLoss() than commitNow() .

MrWangChong commented 6 years ago

问题解决了吗?我也遇到这个问题了

lovejjfg commented 6 years ago

I still use version 0.9.5 ,in this version, there is no this issue.

MrWangChong commented 6 years ago

Thanks, I let't delay 200 millisecond, then no problem, if has problem I'm attempt your method!

YougaKing commented 6 years ago

我fork了一份解决了这个问题,比楼上的延时处理更好 https://github.com/YougaKing/RxPermissions.git

akingyin1987 commented 6 years ago

好像没有0.9.5 这个版本的吧

akingyin1987 commented 6 years ago

我fork了一份解决了这个问题,比楼上的延时处理更好 https://github.com/YougaKing/RxPermissions.git

你是处理的哪里

YougaKing commented 6 years ago

我fork了一份解决了这个问题,比楼上的延时处理更好 https://github.com/YougaKing/RxPermissions.git

你是处理的哪里

fragment 创建时机问题,java.lang.IllegalStateException

hijamoya commented 6 years ago

Same problem here

dergod commented 6 years ago

i have this problem too

DeevD commented 6 years ago

i have problem too

tim4dev commented 6 years ago

A detailed description of the problem and what you have to do is here. https://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html

In general, the best way to avoid the exception in these cases is to simply avoid committing transactions in asynchronous callback methods all together. Google engineers seem to agree with this belief as well. According to this post on the Android Developers group, the Android team considers the major shifts in UI that can result from committing FragmentTransactions from within asynchronous callback methods to be bad for the user experience.

we have to do:

mrArtCore commented 6 years ago

@tim4dev disagree with your suggestions (but not with article). According to provided link

Use commitAllowingStateLoss() only as a last resort.

Good way of handling such situations will be dispose subscribtions to any org.reactivestreams.Publisher (e.g. Obsevable, Flowable etc) in Activity/Fragment onStop(). And if we speak about what is the best we could do with it I think in general we just don't need commit fragments transactions after onSaveInstanceState() was called.

We use a lot of Rx code in our projects and we've forgotten about described crashes since we started clear all related to screen subscribtions in onStop() (but we used to do it in onDestroy() untill SKD implementation of FragmentTransactions was changed).

tim4dev commented 5 years ago

@mrArtCore it's very good that you learned how to work with RxJava. But you can believe that none of us use calls after onSaveInstanceState, and yet the error appears. What exactly do you suggest?

mrArtCore commented 5 years ago

@tim4dev Hey, I don't like your sarcasm. First of all I tried to help. It appears that not all of users of this library quite familiar with Rx. My suggestions:

Show only stacktrace - is nothing. It's very hard understand what's going on if you will be look for problem solving without viewing from different perspectives.

This is an open source project, remember ? Nobody get paid for that fix. And if you are interested in this fix - give some help, please. Describe problem correctly!

mrArtCore commented 5 years ago

Possible duplicate of https://github.com/tbruyelle/RxPermissions/issues/132 and https://github.com/tbruyelle/RxPermissions/issues/125

imxy commented 5 years ago

so,will you change commitNow() to commitAllowingStateLoss()? @tbruyelle

stargt commented 5 years ago

Same problem. It is hard to reproduce and seems like a random error.

mrArtCore commented 5 years ago

Show us your code. Thats all. Oh, and stacktrace. And example project will be super helpful

stargt commented 5 years ago

@mrArtCore This is one of the crash logs from Crashlytics. hasRightPermission is for getting whether a permission has been granted.

Fatal Exception: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
       at android.support.v4.app.FragmentManagerImpl.checkStateLoss(Unknown Source:10)
       at android.support.v4.app.FragmentManagerImpl.ensureExecReady(Unknown Source:51)
       at android.support.v4.app.FragmentManagerImpl.execSingleAction(Unknown Source:11)
       at android.support.v4.app.BackStackRecord.commitNow(Unknown Source:6)
       at com.tbruyelle.rxpermissions2.RxPermissions.getRxPermissionsFragment(Unknown Source:24)
       at com.tbruyelle.rxpermissions2.RxPermissions.access$000(Unknown Source)
       at com.tbruyelle.rxpermissions2.RxPermissions$1.get(Unknown Source:9)
       at com.tbruyelle.rxpermissions2.RxPermissions$1.get(Unknown Source)
       at com.tbruyelle.rxpermissions2.RxPermissions.isGranted(Unknown Source:8)
       at com.testapp.TestActivity.hasRightPermission(Unknown Source:9)
       at com.testapp.TestActivity.onCreateOptionsMenu(Unknown Source:37)
       at android.app.Activity.onCreatePanelMenu(Activity.java:3567)
       at android.support.v4.app.FragmentActivity.onCreatePanelMenu(Unknown Source:2)
       at android.support.v7.view.WindowCallbackWrapper.onCreatePanelMenu(Unknown Source:2)
       at android.support.v7.app.AppCompatDelegateImpl$AppCompatWindowCallback.onCreatePanelMenu(Unknown Source:8)
       at android.support.v7.view.WindowCallbackWrapper.onCreatePanelMenu(Unknown Source:2)
       at android.support.v7.app.ToolbarActionBar.populateOptionsMenu(Unknown Source:24)
       at android.support.v7.app.ToolbarActionBar$1.run(Unknown Source:2)
       at android.os.Handler.handleCallback(Handler.java:873)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:214)
       at android.app.ActivityThread.main(ActivityThread.java:6981)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
mrArtCore commented 5 years ago

Hi @stargt ! I see you have some testapp and just may be you are able to reproduce this crash ? And what's more important that is code how you request permissions. Could you share it ?

wangjiangtao commented 5 years ago

I meet the same Exception

mrArtCore commented 5 years ago

@wangjiangtao Guys, how about to show code ? Did you check this and this comments ?

Read carefully please, and if this is doesn't solve your problems, give us yout code example.

xmc91 commented 5 years ago

我fork了一份解决了这个问题,比楼上的延时处理更好 https://github.com/YougaKing/RxPermissions.git

老哥,,,你的pull request 未被允许呀

small-tree commented 5 years ago

我也是 不提供解决方案吗

lkang08 commented 5 years ago

0.10.2 still have this problem java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at android.support.v4.app.FragmentManagerImpl.checkStateLoss(SourceFile:2080) at android.support.v4.app.FragmentManagerImpl.ensureExecReady(SourceFile:2219) at android.support.v4.app.FragmentManagerImpl.execSingleAction(SourceFile:2239) at android.support.v4.app.BackStackRecord.commitNow(SourceFile:648) at com.tbruyelle.rxpermissions2.b.b(SourceFile:77) at com.tbruyelle.rxpermissions2.b.a(SourceFile:36) at com.tbruyelle.rxpermissions2.b$1.get(SourceFile:61) at com.tbruyelle.rxpermissions2.b$1.get(SourceFile:54) at com.tbruyelle.rxpermissions2.b.isGranted(SourceFile:308) at showPermission(SourceFile:25) at .onClick(SourceFile:332) at android.view.View.performClick(View.java:6324) at android.view.View$PerformClick.run(View.java:24977) at android.os.Handler.handleCallback(Handler.java:790) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:192) at android.app.ActivityThread.main(ActivityThread.java:6814) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:818)

zhuxiaohao commented 5 years ago

This bug is also occasionally found on our side.

mrArtCore commented 5 years ago

@zhuxiaohao @lkang08 Guys, if you provide code where such error could be reproduced (with "steps to reproduce" of course), I'll try to help. This crash affected many users, as I can see now... Guys, messages and stacktraces without code where bug could be represented worth nothing. Nobody want waste so much time here. I've got idea why this crash appear (maybe it's about Permission emission without check for activeObservers) but I have no time to setup enviroment where crash could be reproduced.
Good luck!

fAntel commented 5 years ago

I don't know what to do with rx methods and I can't create example that can reproduce this exception (I've spend whole evening in tryings and can't reproduce). But exception in rx methods will be emitted into downstream and easy to catch. More important that this exception can be thrown with isGranted methos which isn't rx method. I think, for such non-rx methods creation of fragment can be replaced with ContextCompat.checkSelfPermission methods.

mrArtCore commented 4 years ago

@fAntel Your activity/fragment is not in 'right' state, I suppose. Maybe it happens when screen is rotated or something. You can add check like lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED) inside subscribe()method. Or something like this. Play around. It's hard to suggest something useful while having no idea what is going on in your code.

fAntel commented 4 years ago

@mrArtCore if we look at stack traces above we can see this line com.tbruyelle.rxpermissions2.RxPermissions.getRxPermissionsFragment It create fragment inside library code. Even on non-rx methods like isGranted. And I suggest to swap this with ContextCompat.checkSelfPermission call inside library code. As workaround I've already swaped all RxPermissions.isGranted calls with ContextCompat.checkSelfPermission in my app because error in rx pipeline will be consumed at onError method in subscribe but non-rx call RxPermission.isGranted if called at main thread will lead to crash.

GensaGames commented 4 years ago

@fAntel Thanks for suggestion. Still trying to stick to the library. But don't understand why, for calling three functions, which already implemented in AppCompat.

hoanghiephui commented 4 years ago

Wow

dengzhi00 commented 4 years ago

在 activity 的oncreate的时候就先使用rxpermission 把RxPermissionsFragment 的实例初始化并与当前activity相绑定就行,因为在RxPermissions的getRxPermissionsFragment中会做判断,判断该RxPermissionsFragment是否被初始化

unweixiaoyy commented 4 years ago

You can use try catch,able to handle some scenarios.

VuHongKy commented 3 years ago

@mrArtCore Sorry for trouble you, but please check my case: My steps is following: Load API -> request RxPermission -> Crash with same log:

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
        at androidx.fragment.app.FragmentManager.checkStateLoss(FragmentManager.java:1703)
        at androidx.fragment.app.FragmentManager.ensureExecReady(FragmentManager.java:1806)
        at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1826)
        at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:297)
        at com.tbruyelle.rxpermissions3.RxPermissions.getRxPermissionsFragment(RxPermissions.java:78)
        at com.tbruyelle.rxpermissions3.RxPermissions.access$000(RxPermissions.java:37)
        at com.tbruyelle.rxpermissions3.RxPermissions$1.get(RxPermissions.java:62)
        at com.tbruyelle.rxpermissions3.RxPermissions$1.get(RxPermissions.java:55)
        at com.tbruyelle.rxpermissions3.RxPermissions.pending(RxPermissions.java:212)
        at com.tbruyelle.rxpermissions3.RxPermissions.request(RxPermissions.java:201)
        at com.tbruyelle.rxpermissions3.RxPermissions.access$100(RxPermissions.java:37)
        at com.tbruyelle.rxpermissions3.RxPermissions$4.apply(RxPermissions.java:156)
        at io.reactivex.rxjava3.core.Observable.compose(Observable.java:6765)
        at com.tbruyelle.rxpermissions3.RxPermissions.requestEachCombined(RxPermissions.java:194)

My problem is when loading API -> user move app to background -> RxPermission called on background -> so crash happened!

So what should I do? Should I check if app is background and wait until app resume, then call RxPermisson?

arronvera commented 3 years ago

Can not perform this action after onSaveInstanceState

com.tbruyelle.rxpermissions2.RxPermissions.getRxPermissionsFragment

arronvera commented 3 years ago

how to solve it?

arronvera commented 3 years ago

@mrArtCore Sorry for trouble you, but please check my case: My steps is following: Load API -> request RxPermission -> Crash with same log:

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
        at androidx.fragment.app.FragmentManager.checkStateLoss(FragmentManager.java:1703)
        at androidx.fragment.app.FragmentManager.ensureExecReady(FragmentManager.java:1806)
        at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1826)
        at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:297)
        at com.tbruyelle.rxpermissions3.RxPermissions.getRxPermissionsFragment(RxPermissions.java:78)
        at com.tbruyelle.rxpermissions3.RxPermissions.access$000(RxPermissions.java:37)
        at com.tbruyelle.rxpermissions3.RxPermissions$1.get(RxPermissions.java:62)
        at com.tbruyelle.rxpermissions3.RxPermissions$1.get(RxPermissions.java:55)
        at com.tbruyelle.rxpermissions3.RxPermissions.pending(RxPermissions.java:212)
        at com.tbruyelle.rxpermissions3.RxPermissions.request(RxPermissions.java:201)
        at com.tbruyelle.rxpermissions3.RxPermissions.access$100(RxPermissions.java:37)
        at com.tbruyelle.rxpermissions3.RxPermissions$4.apply(RxPermissions.java:156)
        at io.reactivex.rxjava3.core.Observable.compose(Observable.java:6765)
        at com.tbruyelle.rxpermissions3.RxPermissions.requestEachCombined(RxPermissions.java:194)

My problem is when loading API -> user move app to background -> RxPermission called on background -> so crash happened!

So what should I do? Should I check if app is background and wait until app resume, then call RxPermisson?

have you solved it?

kashyap-das commented 2 years ago

RxPermissions Class constructor creates a fragment; In order to commit the fragment transaction, the activity from which the fragment was supposed to be created must be in the foreground. image

The onSaveInstanceState method is called right before the onStop method. If a fragment transaction is committed after onSaveInstanceState, Error Cannot perform this action will be thrown.

Solution:

  1. If you are using ComponentActivity or any activity that is inherited from ComponentActivity (ie. FragmentActiviy or AppCompatActivity), can use the getLifecycle method of the activity using androidx.lifecycle library.

if (this?.lifecycle?.currentState?.isAtLeast(Lifecycle.State.RESUMED) == true) new RxPermissions(activity)

Alternatively, we can use a boolean to keep track of activity lifecycles if the androidx.lifecycle library is not added in your project!

  1. This library has to update the code in RxPermissions.getRxPermissionsFragment from commitNow() to commitAllowingStateLoss(). Understand the difference from here
mrArtCore commented 2 years ago

Try unsubscribe from the stream whenever the state is saved -> onSaveInstanceState is called. I suggest you do it in fragment/activity#onStop() callback and you will be good to go.

KarisionGou commented 10 months ago

Solution:https://gitee.com/karisiongou/rx-perssmisions.git