I have an android app that uses push. If the app receives a push message from the server it creates a push notification (with headline, message, icon) and presents it to the user.
normal case The click on the notification opens up an Activity (not the launcher) and the activity opens a fragment that shows content based on the notification. No magic here and everything works as expected.
the special/bad case If the device is inactive for at least 2h and you pick it up and click a notification that was pushed before, then it opens the Activity like in the normal case but no fragment comes up. Instead the launcher will be called.
While debugging this is time costly and frustrating I found out the following things. Maybe someone has an idea:
The Activity usually starts with an animation that I load from resources. I load and run it in onCreate(). If the Activity gets invoked by the push then the animation will be loaded but never runs. I bypassed this with a Handler that waits 2 seconds and checks if the animation listener was called. If not (bad case) then the handler calls the code to open the fragment.
opening the fragment caused a crash: IllegalStateException: Cannot perform this after onSaveInstanceState. Similar like here Exception java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState So I replaced commitAllowingStateLoss(). Now there is no crash anymore but the fragment does not appear. Only Fragment.newInstance() will be called but no onCreate() or any other lifecycle method.
Question: What crazy state is it that seems to break functions in my code after longer inactivity?
Device: I'm currently testing with a Nexus 5 with Android 6.0.1
I found out that if my device is in this crazy sleep state that my activity gets startet twice if I then click on a push notification. At first the push triggers the activity with its data in the intent. Then, after it, the launcher activity gets invoked (with an empty intent) and starts the main screen.
I fixed it with like here -> Activity opened twice
To sum it up:
1) I changed my code so that all my deeplinks, push notifications, etc. will invoke the lauchner activity. The activity then decides what to do. That means we have a single entry point into the app. That makes everything easy and the code clearer. (with this fix the same activity will be invoked twice. we have to do a little more to fix it)
2) I marked the activity in the manifest with android:launchMode="singleTask"
. This means that if there is an instance of the activity already, it will be reused and not created a second time.
3) The flag from 2) triggers a callback method. Instead of invoking the activity a second time, the system reuses the already running activity and calls the method onNewIntent(intent)
. That means if the activity is freshly started, then onCreate()
will be called. If the activity is reused (because it was triggered by a push notification, deeplink, etc.) then onNewIntent(intent)
will be called. In both, onCreate()
and onNewIntent()
I call a method to decide what screen/fragment/activity is next and handover the intent from getIntent()
. Done.