2017-05-30 3 views
2

J'utilise Thread.setDefaultExceptionHandler() pour essayer de démarrer une nouvelle activité, le redémarrage de manière efficace l'application. Toutefois, il semble que le ActivityManager tue le nouveau processus de l'application juste après son démarrage.après Android uncaughtException, ActivityManager ne force le nouveau processus d'arrêt

J'ai essayé un certain nombre d'expériences. Le code est le plus réussi, dans le gestionnaire d'exception:

public void handleUncaughtException (Thread thread, Throwable e) 
{ 
    Intent intent = new Intent (getBaseContext(), RestartActivity.class); 
    intent.addFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP | 
        Intent.FLAG_ACTIVITY_CLEAR_TASK | 
        Intent.FLAG_ACTIVITY_NEW_TASK); 

    PendingIntent pending = 
    PendingIntent.getActivity (getBaseContext(), 0, intent, PendingIntent.FLAG_ONE_SHOT); 

    try { 
    pending.send(); 
    } 
    catch (PendingIntent.CanceledException e1) { 
    logE ("send pending intent:" + e1); // logE is a wrapper for Log.e(). 
    } 

    System.exit (1); 
} 

Dans ce cas, la RestartActivity démarre et affiche, mais seulement pour une seconde. Ensuite, l'application est complètement disparue et Android affiche ce qui était l'application précédente.

Le fichier journal contient ce (notez les pid sont légèrement différentes):

05-29 22:46:28.429 1465-3665/? I/ActivityManager: Force stopping com.perinote.crashtest appid=10170 user=0: from pid 14484 
05-29 22:46:28.429 1465-3665/? I/ActivityManager: Killing 14486:com.perinote.crashtest/u0a170 (adj 0): stop com.perinote.crashtest 

J'ai aussi essayé d'utiliser AlarmManager, dans cette variante:

public void handleUncaughtException (Thread thread, Throwable e) 
{ 
    Intent intent = new Intent (getBaseContext(), RestartActivity.class); 
    intent.addFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP | 
        Intent.FLAG_ACTIVITY_CLEAR_TASK | 
        Intent.FLAG_ACTIVITY_NEW_TASK); 

    PendingIntent pending = 
    PendingIntent.getActivity (getBaseContext(), 0, intent, PendingIntent.FLAG_ONE_SHOT); 

    AlarmManager alarm = (AlarmManager)getSystemService (Context.ALARM_SERVICE); 
    alarm.set (AlarmManager.RTC, System.currentTimeMillis() + 3000, pending); 

    System.exit (1); 
} 

Dans ce cas, RestartActivity doesn « affichage t du tout, et je vois une ligne dans le logcat comme ceci:

05-29 22:06:46.841 1465-11842/? I/ActivityManager: Force stopping com.perinote.crashtest appid=10170 user=0: from pid 12551 

Qu'est-ce que Causin g Android veut tellement tuer le processus qui vient de commencer?

+0

Avez-vous essayé d'utiliser ** android.os.Process.killProcess **? –

+0

Je ne pense pas, mais ça fait longtemps. Ce n'est pas actuellement sur ma liste de priorités donc ce sera un "temps" plus long avant d'essayer quoi que ce soit d'autre. Merci. –

+0

N'utilisez pas ** System.exit (1) **, car il ne nettoie pas la pile des tâches et ne permet pas au système d'exploitation de quitter proprement votre application. En savoir plus sur la pile de tâches ici: https://developer.android.com/guide/components/activities/tasks-and-back-stack.html –

Répondre

1

que très modifié ce que vous je prenais essayiez de faire.

La première version ne fonctionne pas parce que vous envoyez une intention dans l'attente de votre propre application. Ce n'est pas parce qu'une intention est en attente qu'elle sera exécutée dans un nouveau processus, cela signifie que, quelle que soit l'application qui l'appelle (comme le lanceur de notifications), elle sera activée comme si votre propre processus lançait l'intention. Ainsi, il peut accéder à des activités privées, par exemple. Cela a commencé dans votre processus avant que vous ne soyez tué, puis il est tué avec vous.

Le, le gestionnaire d'alarme ne fonctionne pas du tout parce que l'intention en attente dans ce doit être à un BroadcastReceiver- il n'accepte pas un à un service ou une activité. Si vous mettez un récepteur dans votre manifeste et utilisez une intention en attente, vous pouvez probablement le faire fonctionner.

+0

Merci, Gabe. Donc, pour être clair, vous n'êtes pas au courant d'autres méthodes de redémarrage d'une application? En supposant que non, je vais essayer d'implémenter un BroadcastReceiver. –

+0

Pas désinvolte. Ce n'est pas quelque chose que j'ai déjà essayé de faire. –

+0

Semble fonctionner - testé sur un seul appareil jusqu'à présent. Question: apparemment, pour des raisons de sécurité, mon récepteur sera ignoré jusqu'à ce que j'ai démarré manuellement l'application. Autrement dit, AlarmManager déclenchera la diffusion, mais Android ne démarrera mon récepteur que si j'ai déjà exécuté l'application au moins une fois. Chaque fois que j'essaie d'exécuter mon code à partir du débogueur, mon récepteur ne démarre jamais. Je dois l'exécuter en le sélectionnant dans Applications sur mon appareil. Existe-t-il un moyen de le faire fonctionner à partir du débogueur? –