Skip to content
This repository has been archived by the owner on Feb 4, 2024. It is now read-only.

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

Open
pradipawasthi opened this issue Sep 15, 2018 · 43 comments

Comments

@pradipawasthi
Copy link

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
Copy link

Edwhis commented Sep 15, 2018

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

@lovejjfg
Copy link

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

@MrWangChong
Copy link

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

@lovejjfg
Copy link

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

@MrWangChong
Copy link

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

@YougaKing
Copy link

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

@akingyin1987
Copy link

好像没有0.9.5 这个版本的吧

@akingyin1987
Copy link

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

你是处理的哪里

@YougaKing
Copy link

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

你是处理的哪里

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

@hijamoya
Copy link

Same problem here

@dergod
Copy link

dergod commented Nov 27, 2018

i have this problem too

@DeevD
Copy link

DeevD commented Nov 28, 2018

i have problem too

@tim4dev
Copy link

tim4dev commented Nov 28, 2018

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:

  • either make a blocking call: blockingSubscribe()
  • either use: commitAllowingStateLoss()

@mrArtCore
Copy link

mrArtCore commented Nov 29, 2018

@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
Copy link

tim4dev commented Dec 7, 2018

@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
Copy link

mrArtCore commented Dec 7, 2018

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

  • give comprehensive example of your code or which is better link to sample project where this crash could be reproduced with more than 50% of success.
  • describe steps to reproduce
  • some additional info, that might be handy.

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
Copy link

mrArtCore commented Dec 7, 2018

Possible duplicate of #132 and #125

@imxy
Copy link

imxy commented Jan 17, 2019

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

@stargt
Copy link

stargt commented Feb 20, 2019

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

@mrArtCore
Copy link

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

@stargt
Copy link

stargt commented Apr 1, 2019

@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
Copy link

mrArtCore commented Apr 1, 2019

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
Copy link

I meet the same Exception

@mrArtCore
Copy link

@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
Copy link

xmc91 commented Apr 8, 2019

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

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

@small-tree
Copy link

我也是 不提供解决方案吗

@lkang08
Copy link

lkang08 commented Jul 23, 2019

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
Copy link

This bug is also occasionally found on our side.

@mrArtCore
Copy link

mrArtCore commented Oct 16, 2019

@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
Copy link

fAntel commented Nov 28, 2019

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
Copy link

@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
Copy link

fAntel commented Dec 5, 2019

@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
Copy link

@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
Copy link

Wow

@dengzhi00
Copy link

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

@unweixiaoyy
Copy link

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

@VuHongKy
Copy link

@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
Copy link

Can not perform this action after onSaveInstanceState

com.tbruyelle.rxpermissions2.RxPermissions.getRxPermissionsFragment

@arronvera
Copy link

how to solve it?

@arronvera
Copy link

@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
Copy link

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
Copy link

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
Copy link

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests