2

EDIT:

So this post was about how to fast load the Android OS to have my application restart a certain way when I call it from background with the restart path, in order to debug an occasional crash on restart from background I provide below what I have understand/guess about this topic with no guarantee at all

I saw 3 states when the application is in the background:

  • the application was 'just' send to background and when you call it back, it reappears effortless (all is still in memory)

  • The app has spent quite time in background and/or the android OS has been stressed enough, for me, starting heavy game (eufloria, browsing one thousand pictures literally, looking at groupon & Gmail did the trick). In this case, it is call back from background and the OS tries to bring the last view to the front and call onRestoreSavedInstance().

  • Too much time in background, or crash, or huge loads... Anyway, your application restart totally when called from background (onRestoreSavedInstance() is not called at all, but the onCreate and Cie without a savedinstance Bundle).

The trick is to save whatever you think might been deleted in case 2 in onSavedInstance() and retrieve it in onRestoreSavedInstance(). But you have to call these saved variables, attributes, parameters AFTER the onStart() methods (of your fragment sure, activity maybe). This is mandatory because the onRestoreSavedInstance() method is called pretty late in the process: after Activity's onStart(). Cf google documentation on this:

Instead of restoring the state during onCreate() you may choose to implement onRestoreInstanceState(), which the system calls after the onStart() method. The system calls onRestoreInstanceState() only if there is a saved state to restore, so you do not need to check whether the Bundle is null:

So you cannot refer to anything before the onResume() method of your fragment due to the relationship between fragment and activity life-cycle: http://www.linuxforu.com/2011/05/android-fragments-api/

There it is, eventual corrector welcome :)
Thx to david

/****** EDIT fin *****/

The application I have to upgraded (helping friends with their start-up) crashed when coming back from background if it is in background for a sufficient time. It is okay if:

  • I kill it from App manager
  • I kill it from long press on home button
  • I call it back after using several others applications (eufloria, temple run 2, gmail, endomondo)
  • all cases I have found on the internet or think of it.

The only way it crashed is coming for background after such time. This issue has been also reported by two customers.

I have read several posts on these subjects and the Google documentation, especially this one from /u/CommonsWare How to emulate unloading of a background application by Android OS? But also these How do you simulate low memory in the Android emulator? https://groups.google.com/forum/?fromgroups#!topic/android-platform/nifVOvknFsU

I really wish some help even if it is not very critical in itself.

*Why it crashed ONLY after long time (one hours) and/or over-applications usage if killing the app is done the same way as CommonsWare said? Or the crashes are linked to other issues?

*How do you, developers, simulate long time breaks to test that? I need to reproduce this crash if I hope to solve it. It might be an issue of singleton, I saw people talking about it.

I would really appreciate wisdom and guidance !

EDIT:

THere it's the logcat of the crash

  06-10 16:08:32.178: I/ActivityThread(26487): Pub com.snapcar.rider: com.snapcar.rider.provider.SCProvider
06-10 16:08:32.298: D/dalvikvm(26487): GC_CONCURRENT freed 255K, 10% free 12336K/13703K, paused 12ms+1ms, total 27ms
06-10 16:08:32.393: V/Localytics(26487): Opening new session
06-10 16:08:32.423: D/dalvikvm(26487): GC_CONCURRENT freed 219K, 10% free 12650K/13959K, paused 1ms+2ms, total 27ms
06-10 16:08:32.423: D/dalvikvm(26487): WAIT_FOR_CONCURRENT_GC blocked 14ms
06-10 16:08:32.423: W/CursorWrapperInner(26487): Cursor finalized without prior close()
06-10 16:08:32.448: D/SC - Auth(26487): Auth-instantiating AuthManager...
06-10 16:08:32.453: D/SC - BookingManager(26487): BookingManager-instantiating BookingManager...
06-10 16:08:32.518: D/SC - WebServiceManager(26487): WebServiceManager-ws type: preprod
06-10 16:08:32.518: D/SC - OtherUtils(26487): OtherUtils-language:fr
06-10 16:08:32.523: E/SC - SCMainActivity(26487): savedInstanceState != null, the application is RE-created
06-10 16:08:32.543: D/dalvikvm(26487): GC_CONCURRENT freed 226K, 10% free 12913K/14215K, paused 11ms+14ms, total 38ms
06-10 16:08:32.628: D/dalvikvm(26487): GC_CONCURRENT freed 145K, 9% free 13307K/14535K, paused 2ms+2ms, total 20ms
06-10 16:08:32.673: D/AndroidRuntime(26487): Shutting down VM
06-10 16:08:32.673: W/dalvikvm(26487): threadid=1: thread exiting with uncaught exception (group=0x40fd82a0)
06-10 16:08:32.678: E/AndroidRuntime(26487): FATAL EXCEPTION: main
06-10 16:08:32.678: E/AndroidRuntime(26487): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.snapcar.rider/com.snapcar.rider.SCMainActivity}: java.lang.NullPointerException
06-10 16:08:32.678: E/AndroidRuntime(26487):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2100)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2125)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at android.app.ActivityThread.access$600(ActivityThread.java:140)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1227)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at android.os.Handler.dispatchMessage(Handler.java:99)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at android.os.Looper.loop(Looper.java:137)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at android.app.ActivityThread.main(ActivityThread.java:4898)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at java.lang.reflect.Method.invokeNative(Native Method)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at java.lang.reflect.Method.invoke(Method.java:511)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at dalvik.system.NativeStart.main(Native Method)
06-10 16:08:32.678: E/AndroidRuntime(26487): Caused by: java.lang.NullPointerException
06-10 16:08:32.678: E/AndroidRuntime(26487):    at com.snapcar.rider.fragment.BookingFormFragment.onCreateView(BookingFormFragment.java:332)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at android.support.v4.app.FragmentManagerImpl.moveToState(Unknown Source)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at android.support.v4.app.FragmentManagerImpl.moveToState(Unknown Source)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at android.support.v4.app.FragmentManagerImpl.moveToState(Unknown Source)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(Unknown Source)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at android.support.v4.app.FragmentActivity.onStart(Unknown Source)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1167)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at android.app.Activity.performStart(Activity.java:5216)
06-10 16:08:32.678: E/AndroidRuntime(26487):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2073)
06-10 16:08:32.678: E/AndroidRuntime(26487):    ... 11 more

EDIT 2 :

riderID = Integer.parseInt(UserManager.getSharedInstance().getCurrentRider().getUniqueID());

It is the line who crashed this time, I am not sure it is always here. But this (would) confirm what I was pointing to Singleton or values lost? To counter that I was trying this morning to implemented a shared Preferences saving following post and guidelines:

@Override public void onSaveInstanceState(Bundle savedInstanceState) { Dbg.e(TAG, "onSavedInstance called"); if (UserManager.getSharedInstance().getCurrentRider() != null ){ Dbg.d(TAG, "We have a current rider"); Rider currentRider = UserManager.getSharedInstance().getCurrentRider(); savedInstanceState.putString(Rider.UNIQUEID_KEY, currentRider.getUniqueID()); (more attributes saved)

The problem is that the fonction onREstoreSavedInstance was not called here. It is like the User Interface is created too fast.

What should I do? Re-define the UI later in the call process of the fragment?

Or is there a more complex issue and this is just one breaking point (if I solve it here, the application will just crash later ?)

thanks for the help and support! It's really give me more courage to keep going on!

EDIT 2: This is my retrieving function:

public void onRestoreInstanceState(Bundle savedInstanceState) {
    Dbg.d(TAG,"the application is RE-created & called from onRestoreInstanceState");

    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);

    // Restore state members from saved instance
    if (UserManager.getSharedInstance().getCurrentRider() == null) {
        Rider currentRider = new Rider();
        currentRider.setUniqueID(savedInstanceState.getString(Rider.UNIQUEID_KEY));
   }}

(more settings)

I just noticed I didn't wrote Override & I did not set the created rider to the UserManager. Thus, the method is called in some other proofs I was doing. I add both now. I retest.

EDIT 3-4 ?

It is the rider that is null:

06-10 17:05:14.248: E/SC - BookingFormFragment(837): it's the CurrentRider that is null  !!!
Community
  • 1
  • 1
Poutrathor
  • 1,990
  • 2
  • 20
  • 44
  • What kind of crash? could you post the LogCat? – David M Jun 10 '13 at 13:13
  • No I have none at the moment, I will try to grab one the next time I successfully make it crash again. I will try with adb command because aLogCat never works with me. That 's the second point of my issue, how to reiterate this behavior as much as possible to get crashes and correct bugs? – Poutrathor Jun 10 '13 at 13:43
  • Okey dokey. hopefully this crash is something basic, perhaps some code needs to move to `onResume()` to make sure it's reinitialized when it resumes from hibernation. i guess we'll soon see. – David M Jun 10 '13 at 13:46
  • I made it crashed! Let me 5 minutes to find again the post about getting the logcat and i am here. – Poutrathor Jun 10 '13 at 13:56
  • `NullPointerException 06-10 16:08:32.678: E/AndroidRuntime(26487): at com.snapcar.rider.fragment.BookingFormFragment.onCreateView(BookingFormFragment.java:332)` could you post BookingFormFragment's `onCreateView()`?? and hilite line 332? – David M Jun 10 '13 at 14:24
  • `riderID = Integer.parseInt(UserManager.getSharedInstance().getCurrentRider().getUniqueID());` – Poutrathor Jun 10 '13 at 14:28
  • I edit to give context above, ok? – Poutrathor Jun 10 '13 at 14:28
  • yeah, you're going to have to post a bit more code. We'd need to see if `UserManager` has a value (is that a custom class? i see http://developer.android.com/reference/android/os/UserManager.html, but no `getSharedInstance()` method.) – David M Jun 10 '13 at 14:32
  • UserManager is custom indeed. It has single instance (static). It was designed to manager the unique rider (=user). Do you know about the chat utility? no reputation, let's forget about this ^^ – Poutrathor Jun 10 '13 at 14:39
  • yep? i'm there....oops! you don't have enough rep to chat (it's telling me). You might want to do "lots" of null checking prior to that line (logging the results) so on the next time this comes up, you'll be able to see what's null. i.e. `UserManager um = UserManager.getSharedInstance(); if (um == null) log.e("XXX", "UserManager is null!!!"; else Rider r = um.getCurrentRider(); if ...` – David M Jun 10 '13 at 14:41
  • So My current rider is null and the question I have is: "WHY the fonction onRestoreSavedInstance() is not called before the onCreateView()?" OK. I just looked at my permanently pined to the wall notes and my hypothesis is: Google said that "This method is called between onStart() and onPostCreate(Bundle)." so I think, because of the link between fragment and activity states that Fragment OnCreatedView is called before Activity.onStart() Your thoughts? – Poutrathor Jun 10 '13 at 15:17
  • Whew! Well, at least you now know what the problem is! as to what gets called when, i truly do not know for certain. if it were me, i'd `Log()` the functions in question and see for myself the order. I think you're on the right track, and will have a solution soon. Good luck. – David M Jun 10 '13 at 15:20
  • thanks! i ll try to post final solution if I find one! – Poutrathor Jun 10 '13 at 15:25

2 Answers2

1

So this post was about how to fast load the Android OS to have my application restart a certain way when I call it from background with the restart path, in order to debug an occasional crash on restart from background I provide below what I have understand/guess about this topic with no guarantee at all

I saw 3 states when the application is in the background:

the application was 'just' send to background and when you call it back, it reappears effortless (all is still in memory)

The app has spent quite time in background and/or the android OS has been stressed enough, for me, starting heavy game (eufloria, browsing one thousand pictures literally, looking at groupon & Gmail did the trick). In this case, it is call back from background and the OS tries to bring the last view to the front and call onRestoreSavedInstance().

Too much time in background, or crash, or huge loads... Anyway, your application restart totally when called from background (onRestoreSavedInstance() is not called at all, but the onCreate and Cie without a savedinstance Bundle).

The trick is to save whatever you think might been deleted in case 2 in onSavedInstance() and retrieve it in onRestoreSavedInstance(). But you have to call these saved variables, attributes, parameters AFTER the onStart() methods (of your fragment sure, activity maybe). This is mandatory because the onRestoreSavedInstance() method is called pretty late in the process: after Activity's onStart(). Cf google documentation on this:

Instead of restoring the state during onCreate() you may choose to implement onRestoreInstanceState(), which the system calls after the onStart() method. The system calls onRestoreInstanceState() only if there is a saved state to restore, so you do not need to check whether the Bundle is null:

So you cannot refer to anything before the onResume() method of your fragment due to the relationship between fragment and activity life-cycle: http://www.linuxforu.com/2011/05/android-fragments-api/

There it is, eventual corrector welcome :) Thx to david

Poutrathor
  • 1,990
  • 2
  • 20
  • 44
0

First, did you implement onResume() and onRestart() methods ?

Another way, if your app need a login (Facebook, Google +, own service...), you may receive a Token who must expire after a certain time. You must ask a new token key when resume...

Please post your LogCat for more help.

Adrien

Adrien Cerdan
  • 1,005
  • 1
  • 11
  • 21
  • No there is only a onResume() method currently implemented. I was thinking about adding a onRestart() but looking at Google documentation I decided the app did not need it so far: Google: "It's uncommon that an app needs to use onRestart() to restore the activity's state, so there aren't any guidelines for this method that apply to the general population of apps. However, because your onStop() method should essentially clean up all your activity's resources, you'll need to re-instantiate them when the activity restarts." – Poutrathor Jun 10 '13 at 13:47
  • Google end citation: "Yet, you also need to instantiate them when your activity is created for the first time (when there's no existing instance of the activity). For this reason, you should usually use the onStart() callback method as the counterpart to the onStop() method, because the system calls onStart() both when it creates your activity and when it restarts the activity from the stopped state." – Poutrathor Jun 10 '13 at 13:48