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