警报管理器在 Android 6.0 上无法在后台运行
Alarm Manager does not work in background on 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>
以上代码在后台成功地在 MarshMallow 之前的设备上执行了 BroadcastReceiver
,但是在 MarshMallow 设备上,BroadcastReceiver
没有被执行。有谁知道这里会发生什么?谢谢。
原因可能是 Doze mode introduced in Android 6.0 Marshmallow. Use setAlarmclock() 而不是 set()
。它是专门为闹钟设计的,也许可以打瞌睡。您可以使用一些 adb 命令手动将 phone 置于打瞌睡或应用程序待机模式:
https://developer.android.com/preview/features/power-mgmt.html
如果这无法唤醒您的应用程序,那么万无一失的方法 setExactAndAllowWhileIdle() 旨在无论如何将 phone 从休眠中唤醒。最坏的情况,你可以用这个方法唤醒你的应用程序,并使用唤醒来安排下一个闹钟。
参考:
有一些你可以尝试的东西,当它们一起使用时,应该能够切断所有 idle/standby/doze 模式(不管 OS版)。
1.使用WakefulBroadcastReceiver
instead of an ordinary BroadcastReceiver
. Make sure you include the 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. Alarm manager for background services.
2. A flowchart for background work, alarms, and your Android app.
在我的实验中,AlarmManagerCompat + setAlarmClock 可以稳定地在休眠模式下唤醒。我用的是小米的MIUI
AlarmManagerCompat.setAlarmClock(alarmManager, time, showIntent, pendingIntent)
如果这对您有好处,请投票,干杯!
这是我的 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>
以上代码在后台成功地在 MarshMallow 之前的设备上执行了 BroadcastReceiver
,但是在 MarshMallow 设备上,BroadcastReceiver
没有被执行。有谁知道这里会发生什么?谢谢。
原因可能是 Doze mode introduced in Android 6.0 Marshmallow. Use setAlarmclock() 而不是 set()
。它是专门为闹钟设计的,也许可以打瞌睡。您可以使用一些 adb 命令手动将 phone 置于打瞌睡或应用程序待机模式:
https://developer.android.com/preview/features/power-mgmt.html
如果这无法唤醒您的应用程序,那么万无一失的方法 setExactAndAllowWhileIdle() 旨在无论如何将 phone 从休眠中唤醒。最坏的情况,你可以用这个方法唤醒你的应用程序,并使用唤醒来安排下一个闹钟。
参考:
有一些你可以尝试的东西,当它们一起使用时,应该能够切断所有 idle/standby/doze 模式(不管 OS版)。
1.使用WakefulBroadcastReceiver
instead of an ordinary BroadcastReceiver
. Make sure you include the 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. Alarm manager for background services.
2. A flowchart for background work, alarms, and your Android app.
在我的实验中,AlarmManagerCompat + setAlarmClock 可以稳定地在休眠模式下唤醒。我用的是小米的MIUI
AlarmManagerCompat.setAlarmClock(alarmManager, time, showIntent, pendingIntent)
如果这对您有好处,请投票,干杯!