У меня есть несколько ошибок ANR в моем Android Vitals:
Трансляция намерения {act = android.intent.action.SCREEN_ON flg = 0x50200010 (имеет extras)} или
Трансляция намерения {act = android.intent.action.SCREEN_ON flg = 0x50000010}.
У меня также есть несколько ошибок ANR:
Трансляция намерения {act = android.intent.action.SCREEN_OFF flg = 0x50000010}
Кажется, что эти ошибки ANR происходят регулярно.
Из своего исследования я не нашел решения.
В частности, мне интересно, связаны ли эти ANR с
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
в моем onCreate, чтобы экран оставался включенным.
Я не использую 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)
Спасибо . Кажется, что всегда эти ANR начинаются с функции жизненного цикла GLGame.onPause ()
Кажется, что всегда эти ANR начинаются с функции жизненного цикла GLGame.onPause () at com.myPackageName.framework.impl.GLGame.onPause (GLGame.java:714). Я попытаюсь обновить GLGame.onPause () и посмотрю, избавится ли Android Vitals от ошибок ANR.
Отредактируйте свой вопрос и добавьте код из вашего метода onPause().
Я почти уверен, что этот 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())
}
Оба этих подхода будут заблокированы, если есть другой поток, который в данный момент обращается к блокировке или синхронизированному списку, карте и т. д. И не отказывается от блокировки. В качестве решения я мог бы порекомендовать использовать ReentrantLock с интерфейсом Lock, используя как 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();
}
}
}
Переменные, к которым осуществляется доступ в основном потоке, не должны блокироваться, или рабочий поток должен блокировать их как можно меньше, чтобы основной поток мог получить блокировку сразу после этого, если вы хотите обеспечить синхронизацию. Поэтому я предлагаю проверить весь ваш код на общие переменные и ссылки между основным потоком и другими потоками и синхронизировать только изменения переменных, а не весь блок кода, выполнение которого занимает много времени.
Трансляция не имеет отношения к вашей проблеме
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 в файле GLGame.java в строке 714, вызывает эту синхронизацию.
там вы ждете, что произойдет что-то, что либо займет слишком много времени (даже несколько миллисекунд), либо полностью застрянет (тупик).
Независимо от того, сколько времени он будет ждать, у вас не должно быть кода синхронизации в вашем основном потоке. Но если это тупиковая ситуация, ее перемещение за пределы основного потока исправит только ANR, а обнаружение и устранение тупиковой ситуации само по себе будет другой проблемой.
Если вы еще не проверяли официальный документ об ANR, в котором также говорится о синхронизации и ожидании / уведомлении, что, вероятно, связано с вашей проблемой.
Вкратце: переместите логику синхронизации за пределы основного потока (не делайте этого onPause / onResume) в какую-нибудь фоновую работу.
Невозможно помочь вам больше, не увидев на самом деле вредоносного кода и не зная, что он делает.
Если вы используете следующий фрагмент кода в методе действия 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);
Надеюсь, это поможет вам найти решение.
Удачного кодирования :)
Мы столкнулись с той же проблемой. Это не имеет ничего общего с флагом SCREEN_ON, независимо от того, делаете ли вы это программно или через XML.
В нашем случае сбой произошел из-за отсутствия канала для уведомления onReceive ()
https://developer.android.com/training/notify-user/channels
Starting in Android 8.0 (API level 26), all notifications must be assigned to a channel. For each channel, you can set the visual and auditory behavior that is applied to all notifications in that channel. Then, users can change these settings and decide which notification channels from your app should be intrusive or visible at all.
Возможно, вы захотите найти аналогичную проблему.
Ваш класс GLGame был производным от класса GLSurfaceView.
Это стандартный способ написания игр на Android.
GLSurfaceView.onPause затем вызывается после Activity.onPause.
Внутри GLSurfaceView.onPause есть блокирующая функция wait ():
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 в собственном потоке.
Это не имеет ничего общего с этим флагом. Это связано с тем, что ваше приложение слишком долго использует сторожевую функцию (например, функцию жизненного цикла) в потоке пользовательского интерфейса.