当前位置: 首页 > news >正文

Android WakefulBroadcastReceiver的使用

WakefulBroadcastReceiver 是一种特殊类型的广播接收器,为应用创建和管理 PARTIAL_WAKE_LOCK 。

简单来说,
WakefulBroadcastReceiver 是持有系统唤醒锁的 BroadcastReceiver ,用于执行需要保持CPU运转的场景。

注册

注册 Receiver ,

<receiver android:name=".MyWakefulReceiver"></receiver>

实现MyWakefulReceiver

重写 onReceive() 方法,使用 startWakefulService(Context context, Intent intent) 启动 Service ,

    public class MyWakefulReceiver extends WakefulBroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {// Start the service, keeping the device awake while the service is// launching. This is the Intent to deliver to the service.Intent service = new Intent(context, MyIntentService.class);startWakefulService(context, service);}}

Service

Service 里执行正常的逻辑,实行结束后调用 MyWakefulReceiver.completeWakefulIntent(Intent intent) 方法。

public class MyIntentService extends IntentService {public MyIntentService() {super("MyIntentService");}@Overrideprotected void onHandleIntent(Intent intent) {Bundle extras = intent.getExtras();// Do the work that requires your app to keep the CPU running.// ...// Release the wake lock provided by the WakefulBroadcastReceiver.MyWakefulReceiver.completeWakefulIntent(intent);}
}

源码分析

startWakefulService(Context context, Intent intent) 方法中,通过 PowerManager.WakeLock 持有了系统锁,并为每个 intent 设置了一个 id 用于标识,存储在 sActiveWakeLocks 数组中,

/*** Do a {@link android.content.Context#startService(android.content.Intent)* Context.startService}, but holding a wake lock while the service starts.* This will modify the Intent to hold an extra identifying the wake lock;* when the service receives it in {@link android.app.Service#onStartCommand* Service.onStartCommand}, it should pass back the Intent it receives there to* {@link #completeWakefulIntent(android.content.Intent)} in order to release* the wake lock.** @param context The Context in which it operate.* @param intent The Intent with which to start the service, as per* {@link android.content.Context#startService(android.content.Intent)* Context.startService}.*/public static ComponentName startWakefulService(Context context, Intent intent) {synchronized (sActiveWakeLocks) {int id = mNextId;mNextId++;if (mNextId <= 0) {mNextId = 1;}intent.putExtra(EXTRA_WAKE_LOCK_ID, id);ComponentName comp = context.startService(intent);if (comp == null) {return null;}PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"androidx.core:wake:" + comp.flattenToShortString());wl.setReferenceCounted(false);wl.acquire(60 * 1000);sActiveWakeLocks.put(id, wl);return comp;}}

当 Service 调用 MyWakefulReceiver.completeWakefulIntent(Intent intent) 方法时,释放系统锁,并根据 id 将此锁从数组中移除,

/*** Finish the execution from a previous {@link #startWakefulService}.  Any wake lock* that was being held will now be released.** @param intent The Intent as originally generated by {@link #startWakefulService}.* @return Returns true if the intent is associated with a wake lock that is* now released; returns false if there was no wake lock specified for it.*/public static boolean completeWakefulIntent(Intent intent) {final int id = intent.getIntExtra(EXTRA_WAKE_LOCK_ID, 0);if (id == 0) {return false;}synchronized (sActiveWakeLocks) {PowerManager.WakeLock wl = sActiveWakeLocks.get(id);if (wl != null) {wl.release();sActiveWakeLocks.remove(id);return true;}// We return true whether or not we actually found the wake lock// the return code is defined to indicate whether the Intent contained// an identifier for a wake lock that it was supposed to match.// We just log a warning here if there is no wake lock found, which could// happen for example if this function is called twice on the same// intent or the process is killed and restarted before processing the intent.Log.w("WakefulBroadcastReceiv.", "No active wake lock id #" + id);return true;}}
http://www.lryc.cn/news/135718.html

相关文章:

  • python知识:什么是字符编码?
  • Vue2中使用Pinia
  • Docker关于下载,镜像配置,容器启动,停止,查看等基础操作
  • 穿越网络迷雾的神奇通道 - WebSocket详解
  • 无脑入门pytorch系列(五)—— nn.Dropout
  • Python土力学与基础工程计算.PDF-压水试验
  • Linux入门
  • 适合国内用户的五款ChatGPT插件
  • Dubbo Spring Boot Starter 开发微服务应用
  • linux中互斥锁,自旋锁,条件变量,信号量,与freeRTOS中的消息队列,信号量,互斥量,事件的区别
  • 安装docker服务,配置镜像加速器
  • CF 896 C Willem, Chtholly and Seniorious(珂朵莉树模板)
  • Android Jetpack组件的全方位分析
  • Prometheus+Grafana+AlertManager监控SpringBoot项目并发送邮件告警通知
  • 猿辅导Motiff亮相IXDC 2023国际体验设计大会,发布新功能获行业高度关注
  • 【QT】重写QAbstractLIstModel,使用ListView来显示多列数据
  • 【从零学习python 】64. Python正则表达式中re.compile方法的使用详解
  • 【FAQ】视频云存储/安防监控EasyCVR视频汇聚平台如何通过角色权限自行分配功能模块?
  • 基于Spring Boot的社区诊所就医管理系统的设计与实现(Java+spring boot+MySQL)
  • mysql从传统模式切到GTID模式后启动主从,主从异常报错1236
  • Qt+C++串口调试接收发送数据曲线图
  • 【从零学习python 】75. TCP协议:可靠的面向连接的传输层通信协议
  • IPv4 基础概念
  • stm32片内读写项目总结(多字节读写tongxindu)
  • ECMAScript6 简介及拓展
  • 可视化构建包分析报告
  • 统一git使用方法,git状态变迁图,git commit提交规范
  • react与vue的区别
  • 成功解决SQL 错误 [22000]: 第3 行附近出现错误: 试图修改自增列[ID](达梦数据库)
  • 【算法】活用双指针完成复写零操作