Я работаю над будильником, и у меня есть серьезная проблема, BroadCastReceiver всегда вызывается точно в срок , я выполняю какую-то работу, например, собираю преднамеренные дополнения, ничего тяжелого или долго, а затем я вызываю тревожную активность.
Там есть очень странное поведение, много раз он просто отлично работает, но иногда вызов активности задерживается , и я говорю о 1-13 минут в моих тестах до сих пор, что совершенно неприемлемо для приложения тревоги.
Это происходит, когда устройство выходит из режима ожидания.
Я использую setExactAndAllowWhileIdle()
, который действительно работает как талисман при вызове получателя, но не запускается активность с получателя.
Вот часть кода получателя:
@Override
public void onReceive(Context context, Intent intent) {
Log.d("Ben", "Alarmreceiver HELLO");
[...]
Log.d("Ben", "Alarmreceiver CALLING WAKE SCREEN NOW");
if (wait) {
new Thread(new Runnable() {
@Override
public void run() {
Log.d("Ben", "AlarmReceiver: Alarm still running, wait for finsihing...");
try {
Thread.sleep(3_000);
} catch (Exception e) {
context.startActivity(new Intent("package.action.alarm").addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
context.startActivity(new Intent("package.action.alarm").addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
}).start();
}
else
context.startActivity(new Intent("package.action.alarm").addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
Log.d("Ben", "Call done.");
}
//end of receiver
Вот что я получаю от LogCat:
06-24 20:50:02.623 6527-6527/package D/Ben: Alarmreceiver HELLO
06-24 20:50:02.753 6527-6527/package D/Ben: Alarmreceiver CALLING WAKE SCREEN NOW
06-24 20:50:02.794 6527-6527/package D/Ben: Call done.
06-24 20:55:09.129 6527-6527/package D/Ben: AlarmActivity.onCreate()
Как вы видите, между командой и фактическим началом действия есть задержка в 5 минут!
Видно, что Log.d "вызов завершен" достигается менее чем через 200 мс.
Запуск не должен быть проблемой, так как он даже не был запущен в этом случае. (Он ожидает завершения ранее запущенного сигнала тревоги, если он был запущен)
Log.d из AlarmActivity.onCreate()
- самое первое утверждение в AlarmActivity, сразу после этого я получаю wakelocks.
Я пытался: intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
, так как я нашел это здесь в другом посте, но никаких изменений в поведении вообще.
Это действительно расстраивает - кто-нибудь знает, почему это происходит или как я могу это исправить?
EDIT
Теперь, когда я обменял новую тему на следующий код:
final PendingResult result = goAsync();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
context.startActivity(new Intent("package.action.alarm").addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
Log.d("Ben", "Runnable done.");
result.finish();
}
}, 2_000);
все кажется работает нормально.
Сегодня я провел 5 долгосрочных тестов, где я установил будильник на +50 или 60 минут каждый, чтобы убедиться, что система обязательно находится в режиме ожидания (я не доверяю режиму adb force doze):
Первые 3 пробега с goAsync
пробежали идеально вовремя.
Четвертый прогон, в котором я изменил код обратно на поток без явного перехода в асинхронное состояние, снова опоздал более чем на 4 минуты.
Пятый тест с postDelayed
и goAsync
снова прошел идеально.
Я считаю, что сейчас это работает надежно, пока оно не зазвонит слишком поздно.
Огромное спасибо Джонасу !!! Я боролся с этой проблемой в течение МЕСЯЦЕВ, думая, что новый поток будет достаточно асинхронным;)
РЕДАКТИРОВАТЬ 2:
Я проверил все это еще 1 неделю, и он все еще не работает.
После того, как я изменил свою работоспособность на:
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
context.startActivity(new Intent("package.action.alarm").addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
Log.d("Ben", "Activity has been called.");
// give an extra 4.5 sec window to start activity and alarm stream...
Handler h = new Handler();
h.postDelayed(new Runnable() {
@Override
public void run() {
result.finish();
Log.d("Ben", "Allowing Rec. finish now...");
}
}, 4_500);
}
}, 2_000);
работает нормально, но не на 100%. (2 секунды - чтобы закончить уже запущенный сигнал тревоги, и с 4,5 секундами я надеюсь дать активности и обслуживанию достаточно времени для запуска потока, тогда он будет работать нормально)
Дополнительная информация:
Приемник запускает Активность, и первым действием там является приобретение Wakelocks (Wi-Fi и питание) и включение экрана.
После этого я выполняю обработку телефонных звонков, а после этого запускаю службу переднего плана, которая будет транслировать музыку.
У меня есть Log.d повсюду, и я вижу, что иногда, когда поток буферизует слишком долго - так, что прошло 4,5 секунды в BR, устройство засыпает и не начинает потоковую передачу музыки до случайного время прошло снова (окно технического обслуживания, я думаю), ДАЖЕ ЕСЛИ БУДЕТЕ УЖЕ БЫЛО, УЖЕ ПРИОБРЕТЕНО.
Это не имеет никакого отношения к Runnable, я теперь выяснил. Я удалил его и вызвал Activity прямо в конце BR, что привело к почти определенной задержке в несколько минут в процедуре запуска активности. Без асинхронности - еще быстрее засыпает ...
Как мне начинать действие с приемника вещания, который не засыпает / не дремлет, когда БР закончен?
Это похоже на ошибку для меня. Или я упускаю что-то очень простое.Экран включен и остается включенным, но потоковая служба переднего плана иногда запускается после этой задержки (несколько минут).
То же самое происходит, когда я запускаю службу переднего плана из BR.Служба переднего плана иногда останавливается в середине onCreate, потому что BR заканчивается, и устройство, кажется, спит (задремал) ...
Я действительно в отчаянии.
Когда я дал 7,5 вместо 4,5 секунд второму работоспособному в BR, я мог заметить ANR в консоли Google.(Хотя я считаю, что сигнализация работала нормально).
Как правильно решить эту проблему?Запуск asyncTask?
РЕДАКТИРОВАТЬ 3:
Джонас, спасибо за ваш ответ еще раз - я целую неделю пробовал много разных подходов, и на моих устройствах все выглядит нормально,но пользователи сообщают о задержках до 13 минут…
2 вещи, которые я пробовал:
запуск ForegroundService с уведомлением и wakelocks как единственное действие в AlarmReceiverи выполняя всю работу внутри службы
, удаляя приемник и запуская AlarmActivity напрямую, чтобы выполнить все как можно быстрее - захватить пробуждения и включить экран в качестве первого шага в упражнении,после этого получаю IntentExtras и запускаю музыку StreamService в качестве третьей вещи (все это в течение 1-2 секунд)
этот второй подход - мое текущее состояние, и я думал, что он работает хорошо, пока кто-тоснова сообщил о 13-минутной задержке.
ForegroundService вообще не работал - он часто засыпал передКогда играла музыка ... Я позволил завершить эту службу только тогда, когда музыка уже начала играть, но иногда это происходило после задержки - я понятия не имею, как?Это не может быть правильным, служба переднего плана с удерживаемыми wakelocks ДОЛЖНА держать устройство в активном состоянии!?!?
(я бы опубликовал Activity, но он состоит из 750 строк, так что ... нет.)
В любом случае: что еще я могу сделать, чтобы ДЕЙСТВИТЕЛЬНО удерживать / выводить устройство из режима ожидания?
setExactAndAllowWhileIdle РАБОТАЕТ ОТЛИЧНО
получение wakelocks работает отлично
получение IntentExtras кажется, работает хорошо
Через некоторое время после этого устройство засыпает, хотя у меня появились пробуждения и экран включен.
музыкальный сервис запускается, но не завершает буферизацию из-за (я полагаю) режима ожидания снова
воспроизведение музыки начинается через x минут
это то, что я видел в журналах, теперь он работает нормально в 99% случаев, но все еще редко.Что мне не хватает?Есть ли магическая функция, которая не дает дремать в течение x минут?