Android applications are often killed by the system’s LowMemoryKiller while running in the background, and when the user clicks icon again or launches from the most recent task list, the process is rebuilt and the scene is restored. What does that mean? If the APP’s Activity stack looks like this before it is killed, A<B<C, with C at the top
After the APP is killed by the background, the APP side process is destroyed, so there is no Activity, and there is no Activity stack, but AMS is preserved:
What happens when the user starts the APP again? In this case, C is the first interface to be seen, rather than A at the bottom of the stack, which means that the first interface to be seen after being killed is the one that the user saw last.
When users click back, they will see the previous interface B, followed by A
The reason for this is that the creation of app-side activities is actually managed by AMS. AMS strictly maintains the ActivityRecord stack corresponding to the app-side activities, which can be regarded as the scene of the current APP. However, The destruction of an Activity on the APP side is not necessarily synchronous with the destruction of an ActivityRecord on the AMS side, most notably in the background killing scenario. Android does this in order to make the user unaware of the background kill, but in the development of this logic does have a variety of problems, even some products do not want to go through the recovery process, this article explains how to avoid the recovery process. Combined with common development scenarios, there are two types: one is to evoke APP for push, and the other is to evoke APP (or icon) from recent task list.
Invoke from the most recent task list without going through the recovery process
The Activity has an onCreate method that calls back after the ActivityThread creates a new Activity. If the Activity was killed and restored in the background, The onCreate callback passes a non-empty Bundle savedInstanceState to the current Activity. This non-empty Bundle is used to determine if it is a recovery process.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
Copy the code
Now that you know the recovery process, what do you do? The IntentFlag must be set when launching the splash screen: Intent. FLAG_ACTIVITY_NEW_TASK | Intent. FLAG_ACTIVITY_CLEAR_TASK, reasons for doing so is to clean up the previous scenario, Otherwise, the old ActivityRecord stack will remain in ActivityManagerService. The implementation is as follows:
Intent intent = new Intent(this, SplashActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
Copy the code
What if you don’t set it? For example, it is most common to jump to the main screen after the flash screen. The main screen often has router logic, and its startup mode is generally singleTask, processing some push, so its onCreate and onNewIntent have corresponding processing. If not set, after the flash screen is over, OnNewIntent is called at the same time as onCreate, so it is best to clean it up.
How to walk the splash screen logic when evoking a killed APP from push
For the processing of push message, its router is generally placed in MainActivity and added to onCreate and onNewIntent. If the APP is alive, it can directly jump to the target page. If the APP is killed, it is expected to jump to the main interface first and then to the target page. The user first sees the target page, and then sees the main interface when clicking back. If the flash screen is added, the desired effect is to see the flash screen first, click back to see the target page, and then click back to see the main page. If we briefly divide the push scenarios, we can see three of them
- The process lives and the Activity lives
- The process lives, but no Activity lives
- Process does not exist (whether killed or not)
Start MainActivity and then start SplashActivity with startActivityForResult in OnCreate. SplashActivity returns after the start TargetActivity. The following discussion is all about the latter two, and there are two things that need to be done
- FLAG_ACTIVITY_CLEAR_TASK: Intent.flag_activity_clear_task: intent.flag_activity_clear_task: intent.flag_activity_clear_task: intent.flag_activity_clear_task: intent.flag_activity_clear_task: intent.flag_activity_clear_task
- Second, in the routing system of MainActivity, for these two scenarios, first jump to the flash screen, and then jump to the push page after the flash screen comes back
In fact, the last two scenarios only need to determine whether there is an Activity alive, that is, check whether topActivity of APP is null, do not query AMS, but in the local process. You can use reflection to query the mActivities of ActivityThread or check the Activity stack maintained by yourself. If there are no viable activities, you can redirect to the main page
Intent intent = new Intent(this, MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK); Intent.setdate (intent's Uri scheme) startActivity(intent);Copy the code
In the route of MainActivity, it is necessary to distinguish accurately whether the MainActivity is pushing the jump in. If it is not pushing the jump in, no special treatment is needed. If it is pushing the jump in, it must carry the jump scheme data.
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Uri uri= getIntent().getData(); <! If the intent is set to jump only when the intent is set to jump. If the intent is cold, no data is available. =null){ SplashActivity.startActivityForResult(this,JUMP_TO_TARGET) } } <! Intent.flag_activity_clear_task ensures that when onNewIntent is called, > @override protected void onNewIntent(Intent Intent) {Uri Uri = intent.getData(); intent.setData(null); router(uri); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(requestCode==JUMP_TO_TARGET && requestCode == RESULT_OK){ router(getIntent().getData()); getIntent().setData(null); } } private void router(Uri uri) { }Copy the code
Through the processing of the above two parts, it can basically meet the requirements of jumping to the splash screen first when the APP “dies”.
After being killed by the background, how can Android applications re-run the splash screen logic
For reference only, welcome correction