16 votes

Écouter et répondre à l'ANR ?

Existe-t-il un moyen d'être averti lorsque votre application déclenche un ANR (Application Not Responding) ? Similaire au gestionnaire d'exception par défaut ?

En prévision des réponses à la question "qu'en feriez-vous ?", il suffit d'enregistrer les données. Ne pas "faire" quoi que ce soit.

10voto

Salomon BRYS Points 676

Puisque le chien de garde du système n'avertit pas l'application, l'application elle-même peut avoir son propre chien de garde. Les étapes sont simples, il suffit de démarrer un thread qui boucle en faisant ce qui suit :

  1. Programmer l'exécution d'un petit code sur le thread de l'interface utilisateur dès que possible.
  2. Attendez X secondes (c'est vous qui décidez).
  3. Vérifier si le code s'est exécuté : si c'est le cas, revenir au point 1
  4. Si le code n'a pas été exécuté, cela signifie que le thread de l'interface utilisateur a été bloqué pendant au moins X secondes, ce qui soulève une exception avec la trace de pile du thread de l'interface utilisateur.

J'ai écrit une petite bibliothèque qui fait exactement cela et que j'utilise avec ACRA.

J'espère que cela vous aidera ;)

5voto

larham1 Points 2088

Non. Contrairement aux exceptions qui se produisent dans la VM de votre processus et que vous pouvez rattraper, l'ANR est générée par un chien de garde du système, en dehors de votre VM. Google propose informations sur les déclencheurs et l'évitement

5voto

Kevin Galligan Points 6101

J'y ai beaucoup réfléchi. Vous pourrait faire ce qui suit, même si c'est assez lourd. Les ANR écrivent un fichier de fils dans un répertoire généralement lisible :

/data/anr/traces.txt

Vous pourriez demander à un service, dans un autre processus, d'interroger périodiquement ce fichier. Si la date change et que votre application est en tête de liste, il s'agit probablement d'un événement ANR.

Je ne suis pas sûr à 100 % du format du fichier.

1voto

Hasan TBT Points 409

Ce petit ANR-Chien de garde peut vous aider à surveiller le fil de votre application et à être notifié en cas d'ANR.

new ANRWatchDog().setANRListener(new ANRWatchDog.ANRListener() {
    @Override
    public void onAppNotResponding(ANRError error) {
        // Handle the error. For example, log it to HockeyApp:
        ExceptionHandler.saveException(error, new CrashManager());
    }
}).start();

0voto

android developer Points 20939

Vous pourriez utiliser un service (de préférence un service d'avant-plan) qui écoute les journaux (en utilisant un thread), et s'il y a un journal qui indique l'ANR, le traiter.

Voici un petit exemple d'application qui provoque des bruits parasites :

...
findViewById(R.id.button).setOnClickListener(new OnClickListener()
  {
    @Override
    public void onClick(final View v)
      {
      try
        {
        Thread.sleep(10000);
        }
      catch(final InterruptedException e)
        {
        // TODO Auto-generated catch block
        e.printStackTrace();
        }
      }
  });
...

Voici le log que j'ai obtenu du logcat lorsque j'ai reçu l'ANR :

08-03 13:02:37.746: E/ActivityManager(158): ANR in com.example.anr (com.example.anr/.MainActivity)
08-03 13:02:37.746: E/ActivityManager(158): Reason: keyDispatchingTimedOut
08-03 13:02:37.746: E/ActivityManager(158): Load: 6.19 / 2.37 / 0.86
08-03 13:02:37.746: E/ActivityManager(158): CPU usage from 5598ms to 0ms ago:
08-03 13:02:37.746: E/ActivityManager(158):   2.6% 158/system_server: 2.5% user + 0.1% kernel / faults: 86 minor
08-03 13:02:37.746: E/ActivityManager(158):   0.5% 298/com.android.phone: 0.3% user + 0.1% kernel / faults: 15 minor
08-03 13:02:37.746: E/ActivityManager(158):   0% 35/rild: 0% user + 0% kernel
08-03 13:02:37.746: E/ActivityManager(158): 4.6% TOTAL: 3.9% user + 0.6% kernel
08-03 13:02:37.746: E/ActivityManager(158): CPU usage from 2029ms to 2654ms later:
08-03 13:02:37.746: E/ActivityManager(158):   11% 158/system_server: 4.8% user + 6.4% kernel / faults: 2 minor
08-03 13:02:37.746: E/ActivityManager(158):     11% 192/InputDispatcher: 4.8% user + 6.4% kernel
08-03 13:02:37.746: E/ActivityManager(158):     1.6% 163/Compiler: 1.6% user + 0% kernel
08-03 13:02:37.746: E/ActivityManager(158):     1.6% 193/InputReader: 0% user + 1.6% kernel
08-03 13:02:37.746: E/ActivityManager(158): 18% TOTAL: 9.3% user + 9.3% kernel

Donc, oui, je pense que c'est possible.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X