Broadcast
1. Broadcast定义、应用场景及种类
(1) 定义: 广播是一种应用程序间传输信息的机制(类似于Java中的观察者模式)。广播内容是一个intent,携带需要传输的数据。
观察者模式
:被观察者发生变化时,通知观察者做相应的数据处理。
(2) 应用场景:
- 实现不同应用程序间的数据传输和共享(不同app的组件间的消息通信)
注意:和发送
广播的activity具有相同action
的接收
者都可以接受该广播。 - 通知作用( 同一app的不同进程的组件间的消息通信):service通过broadcast向activity发送消息来更新UI
(3) 种类
- 普通广播
- 有序广播(属于系统广播)
- 本地广播:只在app内传播
2. 实现广播(BroadcastReceiver)的两种方式
(1) 静态注册:在manifest.xml中注册广播接收者BroadcastReceiver。广播不会随它所依赖的activity的销毁而销毁,进程杀死也仍能接收广播。
(2) 动态注册:在代码中使用registReveiver()来注册BroadcastReceiver。广播的销毁会跟随activity的生命周期。、
注意
:需在activity的onDistory()方法中调用unregistReveiver()来销毁广播接收者,否则容易引起内存泄漏。
3. 广播内部实现原理(实质是Binder机制)

(1) 广播接收方注册BroadcastReceiver并重写onReceive()方法
(2) 广播接收方通过Binder机制向AMS(Activity Manage Service)进行注册
(3) 广播发送方通过Binder机制向AMS发送广播
(4) AMS查找符合条件(IntentFilter的action标识不同广播)的BroadcastReceiver,并将广播发送到BroadcastReceiver对应的消息队列中
(5) BroadcastReceiver在消息队列中获取此广播,并回调BroadcastReceiver的onReceive()方法,根据action来标识不同的广播并进行处理
本地广播eg
:service通过broadcast向activity发送消息来更新UI;activity也可通过broadcast调用service中的方法
(1) BroadcastTestActivity.java(作为接收方)
package comi.example.liy.mytestdemo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
/**
* Created by liy on 2019-11-05 16:27
*/
public class BroadcastTestActivity extends FragmentActivity {
/*********************服务****************************/
private NotificationService notificationService;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
notificationService = ((NotificationService.MyBinder) service).getService();// 服务已连接
System.out.println("Service连接成功");
//执行服务内部的方法
myService.excute();
}
@Override
public void onServiceDisconnected(ComponentName name) {
notificationService = null;// 未连接为空
}
};
/*********************本地广播****************************/
private MessageReciver mReciver;
private IntentFilter mIntentFilter;
private LocalBroadcastManager mLocalBroadcastManager;//本地广播管理器
// 自定义广播接收者并重写onReceive()方法
class MessageReciver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(NotificationService.MESSAGE_ACTION)) {
String message = intent.getStringExtra("content");
Log.v("通知内容", message);
} else {
Log.v("notification_else", "未知的广播消息");
}
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onPause() {
super.onPause();
unbindService(conn);// 注销服务
mLocalBroadcastManager.unregisterReceiver(mReciver);// 注销广播:最好在onPause()中注销
}
@Override
protected void onStop() {
super.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
private void initData() {
Intent serviceIntent = new Intent(this, NotificationService.class);
bindService(serviceIntent, conn, BIND_AUTO_CREATE);//绑定服务
mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);//获取本地广播管理器实例
mReciver = new MessageReciver();//获取广播接收者
mIntentFilter = new IntentFilter();
mIntentFilter.addAction(NotificationService.MESSAGE_ACTION);//添加广播标识
mLocalBroadcastManager.registerReceiver(mReciver, mIntentFilter);//注册本地广播接收器
}
}
(2) NotificationService.java(作为发送方)
package comi.example.liy.mytestdemo;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
/**
* Created by liy on 2019-11-05 16:36
* Activity调用bindService (Intent service, ServiceConnection conn, int flags)方法,得到Service对象的一个引用,这样Activity可以直接调用到Service中的方法,如果要主动通知Activity,我们可以利用回调方法
* Service向Activity发送消息,可以使用广播,当然Activity要注册相应的接收器。比如Service要向多个Activity发送同样的消息的话,用这种方法就更好。
* Activity中创建广播接收器:Activity中新建内部类继承BroadcastReceiver并重写onReceive()方法,当有广播到来时onReceive()方法就会得到执行。
*/
public class NotificationService extends Service {
private final IBinder binder = new MyBinder();
/**消息通知标识**/
public static final String MESSAGE_ACTION="message_ACTION";
/**本地广播**/
private LocalBroadcastManager mLocalBroadcastManager;
@Override
public IBinder onBind(Intent intent) {
return binder;
}
@Override
public void onCreate() {
super.onCreate();
new NotificationThread().start();//service每隔一段时间发送一条消息,通过broadcast发送给activity来更新UI
mLocalBroadcastManager=LocalBroadcastManager.getInstance(this);
}
class NotificationThread extends Thread {
@Override
public void run() {
super.run();
while (true){
try{
sleep(5000);
}catch (Exception e){
e.printStackTrace();
}
Intent intent=new Intent(MESSAGE_ACTION);
intent.putExtra("content","新的通知");
mLocalBroadcastManager.sendBroadcast(intent);
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
}
public class MyBinder extends Binder {
NotificationService getService() {
return NotificationService.this;//获取MyService的引用,从而可以引用其内部的方法和变量
}
}
public void excute() {
System.out.println("通过Binder得到Service的引用来调用Service内部的方法");
}
}
(3)注意
:别忘记在manifest.xml中注册Activity和Broadcast
<activity android:name=".BroadcastTestActivity"/>
<service android:name=".NotificationService"/>
(4) 拓展
:若要发送多个广播,添加对应代码即可,如



