【问题标题】:Android - Key Dispatching Timed OutAndroid - 密钥调度超时
【发布时间】:2010-08-12 11:39:39
【问题描述】:

在我的 Android 应用程序中,我遇到了一个非常奇怪的崩溃,当我在 UI 上按下一个按钮(图像)时,整个应用程序会冻结,几秒钟后,我会出现可怕的强制关闭对话框。

这是日志中打印的内容:


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'

这是按钮的代码(图片):


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));
                    }
            });     

如果我将以下内容注释掉,按下按钮(图像)不会导致崩溃:


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

上述代码通过应用程序的多个级别向下调用并进入本机层(NDK),通过多个对象的调用是否会导致强制关闭?这似乎不太可能,因为其他几个按钮也没有问题。

原生层呢?我使用 NDK 构建的某些代码是否会导致问题?

关于问题的原因可能是什么其他想法?

【问题讨论】:

    标签: android timeout key freeze dispatch


    【解决方案1】:

    在您的 onClick 实现中,您必须尽可能快。一般来说,昂贵的操作应该卸载到后台线程。

    在 onClick 中,尝试:

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

    而不仅仅是

    your_stuff()
    

    【讨论】:

      【解决方案2】:

      当您阻塞主线程(也称为 UI 线程)几秒钟时,您可能会遇到此错误。一般来说,昂贵的操作应该卸载到后台线程。 AsyncTask 在这些情况下非常有用。

      在您的情况下,您可以执行以下操作:

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

      【讨论】:

        【解决方案3】:

        在单独的线程中执行长操作或使用 AsyncTask 摆脱 ANR。

        当某个long operation takes place in the "main" 线程发生ANR(Activity Not Responding)。这是事件循环线程,如果它很忙,Android 将无法在应用程序中处理任何进一步的 GUI 事件,因此会抛出 ANR dialog

        您的活动花了很长时间才对 Android 操作系统说“嘿,我还活着”! (这就是 UI 线程所做的)。

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

        基本上,如果您让 UI 线程执行一些复杂的任务,那么您的任务就太忙了,无法告诉操作系统它仍然“活着”。

        http://android-developers.blogspot.co.uk/2009/05/painless-threading.html

        您应该将您的 XML Parsing 代码移动到另一个线程,然后使用回调告诉 UI 线程您已经完成并对结果进行处理。

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

        如果是永久阻塞(例如死锁获取一些锁),检测 ANR 发生的位置很容易,但如果只是暂时延迟,则更难。首先,检查你的代码并寻找易受攻击的地方和长时间运行的操作。示例可能包括在事件线程内使用套接字、锁、线程休眠和其他阻塞操作。您应该确保这些都发生在单独的线程中。如果没有问题,请使用 DDMS 并启用线程视图。这将显示应用程序中的所有线程,类似于您拥有的跟踪。重现ANR,同时刷新主线程。这应该能准确地告诉你 ANR 发生时发生了什么

        如果 Logcat 没有输出任何有用的信息,请尝试从 /data/anr/traces.txt 中提取 traces.txt

        adb pull /data/anr/traces.txt .
        

        因为它可能会提供有关 ANR 异常发生位置的更多信息

        this link 也可能有助于创建 AsyncTask 和线程

        【讨论】:

          【解决方案4】:

          如果您正在执行一项资源密集型任务,那么它可能会发生。在恢复活动时。 1. 尝试在 onPause 上停止所有密集工作,然后在 onResume 上重新启动它。 2. 如果您在 Activity 上显示地图,则在其上绘制叠加层,然后在睡眠时停止刷新叠加层。然后在 onResume 上重新启动它。

          【讨论】:

            猜你喜欢
            • 2011-05-13
            • 2013-09-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-08-14
            • 1970-01-01
            • 1970-01-01
            • 2023-03-28
            相关资源
            最近更新 更多