it-swarm-eu.dev

Utilisation de la gestion des exceptions globales sur android

Existe-t-il un exemple de code ou un didacticiel sur l'utilisation de Thread.setDefaultUncaughtExceptionHandler méthode? Fondamentalement, j'essaie d'afficher une boîte de dialogue d'alerte personnalisée, chaque fois qu'une exception est levée, dans mon application. Est-il possible de faire cela? Je sais que c'est un peu délicat d'afficher quelque chose à l'écran, si l'exception est levée dans le thread d'interface utilisateur, mais je ne connais pas de solution pour cela.

56
Gratzi

Exemple de base pour quelqu'un qui vient sur cette page avec une solution :)

public class ChildActivity extends BaseActivity {
    @SuppressWarnings("unused")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        int a=1/0;
    }
}

Classe de gestion des erreurs:

public class BaseActivity extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
                Log.e("Alert","Lets See if it Works !!!");
            }
        });
    }
}
73
Code_Life

Voici une variante de la réponse par Mohit Sharma avec les améliorations suivantes:

  • Ne provoque pas le gel de l'application/du service après la gestion des erreurs
  • Permet Android de faire sa gestion d'erreur normale après la vôtre

Code:

public class BaseActivity extends Activity {
    @Override
    public void onCreate() {
        super.onCreate();

        final Thread.UncaughtExceptionHandler oldHandler =
            Thread.getDefaultUncaughtExceptionHandler();

        Thread.setDefaultUncaughtExceptionHandler(
            new Thread.UncaughtExceptionHandler() {
                @Override
                public void uncaughtException(
                    Thread paramThread,
                    Throwable paramThrowable
                ) {
                    //Do your own error handling here

                    if (oldHandler != null)
                        oldHandler.uncaughtException(
                            paramThread,
                            paramThrowable
                        ); //Delegates to Android's error handling
                    else
                        System.exit(2); //Prevents the service/app from freezing
                }
            });
    }
}
33
Sam

Gardez à l'esprit que la The RuntimePermission("setDefaultUncaughtExceptionHandler") est vérifiée avant de définir le gestionnaire et assurez-vous de provoquer l'arrêt du processus par la suite, en lançant une exception non interceptée, car les choses pourraient être dans un état incertain.

N'affichez rien, en effet le thread d'interface utilisateur pourrait être celui qui s'est écrasé, écrivez un journal et/ou envoyez les détails à un serveur à la place. Vous voudrez peut-être vérifier cette question et ses réponses .

4
luvieere

si vous voulez utiliser cette bibliothèque

https://github.com/selimtoksal/Android-Caught-Global-Exception-Library

créez votre TransferObject pas tous dans vos activités utilisez simplement dans l'activité de base

2
secret paladin

Je voulais juste souligner mon expérience jusqu'à présent. J'utilise la solution suggérée par https://stackoverflow.com/a/26560727/273724 pour vider l'exception dans mon fichier journal avant de donner le contrôle au gestionnaire d'exceptions par défaut.

Cependant, ma structure ressemble à ceci:

          BaseActivity
               |
    _______________________
    |          |          |
Activity A Activity B Activity C
final Thread.UncaughtExceptionHandler defaultEH = Thread.getDefaultUncaughtExceptionHandler();                                                                                                                                                                                                                                                                                                                              
    Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {                                                                                                                                                                                                                                                                                                                                           
        @Override                                                                                                                                                                                                                                                                                                                                                                                                               
        public void uncaughtException(Thread thread, Throwable e) {                                                                                                                                                                                                                                                                                                                                                             
            handleUncaughtException(thread, e, defaultEH);                                                                                                                                                                                                                                                                                                                                                                      
        }                                                                                                                                                                                                                                                                                                                                                                                                                       
 });

handleUncaughtException(thread, e, defaultEH); écrit dans le journal et remet l'appel au UncaughtExceptionHandler d'origine.

Donc, ce qui s'est passé en utilisant ce code était le suivant:

  • L'activité A est instanciée
  • Le nouveau gestionnaire d'exceptions par défaut (DEH) est maintenant mon gestionnaire de journaux + l'ancien DEH
  • L'activité B est instanciée
  • Le nouveau DEH est maintenant mon gestionnaire de journaux + l'ancien DEH (gestionnaire de journaux + DEH d'origine)
  • L'activité C est instanciée
  • Le nouveau DEH est maintenant mon gestionnaire de journaux + l'ancien DEH (gestionnaire de journaux + gestionnaire de journaux + DEH d'origine)

C'est donc une chaîne qui croît à l'infini, causant deux problèmes:

  1. Le code personnalisé spécifié (dans mon cas, écrit dans le fichier journal) sera appelé plusieurs fois, ce qui n'est pas l'action souhaitée.
  2. La référence de defaultEh est conservée dans le tas même après la fin de l'activité, car elle est utilisée par la chaîne de référence, de sorte que la pire chose qui puisse arriver est une exception de mémoire insuffisante.

Par conséquent, j'ai ajouté une chose pour enfin faire fonctionner cela sans problèmes:

private static boolean customExceptionHandlerAttached = false;                                                                                                                                                                                                                                                                                                                                                                      

@Override                                                                                                                                                                                                                                                                                                                                                                                                                           
protected void onCreate(@Nullable Bundle savedInstanceState) {                                                                                                                                                                                                                                                                                                                                                                      
    super.onCreate(savedInstanceState);                                                                                                                                                                                                                                                                                                                                                                                             

    if(!customExceptionHandlerAttached) {                                                                                                                                                                                                                                                                                                                                                                                            
        final Thread.UncaughtExceptionHandler defaultEH = Thread.getDefaultUncaughtExceptionHandler();                                                                                                                                                                                                                                                                                                                              
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {                                                                                                                                                                                                                                                                                                                                           
            @Override                                                                                                                                                                                                                                                                                                                                                                                                               
            public void uncaughtException(Thread thread, Throwable e) {                                                                                                                                                                                                                                                                                                                                                             
                 handleUncaughtException(thread, e, defaultEH);                                                                                                                                                                                                                                                                                                                                                                      
            }                                                                                                                                                                                                                                                                                                                                                                                                                       
        });                                                                                                                                                                                                                                                                                                                                                                                                                         
        customExceptionHandlerAttached = true;                                                                                                                                                                                                                                                                                                                                                                                      
    }                                                                                                                                                                                                                                                                                                                                                                                                                               
}

Avec cette solution, nous pouvons nous assurer de:

  • ajouter un gestionnaire d'exceptions personnalisé pour l'action souhaitée
  • assurez-vous que cette action n'est déclenchée qu'une seule fois
  • permettant au ramasse-miettes de supprimer complètement notre activité en appelant finish ()
2
GC268DM