Lorsque le processus de candidature meurt, Android parcourt les enregistrements d'activités (les entrées représentent des activités dans la pile d'historique) et décide lesquelles conserver dans l'historique et celles à supprimer.
L'un des points clés ici est le ActivityRecord
champ appelé haveState
, que les ingénieurs d'Android Framework décrivent comme "avons-nous obtenu le dernier état d'activité?".
Par défaut, Android considère que l'activité a un état. L'activité devient sans état lorsque l'application signale au service du gestionnaire de tâches d'activité que l'activité a repris et cela est valide jusqu'à ce que l'application notifie à l' infrastructure que l'activité est entrée dans l'état Arrêté. En termes simples, la haveState
valeur est false
entre l'activité onResume()
est appelée et onStop()
ou onSaveInstanceState()
est appelée, selon la version cible de l'application.
Si je tue le processus, Android recrée le processus et crée ActivityC.
Dans ce cas, ActivityD n'a pas d' android:stateNotNeeded="true"
attribut dans le manifeste de l'application et il est actuellement en cours d'exécution au premier plan, donc Android le supprime de l'historique car le système n'a pas obtenu son dernier état.
Comment simuler Android en tuant mon processus
Comme cela a été mentionné à plusieurs reprises, vous pouvez simplement déplacer l'application en arrière-plan, de sorte que l'activité principale de la pile arrière d'activité enregistre son état, et après cela, vous pouvez tuer le processus d'application via Android Debug Bridge, Android Studio ou en utilisant le Propriété Limite des processus d'arrière-plan dans les options du développeur. Après cela, votre activité récente sera recréée avec succès.
Malgré cela, il existe également un autre moyen simple de tester le scénario de décès du processus de candidature. Sachant tout ce qui est décrit ci-dessus et le fait que si vous démarrez un nouvel ActivityE à partir de ActivityD en cours d'exécution, le onStop()
rappel ActivityD n'est appelé qu'après la onResume()
méthode ActivityE , vous pouvez effectuer l'astuce suivante.
class TerminatorActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val isPrePie = applicationInfo.targetSdkVersion < Build.VERSION_CODES.P
val callbacks = TerminatorLifecycleCallbacks(isPrePie)
(applicationContext as Application).registerActivityLifecycleCallbacks(callbacks)
}
private class TerminatorLifecycleCallbacks(
// Before P onSaveInstanceState() was called before onStop(), starting with P it's
// called after
// Used to schedule the death as app reports server that activity has stopped
// after the latest of these was invoked
private val isPrePie: Boolean
) : ActivityLifecycleCallbacksDefault {
private val handler = Handler(Looper.getMainLooper())
override fun onActivityPostStopped(activity: Activity) {
if (isPrePie) {
terminate()
}
}
override fun onActivityPostSaveInstanceState(activity: Activity, outState: Bundle) {
if (!isPrePie) {
terminate()
}
}
fun terminate() {
handler.postDelayed(
{
Process.killProcess(Process.myPid()) // This is the end...
},
LAST_MILLIS
)
}
companion object {
// Let's wait for a while, so app can report and server can handle the update
const val LAST_MILLIS = 100L
}
}
private interface ActivityLifecycleCallbacksDefault : Application.ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
override fun onActivityStarted(activity: Activity) {}
override fun onActivityResumed(activity: Activity) {}
override fun onActivityPaused(activity: Activity) {}
override fun onActivityStopped(activity: Activity) {}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityDestroyed(activity: Activity) {}
}
}
Ensuite, commencez simplement TerminatorActivity
lorsque vous souhaitez supprimer l'application.
À la fin, il existe un outil léger qui simplifie les tests de la mort de votre processus d'application, appelé Venom .