在安卓系统中,深度睡眠通常指的是设备处于低功耗状态,CPU停止运行,大部分后台进程暂停,以节省电量。这时候设备不会响应一般的事件,比如通知或者网络请求,除非有特定的唤醒机制。
常见的方法可能有使用AlarmManager设置重复的定时任务,或者使用WakeLock来保持CPU运行。不过,WakeLock需要特别权限,而且不当使用会导致电池耗尽,所以需要谨慎。
如果需要在特定时间执行任务的应用,比如闹钟或者定时提醒。这时候使用AlarmManager可能更合适,特别是setExactAndAllowWhileIdle或者setAlarmClock这类方法,可以在深度睡眠时唤醒设备。
AlarmManager(精准闹钟)​适用于定时触发任务(如闹钟、定时同步数据):
    /**
     * 设置定时闹钟,唤醒深度睡眠的设备,执行任务。
     * */
    public void setAlarmManagerTask() {
        // 获取 AlarmManager 实例
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        // 创建 PendingIntent,用于在定时任务触发时执行特定的操作
        Intent intent = new Intent(this, MyBroadcastReceiver.class);
        // requestCode设置为一个特殊的数字(123456),避免和其他PendingIntent相同。
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 123456, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        //先取消,再注册,在MyBroadcastReceiver中执行任务完成后,重新调用此函数,实现定时执行任务。
        alarmManager.cancel(pendingIntent);

        // 设置定时任务,每隔一段时间唤醒设备并执行操作
        // 这里不使用System.currentTimeMillis()因为app时间和系统时间因为时区可能导致不一样。
        Date dateNow = new Date();
        // 10秒后触发定时任务。当前时间点增加10秒。
        long triggerAtMillis = dateNow.getTime() + (10 * 1000);
        // 每隔1分钟重复执行一次
        long intervalMillis = 60 * 1000;

        // 使用 RTC_WAKEUP 确保设备休眠时唤醒
        // 方式1:设置重复闹钟(经过测试,会有不准确的情况,原因是此方法会被系统调整。)
        //alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtMillis, intervalMillis, pendingIntent);

        //方式2:使用setExact和setExactAndAllowWhileIdle设置闹钟,然后在MyBroadcastReceiver中重新调用此方法注册新闹钟。
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
        } else {
            alarmManager.set(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
        }
    }

创建广播接收器
在上述代码中,我们创建了一个 BroadcastReceiver 类来处理设备唤醒后的操作。以下是一个简单的示例:

public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 在设备唤醒后执行的操作
        Toast.makeText(context, "设备已唤醒,任务执行中...", Toast.LENGTH_SHORT).show();
        // 重新注册闹钟,实现定时循环任务。
        setAlarmManagerTask();
    }
}

注册 BroadcastReceiver
为了使广播接收器能正常接收到定时任务触发的广播,我们还需要在 AndroidManifest.xml 文件中注册该广播接收器。
注:唤醒设备需要具有权限 android.permission.WAKE_LOCK
以下是注册广播接收器的示例代码:

<manifest xmlns:android=" package="com.example.myapp">
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <application>
        <receiver android:name=".MyBroadcastReceiver" />
    </application>
</manifest>

AlarmManager方法对比:
set()允许系统在休眠时延迟触发,以节省电量。非关键任务(如定期更新)
setExact()强制准时触发,不延迟。需要精确时间的任务
setRepeating()周期性触发,但间隔可能被系统调整。周期性任务(但不要求严格间隔)
setExactAndAllowWhileIdle()允许在 Doze 模式下立即触发(但可能增加耗电)。极端紧急任务(如报警)
取消闹钟:
创建与设置时相同的 PendingIntent,必须使用相同的 requestCode、Intent 数据和 flags。
调用 alarmManager.cancel(pendingIntent),传入对应的 PendingIntent 即可取消关联的闹钟。

alarmManager.cancel(pendingIntent);
pendingIntent.cancel(); // 清理 PendingIntent

资源管理:
务必通过 alarmManager.cancel(pendingIntent) 取消不再需要的闹钟,避免内存泄漏。
使用 PendingIntent.FLAG_UPDATE_CURRENT 或 FLAG_IMMUTABLE 确保 PendingIntent 行为可控。
PendingIntent 要执行的操作:
当闹钟触发时,系统会通过此 PendingIntent 启动目标组件(如 BroadcastReceiver 或 Service)。
必须通过 PendingIntent.getActivity()、PendingIntent.getService() 或 PendingIntent.getBroadcast() 创建。
Doze 模式兼容性:
在 Android 6.0(API 23)及以上,系统会进入 Doze 模式以延长续航,此时普通闹钟(如 setExact())可能被延迟。
setExactAndAllowWhileIdle() 会绕过 Doze 模式的限制,但频繁使用会显著增加耗电。​
触发时间限制:
在 Doze 模式下,系统可能会将多次连续的精确闹钟合并,或推迟到维护窗口执行。若需更严格的实时性(如每秒触发),需结合前台服务(ForegroundService)。

通过使用 AlarmManager 类和 BroadcastReceiver 类,我们可以实现在 Android 设备的深度休眠模式下唤醒设备并执行特定的操作。这种方法可以用于定时任务、后台数据同步等场景。希望本文能帮助你理解如何在 Android 中实现深度休眠唤醒。

posted on 2025-05-28 10:11  邢帅杰  阅读(202)  评论(0)    收藏  举报