Alarm Manager не работает в фоновом режиме на Android 6.0
Это мой код Activity
,
Long time = new GregorianCalendar().getTimeInMillis()+20000;//Setting alarm after 20 sec
Intent intentAlarm = new Intent("alarm");
intentAlarm.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intentAlarm.putExtra("req_code",10);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,10, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, time, pendingIntent);
Это все разрешения, которые у меня есть в моем приложении,
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="com.myapp.pack.permission.SET_ALARM"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Это мой код BroadcastReceiver
,
@Override
public void onReceive(Context context, Intent intent) {
SharedPreferences sharedPreferences =
context.getSharedPreferences( "mydata", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean("elligible",true);
editor.apply();
}
Я зарегистрировал свой BroadcastReceiver
в манифесте,
<receiver android:name="com.myapp.pack.AlarmReciever" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="alarm" />
</intent-filter>
</receiver>
Вышеупомянутый код успешно выполняет BroadcastReceiver
на устройствах pre-MarshMallow в фоновом режиме, но на устройстве MarshMallow BroadcastReceiver
не выполняется. Кто-нибудь знает, что может происходить здесь? Спасибо.
Ответы
Ответ 1
Есть несколько вещей, которые вы можете попробовать, которые при совместном использовании должны иметь возможность разрезать все режимы бездействия/ожидания/доза (независимо от версии ОС).
1. Используйте WakefulBroadcastReceiver
вместо обычного BroadcastReceiver
. Убедитесь, что вы включили разрешение WAKE_LOCK
, чтобы использовать его правильно.
2. Используйте метод setExactAndAllowWhileIdle()
(по API 23 и выше), чтобы запланировать Intent
для получателя:
if(Build.VERSION.SDK_INT < 23){
if(Build.VERSION.SDK_INT >= 19){
setExact(...);
}
else{
set(...);
}
}
else{
setExactAndAllowWhileIdle(...);
}
Литература:
1. Менеджер аварийных сигналов для фоновых служб.
2. Блок-схема фоновой работы, аварийных сигналов и вашего приложения для Android.
Ответ 2
Причиной может быть Режим Doze, представленный в Android 6.0 Marshmallow. Используйте setAlarmclock() вместо set()
. Он разработан специально для будильников и может прорезать дозу. Есть несколько команд adb, которые вы можете использовать для ручного перевода телефона в режим ожидания или ожидания приложения:
https://developer.android.com/preview/features/power-mgmt.html
Если это не способно разбудить ваше приложение, то метод surefire setExactAndAllowWhileIdle() предназначен для пробуждения телефона от доза не важно что. В худшем случае вы можете разбудить свое приложение с помощью этого метода и использовать пробуждение для планирования следующего аварийного сигнала.
Справка:
Как заставить Alarm Manager работать, когда Android 6.0 в режиме Doze?
Ответ 3
Вы можете использовать workmanager, как упомянуто в ссылке. Он поддерживает все версии API и прост в использовании, поскольку использует обратную совместимость с уровнем API 14.
https://developer.android.com/topic/libraries/architecture/workmanager
https://medium.com/androiddevelopers/introducing-workmanager-2083bcfc4712