【问题标题】:Start AlarmManager if device is rebooted如果设备重新启动,则启动 AlarmManager
【发布时间】:2013-07-14 11:15:12
【问题描述】:

在我的应用程序中,我想使用AlarmManager 每天在特定时间运行一些代码。在android documentation 我发现了这个:

在设备处于睡眠状态时会保留已注册的警报 [...],但如果将其关闭并重新启动,则会被清除。

这就是问题所在。即使用户重新启动手机,我也想运行代码。如果用户重新启动手机,他目前必须重新启动我的应用程序才能再次启动警报。我怎样才能防止这种情况?我应该使用更好的机制吗?

【问题讨论】:

标签: android restart android-alarms reboot


【解决方案1】:

使用以下代码创建引导接收器:

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" />

【讨论】:

  • onReceive() 方法似乎没有调用 getAction 来确保接收到的 Intent 的操作字符串与预期值匹配,这可能使另一个参与者可以发送没有操作字符串的欺骗意图或不同的操作字符串并导致不良行为。所以你应该在你的 onReceive() 中添加这行代码: if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { // 在这里做你的工作 }
  • 两个接收者都需要在AndroidManifest中定义吗?
【解决方案2】:

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

 <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()));
    }
    }
    

    【讨论】:

    • 确保将使用权限 () 放入清单文件中的正确位置。 (通常在活动之前)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-14
    • 1970-01-01
    • 2021-04-25
    相关资源
    最近更新 更多