设备重启后启动AlarmManager

24
在我的应用程序中,我想每天在特定时间运行一些代码,使用AlarmManager实现。在Android文档中找到了这段话:

注册的闹钟会在设备睡眠时保留[...]但如果设备关闭并重新启动,则会清除注册的闹钟。

这就是问题所在。即使用户重新启动手机,我仍希望能够运行代码。目前,如果用户重新启动手机,他必须重新启动我的应用程序才能重新开启闹钟。有什么方法可以防止这种情况发生吗?是否有更好的机制可以代替?

1
创建一个接收器以便在启动完成后设置闹钟管理器(如果您的应用程序之前有任何闹钟,请先清除它们)。 - Athul Harikumar
1
尝试这个:https://dev59.com/L3PYa4cB1Zd3GeqPm8KV#17315856 - Poovizhirajan N
非常有用的问题。 - ivanleoncz
3个回答

35

使用以下代码创建启动接收器:

public class BootBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context pContext, Intent intent) {
        if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
            // Do your work related to alarm manager
        }
    }
}
在您的清单文件中,注册此广播接收器:

<receiver
android:name="com.yourapp.BootBroadcastReceiver"
android:enabled="true" >
<intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>

不要忘记在 AndroidManifest.xml 文件中添加权限:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

1
onReceive()方法似乎没有调用getAction来确保接收到的Intent的动作字符串与预期值匹配,这可能使另一个操作者发送伪造的意图而不带动作字符串或不同的动作字符串,并引起不希望的行为。因此,在您的onReceive()中应添加以下代码行:if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { // 在此处执行您的工作 } - Marija
AndroidManifest 中需要定义两个接收器吗? - DaveTheMinion

6

您可以使用广播接收器在设备启动时创建服务。

 <receiver android:enabled="true" android:name=".YourReceiver"
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</receiver>

权限:

 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

3
您需要在清单文件中添加一个引导接收器,如下所示:

<application ...  >

    <receiver android:name=".OnBootReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <uses-permission android:name="android.permission.WAKE_LOCK" />
        </intent-filter>
    </receiver>
</application>

然后创建像这样的引导接收器类...

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class OnBootReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context ctxt, Intent intent) {
AlarmHelper.setAlarm(ctxt);
}
}

我的闹钟帮助类是一个简单的每天起床闹钟,像这样...

public class AlarmHelper {

public static void testAlarm(Context context) {
Calendar when = Calendar.getInstance();
when.add(Calendar.SECOND, 10);
setAlarm(context, when);    
}

public static void setAlarm(Context context) {
Calendar when = Calendar.getInstance();
when.add(Calendar.DAY_OF_YEAR, 1);
when.set(Calendar.HOUR_OF_DAY, 0);
when.set(Calendar.MINUTE, 0);
when.set(Calendar.SECOND, 0);
setAlarm(context, when);
}

    @SuppressLint("SimpleDateFormat")
private static void setAlarm(Context context, Calendar when) {

SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(context.getApplicationContext());

Boolean showNotifications = prefs.getBoolean("PREF_SHOW_NOTIFICATIONS",
false);

if (showNotifications) {    
AlarmManager am = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);

am.setRepeating(AlarmManager.RTC_WAKEUP, when.getTimeInMillis(), AlarmManager.INTERVAL_DAY, getPendingIntent(context.getApplicationContext()));

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

Log.i(TAG, "Alarm set " + sdf.format(when.getTime()));
}
}

1
请确保将使用权限 (<uses-permission android:name="android.permission.WAKE_LOCK" />) 放置在清单文件的正确位置(通常是在活动之前)。 - UKDataGeek

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