闹钟管理器在安卓6.0的后台不起作用。

13

这是我的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无法执行。有人知道这是怎么回事吗?谢谢。

3个回答

26

有几件事情可以尝试一下,当它们同时使用时,应该能够减少所有空闲/待机/休眠模式(无论操作系统版本)。

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应用的流程图.


1
如果我使用 setExactAndAllowWhileIdle(),那么我是否需要将我的应用程序的最低SDK版本更改为23? - Parag Kadam
1
setExact()仅在API 19及以上版本中可用。因此,在片段中的else if条件中,您还需要进行该检查。 - Henry
setExactAndAllowWhileIdle() 在一些设备上(如金立、小米、三星等)不能始终给出期望的输出......在某些设备上,它不能在完美的时间触发,在其他设备上则无法触发...... - Himanshu
@himCream:您能否详细描述一下您的问题,最好是在一个新的问题里? - Yash Sampat
你在使用什么设备?我建议你先在模拟器中检查它,并确认它是否正常工作... - Yash Sampat
显示剩余4条评论

7

原因可能是由于Android 6.0 Marshmallow引入了待机模式。使用setAlarmclock()代替set()。它专门为闹钟设计,可能能够突破待机模式。有一些adb命令可以手动将手机置于待机或应用程序待机模式:

https://developer.android.com/preview/features/power-mgmt.html

如果以上方法不能唤醒您的应用程序,那么有一个绝对有效的方法setExactAndAllowWhileIdle()专门设计用于从待机模式中唤醒手机。最坏的情况是,您可以使用此方法唤醒您的应用程序,并利用这个唤醒来安排下一次闹钟。
参考资料: 如何在Android 6.0的待机模式下使闹钟管理器工作?

好的,我会尝试。 - Parag Kadam

0
在我的实验中,AlarmManagerCompat + setAlarmClock 在待机模式下唤醒非常稳定。我使用的是小米设备,它使用MIUI系统。
AlarmManagerCompat.setAlarmClock(alarmManager, time, showIntent, pendingIntent)

如果这对你有帮助,请点赞,谢谢!

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