Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: Unexplained crashes when the app is reopened after a while

I have a bunch of activities A->B->C->D and they all work well. I have tested them with and without internet, multiple configurations and I have triggered the screen to rotate in every of them to see if they would crash. They didn't

But on my Android phone (not emulator), after a while that the app is in the background, if I open it back (either by recents or by my main menu), I get a series of unexplicable crashes. It's literally activity D crashes, goes to C. C crashes, goes to B. B crashes, goes to A. A crashes, resets, and opens fine. It drives me nuts.

It's always NullPointerException on objects, like these ones:

java.lang.RuntimeException: Unable to start activity ComponentInfo{net.getfoodie.foodie/net.getfoodie.foodie.ui.exploremenu.MenuFragmentActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2305)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2363)
at android.app.ActivityThread.access$900(ActivityThread.java:161)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1265)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at net.getfoodie.foodie.ui.exploremenu.MenuGridAdapter.<init>(MenuGridAdapter.java:71)
at net.getfoodie.foodie.ui.exploremenu.MenuFragment.onActivityCreated(MenuFragment.java:75)
at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1794)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:967)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1126)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1108)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1917)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:544)
at net.getfoodie.foodie.ui.exploremenu.MenuFragmentActivity.onStart(MenuFragmentActivity.java:89)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1189)
at android.app.Activity.performStart(Activity.java:5436)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
... 12 more 

And for example, the error above is because of a null object from the parse sdk. But the object has already been fetched during the OnCreate of the activity, and I guess it gets lost when the activity is recreated? although I make sure that I fetch it in my OnCreate(), and I tested the rotation?

What do you think this is due to? Am I missing something in my app lifecycle?

And more importantly, how can I trigger the "activity kill/sleep" on my Android emulator so I can reproduce the issue and actually try to fix it?

like image 948
Stephane Maarek Avatar asked Oct 31 '22 08:10

Stephane Maarek


1 Answers

Activities not on screen are frequently killed by Android for memory. When coming back to an Activity via recents, the most recent activity will be launched but if it was killed it will have no context- it will get the intent it was launched with but have no static variables or singletons assigned to previous values. This causes problems for a lot of apps. The solution is to either allow any activity to fill out these values somehow, or to detect this case and launch an appropriate activity with CLEAR_TOP set to kill the old state.

Oh, and to reproduce it all you need is force stop from the activites manager settings. Go to activity D, then force stop. Then return via recents.

As an example- I have an app with a LoginActivity, and a MainActivity. MainActivity assumes LoginActivity has set up a user singleton. My code in MainActivity is:

public void onCreate(Bundle bundle){
  super.onCreate(bundle);
  if(User.getCurrentUser() == null){
    Intent intent = new Intent(this, LoginActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    startActivity(intent);
    finish();
    return;
  }
  //Continue on with onCreate for this activity
}

This will relaunch the login activity if the User object wasn't set up.

like image 101
Gabe Sechan Avatar answered Nov 05 '22 18:11

Gabe Sechan