web-dev-qa-db-fra.com

Android - La distribution des clés a expiré

Dans mon Android, j'obtiens un crash très étrange, lorsque j'appuie sur un bouton (Image) sur mon interface utilisateur, l'application entière se bloque et après quelques secondes, j'obtiens la redoutée boîte de dialogue de fermeture forcée qui apparaît.

Voici ce qui est imprimé dans le journal:


WARN/WindowManager(88): Key dispatching timed out sending to package name/Activity
WARN/WindowManager(88): Dispatch state: {{KeyEvent{action=1 code=5 repeat=0 meta=0 scancode=231 mFlags=8} to Window{432bafa0 com.Android.launcher/com.Android.launcher.Launcher paused=false} @ 1281611789339 lw=Window{432bafa0 com.Android.launcher/com.Android.launcher.Launcher paused=false} lb=Android.os.BinderProxy@431ee8e8 fin=false gfw=true ed=true tts=0 wf=false fp=false mcf=Window{4335fc58 package name/Activity paused=false}}}
WARN/WindowManager(88): Current state:  {{null to Window{4335fc58 package name/Activity paused=false} @ 1281611821193 lw=Window{4335fc58 package name/Activity paused=false} lb=Android.os.BinderProxy@434c9bd0 fin=false gfw=true ed=true tts=0 wf=false fp=false mcf=Window{4335fc58 package name/Activity paused=false}}}
INFO/ActivityManager(88): ANR in process: package name (last in package name)
INFO/ActivityManager(88): Annotation: keyDispatchingTimedOut
INFO/ActivityManager(88): CPU usage:
INFO/ActivityManager(88): Load: 5.18 / 5.1 / 4.75
INFO/ActivityManager(88): CPU usage from 7373ms to 1195ms ago:
INFO/ActivityManager(88):   package name: 6% = 1% user + 5% kernel / faults: 7 minor
INFO/ActivityManager(88):   system_server: 5% = 4% user + 1% kernel / faults: 27 minor
INFO/ActivityManager(88):   tiwlan_wifi_wq: 3% = 0% user + 3% kernel
INFO/ActivityManager(88):   mediaserver: 0% = 0% user + 0% kernel
INFO/ActivityManager(88):   logcat: 0% = 0% user + 0% kernel
INFO/ActivityManager(88): TOTAL: 12% = 5% user + 6% kernel + 0% softirq
INFO/ActivityManager(88): Removing old ANR trace file from /data/anr/traces.txt
INFO/Process(88): Sending signal. PID: 1812 SIG: 3
INFO/dalvikvm(1812): threadid=7: reacting to signal 3
INFO/dalvikvm(1812): Wrote stack trace to '/data/anr/traces.txt'

Voici le code du bouton (image):


findViewById(R.id.endcallimage).setOnClickListener(new OnClickListener() {
                    public void onClick(View v) {
                        mNotificationManager.cancel(2);

                        Log.d("Handler", "Endcallimage pressed");

                        if(callConnected)
                        elapsedTimeBeforePause = SystemClock.elapsedRealtime() - stopWatch.getBase();

                        try {
                            serviceBinder.endCall(lineId);
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        } 
                            dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.FLAG_SOFT_KEYBOARD));
                            dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));
                    }
            });     

Si je commente ce qui suit, le fait d'appuyer sur le bouton (image) ne provoque pas le crash:


try {
      serviceBinder.endCall(lineId);
    } catch (RemoteException e) {
      e.printStackTrace();
    } 

Le code ci-dessus appelle à travers plusieurs niveaux de l'application et dans la couche native (NDK), l'appel passant par plusieurs objets pourrait-il conduire à la fermeture de la force? Cela semble peu probable car plusieurs autres boutons font de même sans problème.

Et la couche native? Un code que j'ai créé avec le NDK peut-il être à l'origine du problème?

Avez-vous d'autres idées quant à la cause du problème?

36
Donal Rafferty

Vous devez être aussi rapide que possible dans votre implémentation onClick. Les opérations coûteuses doivent être, en général, déchargées sur un thread d'arrière-plan.

Dans onClick, essayez:

Thread t = new Thread(){
    public void run(){
        your_stuff();
    }
};
t.start();

au lieu de juste

your_stuff()
46
Alex

Vous pouvez rencontrer cette erreur lorsque vous bloquez le thread principal (alias le thread d'interface utilisateur) pendant quelques secondes. Les opérations coûteuses doivent être, en général, déchargées sur un thread d'arrière-plan. AsyncTask est très utile dans ces cas.

Dans votre cas, vous pouvez effectuer les opérations suivantes:

new AsyncTask<Void, Void, Void>() {
    @Override
    protected Void doInBackground(Void... params) {
        try {
            serviceBinder.endCall(lineId);
        } catch (RemoteException e) {
            e.printStackTrace();
        } 
    }
}.execute();
5
juanes

Faites votre longue opération dans un thread séparé ou utilisez AsyncTask pour vous débarrasser de l'ANR.

Un ANR (activité ne répondant pas) se produit lorsque certains long operation takes place in the "main" fil. Il s'agit du thread de boucle d'événements, et s'il est occupé, Android ne peut pas traiter d'autres événements GUI dans l'application, et lance donc un ANR dialog.

Votre activité a pris trop de temps à dire au Android OS 'hey je suis toujours vivant'! (C'est ce que fait le thread d'interface utilisateur).

http://developer.Android.com/guide/practices/design/responsiveness.html

Fondamentalement, si vous demandez au thread d'interface utilisateur d'effectuer une tâche complexe, il est trop occupé à faire votre tâche pour dire au système d'exploitation qu'il est toujours "vivant".

http://Android-developers.blogspot.co.uk/2009/05/pireless-threading.html

Vous devez déplacer votre code d'analyse XML vers un autre thread, puis utiliser un rappel pour indiquer au thread d'interface utilisateur que vous avez terminé et faire quelque chose avec le résultat.

http://developer.Android.com/resources/articles/timed-ui-updates.html

Détecter où se produisent les ANR est facile s'il s'agit d'un bloc permanent (blocage bloquant l'acquisition de certains verrous par exemple), mais plus difficile s'il ne s'agit que d'un retard temporaire. Tout d'abord, passez en revue votre code et recherchez les points vunerables et les opérations de longue durée. Les exemples peuvent inclure l'utilisation de sockets, de verrous, de mises en veille de thread et d'autres opérations de blocage à partir du thread d'événement. Vous devez vous assurer que tout cela se produit dans des threads séparés. Si rien ne semble poser problème, utilisez DDMS et activez la vue des threads. Cela affiche tous les threads de votre application similaires à la trace que vous avez. Reproduisez l'ANR et actualisez le thread principal en même temps. Cela devrait vous montrer précisément ce qui se passait au moment de l'ANR

Si Logcat ne produit rien d'utile, essayez d'extraire traces.txt de /data/anr/traces.txt

adb pull /data/anr/traces.txt .

car il peut donner plus d'informations sur le lieu de l'exception ANR

Et ce lien peut également être utile pour créer AsyncTask et Threads

2
Xar E Ahmer

Si vous effectuez une tâche gourmande en ressources, cela peut arriver. En reprenant l'activité. 1. Essayez d'arrêter tout votre travail intensif sur onPause puis de le redémarrer sur onResume. 2. Si vous affichez la carte sur la superposition de dessin d'activité, arrêtez de rafraîchir les superpositions pendant le sommeil. Et puis redémarrez-le sur onResume.

1
Rajesh Narwal