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

Android的BroadcastReceiver

1.基本概念:BroadCast用于进程间或者线程间通信

本质上是用Binder方法,以AMS为订阅中心,完成注册,发布,监听的操作。

2.简单实现的例子

package com.android.car.myapplication;


import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;



public class MainActivityBroadCast extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_carsetting);

        //系统广播
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        BatteryReceiver batteryReceiver = new BatteryReceiver();
        registerReceiver(batteryReceiver,intentFilter);
    }

    public class BatteryReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Bundle bundle = intent.getExtras();
            int current = bundle.getInt("level");
            int total = bundle.getInt("scale");

            if(current * 1.0 / total ==1){
                System.out.println("当前手机电量为"+(current / total)*100+"%");
            }
        }
    }
}

用法很简单不多赘述。

3.接收端registerReceiver

ContextImp:Context的最终实现类。class ContextImpl extends Context

  • ContextImpl.registerReceiver方法:
。。。。。。

//注册binder应用和action到系统
final Intent intent = ActivityManager.getService().registerReceiver(
                    mMainThread.getApplicationThread(), mBasePackageName, rd,filter,...);
  • ActivityManager中getService()实际上是一个Binder
    在ActivityManager.java中可看到:
public static IActivityManager getService() {
         return IActivityManagerSingleton.get();
     }
 
     private static final Singleton<IActivityManager> IActivityManagerSingleton =
             new Singleton<IActivityManager>() {
                 @Override
                 protected IActivityManager create() {
                     final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                     final IActivityManager am = IActivityManager.Stub.asInterface(b);
                     return am;
                 }
             };
 }
  • 所以registerReceiver最后是一个向ActivityManagerService的Binder调用,只不过设计上加上了的发布订阅模式

4.发送端 sendBroadcast

  • 首先调用context的sendBroadCast方法
// Context.java

public abstract void sendBroadcast(@RequiresPermission Intent intent);
  • 调到实现类ContextImpl
// ContextImpl.java(extents Context.java)
    @Override
    public void sendBroadcast(Intent intent) {
        warnIfCallingFromSystemProcess();
        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
        try {
            intent.prepareToLeaveProcess(this);
            ActivityManager.getService().broadcastIntent(
                    mMainThread.getApplicationThread(), intent, resolvedType, null,
                    Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                    getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
  • 同理调用到ActivityManagerService的broadcastIntent方法。

(AMS中关于发布订阅的实现,不在本文范围之内,后续遇到问题再继续研究)

5.总结

如果了解发布订阅的设计模式
了解发布,订阅,订阅中心的模型,那么BroadCastReceiver的基本实现原理就清楚了。

  • 接收端首先订阅,即调用Binder方法registerReceiver。
  • AMS会记下对这个Intent感兴趣的进程
  • 发送端通过Binder方法sendBroadCast发送一个Intent。
  • AMS会收到Intent消息
  • AMS找到所有对Intent消息感兴趣的接收端,将这个消息发到接收端
  • 接收端进入实现的onReceive方法。

参考图:https://www.cnblogs.com/andy-songwei/p/10400259.html
在这里插入图片描述收到


http://www.kler.cn/a/387655.html

相关文章:

  • c#使用COM接口设置excel单元格宽高匹配图片,如何计算?
  • 使用VSCode远程连接服务器并解决Neo4j无法登陆问题
  • 基于表格滚动截屏(表格全部展开,没有滚动条)
  • go T 泛型
  • 力扣.15 三数之和 three-sum
  • LeetCode【0016】最接近的三数之和
  • Linux实验day05-Linux磁盘分区的规则、磁盘分区、格式化、挂载、df、du命令
  • 【AI日记】24.11.09 我对贫困问题的一些思考
  • 《深入浅出Apache Spark》系列②:Spark SQL原理精髓全解析
  • UE5材质篇 2 ICE 冰材质尝试
  • 前端前置——ajax
  • 前端递归获取树(不限制层级)结构下的某个字段并组成数组返回
  • WPF 打包
  • Vue前端开发之自定义动画
  • 如何在 Android 14 中调整字体最大 大小 和 显示最大一格 大小
  • 【AI技术】Edge-TTS 国内使用方法
  • 问题排查:C++ exception with description “getrandom“ thrown in the test body
  • Ubuntu实现双击图标运行自己的应用软件
  • Windows系统中Oracle VM VirtualBox的安装
  • 2024年第四届“网鼎杯”网络安全比赛---朱雀组Crypto- WriteUp
  • 计算机网络常见面试题(一):TCP/IP五层模型、TCP三次握手、四次挥手,TCP传输可靠性保障、ARQ协议
  • 个性化培训:扫码分组指南
  • ResNet 残差网络 (乘法→加法的思想 - 残差连接是所有前沿模型的标配) + 代码实现 ——笔记2.16《动手学深度学习》
  • FPGA时序分析和约束学习笔记(4、IO传输模型)
  • Linux命令学习,git命令
  • Node-Red二次开发:各目录结构说明及开发流程