Quando o processo do aplicativo morre, o Android passa pelos registros de atividades (as entradas representam atividades na pilha do histórico) e decide quais manter no histórico e quais remover dele.
Um dos pontos principais aqui é o ActivityRecord
campo chamado haveState
, que os engenheiros do Android Framework descrevem como "chegamos ao último estado de atividade?".
Por padrão, o Android considera que a atividade tem um estado. A atividade se torna sem estado quando o aplicativo relata ao serviço do gerenciador de tarefas que a atividade foi retomada e isso é válida até que o aplicativo notifique a estrutura de que a atividade entrou no estado Parado. Em palavras simples, o haveState
valor false
entre atividade onResume()
é chamado eonStop()
ou onSaveInstanceState()
é chamado, dependendo da versão de destino do aplicativo.
Se eu matar o processo, o Android recria o processo e cria o ActivityC.
Nesse caso, ActivityD não possui android:stateNotNeeded="true"
atributo no manifesto do aplicativo e está em execução no primeiro plano; portanto, o Android o remove do histórico, pois o sistema não obteve seu último estado.
Como simular o Android matando meu processo
Como foi mencionado várias vezes, você pode simplesmente mover o aplicativo para o segundo plano, para que a atividade principal na pilha traseira da atividade salve seu estado e, depois disso, você pode eliminar o processo do aplicativo através do Android Debug Bridge, Android Studio ou usando o Propriedade Limite de Processos em Segundo Plano nas Opções do Desenvolvedor. Depois disso, sua atividade recente será recriada com sucesso.
Apesar disso, há também outra maneira simples de testar o cenário de morte do processo de aplicativo. Sabendo tudo o que foi descrito acima e o fato de que, se você iniciar a nova ActivityE a partir da ActivityD atualmente em execução, o onStop()
retorno de chamada da ActivityD será invocado somente após o onResume()
método ActivityE , você poderá executar o seguinte truque.
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) {}
}
}
Em seguida, basta iniciar TerminatorActivity
quando você deseja matar o aplicativo.
No final, existe uma ferramenta leve que simplifica o teste da morte do processo de aplicação, chamada Venom .