ANR意图广播 { act = android.intent.action.SCREEN_ON flg = 0x50200010(具有额外信息)}

29

我的android vitals中出现了一些ANR:

Intent { act=android.intent.action.SCREEN_ON flg=0x50200010 (有 extras) }的广播,或者

Intent { act=android.intent.action.SCREEN_ON flg=0x50000010 }的广播。

我也遇到了一些其他的ANR:

Intent { act=android.intent.action.SCREEN_OFF flg=0x50000010 }的广播。

似乎这些ANR经常发生。 经过我的研究,我没有找到解决方法。 具体来说,我想知道这些ANR是否与在我的onCreate中使用getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);以保持屏幕亮起有关。 我的应用程序中没有使用任何BroadcastReceiver。 请帮帮我?

来自android vitals的错误日志:

"main" tid=1 Waiting 
"main" prio=5 tid=1 Waiting
  | group="main" sCount=1 dsCount=0 flags=1 obj=0x73c98680 self=0xee259000
  | sysTid=24710 nice=0 cgrp=default sched=0/0 handle=0xf26ff4bc
  | state=S schedstat=( 2919404633 900616698 9273 ) utm=197 stm=94 core=0 HZ=100
  | stack=0xff6b6000-0xff6b8000 stackSize=8MB
  | held mutexes=
  at java.lang.Object.wait (Native method)
- waiting on <0x03bec179> (a com.myPackageName)
  at com.myPackageName.framework.impl.GLGame.onPause (GLGame.java:714)
- locked <0x03bec179> (a com.myPackageName)
  at com.myPackageName.onPause (MyApp.java:39)
  at android.app.Activity.performPause (Activity.java:7399)
  at android.app.Instrumentation.callActivityOnPause (Instrumentation.java:1414)
  at android.app.ActivityThread.performPauseActivityIfNeeded (ActivityThread.java:4115)
  at android.app.ActivityThread.performPauseActivity (ActivityThread.java:4092)
  at android.app.ActivityThread.performPauseActivity (ActivityThread.java:4066)
  at android.app.ActivityThread.handlePauseActivity (ActivityThread.java:4040)
  at android.app.ActivityThread.-wrap16 (ActivityThread.java)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1708)
  at android.os.Handler.dispatchMessage (Handler.java:105)
  at android.os.Looper.loop (Looper.java:164)
  at android.app.ActivityThread.main (ActivityThread.java:6944)
  at java.lang.reflect.Method.invoke (Native method)
  at com.android.internal.os.Zygote$MethodAndArgsCaller.run (Zygote.java:327)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1374)

1
与那个标志无关。它与你的应用在UI线程上执行看门狗函数(如生命周期函数)时花费太长时间有关。 - Gabe Sechan
谢谢。看起来这些ANR总是从生命周期函数GLGame.onPause()开始。 - Kostas Trakos
似乎这些ANR始终始于生命周期函数GLGame.onPause() at com.myPackageName.framework.impl.GLGame.onPause (GLGame.java:714)。我将尝试更新GLGame.onPause(),看看Android Vitals是否能够摆脱ANR。 - Kostas Trakos
请编辑您的问题并添加来自onPause()方法的代码。 - David Wasser
5个回答

4
我很确定这个ANR是由一个同步块引起的,除非第714行指向super.onPause()。在你的GLGame.onPause (GLGame.java:714)中,你要么故意在主线程上等待一个对象,要么使用一个同步的最终变量(可以是同步的列表、集合、映射等)。由于你没有分享任何源代码,所以我无法确定实际原因而不加查看。
在主线程中使用这种方法可能会阻塞你的线程,这是你绝对不想要的事情(假设锁也在另一个线程中使用)。
// One example
@Override
public void onPause() {
   synchronized(mLock) {
      // access the variable
   }
}

// Another example
@Override
public void onPause() {
   synchronizedList.add(new Object())
}

如果有另一个线程正在访问锁或同步列表、映射等,且不放弃锁,则这两种方法都会被阻止。解决方法是使用ReentrantLockLock接口。可以像这样使用Lock mLock = new ReentrantLock(),并将您的调用转换为以下内容:
@Override
public void onPause() {
   if (mLock.tryLock()){
      try{
         // do your work here
      } finally {
         mLock.unlock();
      }
   }
}

// Another example
@Override
public void onPause() {
   if (mLock.tryLock()){
      try{
         // The list or set should not be synchronized.
         // The synchronization must be managed with lock's
         // "tryLock" method. The "tryLock" also has an
         // overload with a timeout which you can use 
         // in your background thread, but you must not 
         // use on the main thread.
         normalList.add(new Object());
      } finally {
         mLock.unlock();
      }
   }
}

在主线程上访问的变量不应该阻塞,或者工作线程应该尽可能少地阻塞它们,以便主线程可以立即获取锁定,从而确保同步。因此,我建议检查整个代码中主线程和其他线程之间共享变量和引用的情况,并仅同步变量的更改,而不是长时间执行的整个代码块。

3
如果您正在活动的onCreate方法中使用以下代码段:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.main);

只需将其替换为以下代码行

View view = getLayoutInflater().inflate(R.layout.main, null);
view.setKeepScreenOn(true);
setContentView(view);

我希望这能帮助您得到解决方案。

愉快编码 :)


我打算尝试一下 - 但如果能添加任何关于为什么这样做的文档链接就太好了。 - JCutting8
跟进 - 不好意思,这并没有解决问题。转向 XML 并没有产生任何影响。 - JCutting8

2
我们遇到了同样的问题。这与SCREEN_ON标志无关,无论是通过编程还是通过XML进行操作。
在我们的情况下,崩溃发生是因为onReceive()缺少通知通道。

https://developer.android.com/training/notify-user/channels

从Android 8.0(API级别26)开始,所有通知都必须分配到一个频道。对于每个频道,您可以设置应用于该频道中所有通知的视觉和听觉行为。然后,用户可以更改这些设置,并决定您的应用程序的哪些通知频道应该具有侵入性或可见性。
您可能想寻找类似的问题。

1

这个广播与您的问题无关

  at java.lang.Object.wait (Native method)
- waiting on <0x03bec179> (a com.myPackageName)
  at com.myPackageName.framework.impl.GLGame.onPause (GLGame.java:714)

您正在主线程中执行同步操作。 Object.wait() 用于手动同步,您不应该在主线程中执行此类操作。
无论您在 com.myPackageName.framework.impl.GLGame.onPause 文件的第 714 行做了什么,都会导致这种同步。
在那里,您正在等待某些事情发生,可能需要太长时间(即使只有几毫秒),或者完全卡住(死锁)。
无论它在那里等待多长时间,您都不应该在主线程中编写同步代码。但是,如果它是死锁,将其移出主线程只会修复 ANR,找到并修复死锁将成为另一个问题。
如果您还没有检查 有关ANR的官方文档,其中还讨论了同步和等待/通知,这可能与您的问题有关。
简而言之:将同步逻辑移动到主线程之外(不要在 onPause / onResume 中执行),并转移到某些后台工作中。
除非看到实际有问题的代码并知道它的功能,否则无法提供更多帮助。

0
你的GLGame类是从GLSurfaceView类派生而来的。
这是在Android上编写游戏的标准方式。
在Activity.onPause之后,会调用GLSurfaceView.onPause。
在GLSurfaceView.onPause内部是阻塞等待():
    public void onPause() {
        synchronized (sGLThreadManager) {
            if (LOG_PAUSE_RESUME) {
                Log.i("GLThread", "onPause tid=" + getId());
            }
            mRequestPaused = true;
            sGLThreadManager.notifyAll();
            while ((! mExited) && (! mPaused)) {
                if (LOG_PAUSE_RESUME) {
                    Log.i("Main thread", "onPause waiting for mPaused.");
                }
                try {
                    sGLThreadManager.wait();              // <<<<<<<<<<< Causing ANR.
                } catch (InterruptedException ex) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

这通常不是问题,我已经在几个游戏中使用了这种方法。可能是设备上的GL驱动程序有问题。通过在自己的线程上运行GLSurfaceView.onPause,可以修复它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接