1、Android广播机制
广播作为Android组件间的通信方式,使用场景如下:
- 同一app内部的同一组件内的消息通信(单个或多个线程之间)
- 同一app内部的不同组件之间的消息通信(单个进程)
- 同一app具有多个进程的不同组件之间的消息通信
- 不同app之间的组件之间消息通信
- Android系统在特定情况下与App之间的消息通信
从实现原理上看,Android中的广播使用了观察者模式,基于消息的发布/订阅事件模型。因此,从实现的角度来看,Android中的广播将广播的发送者和接受者极大程度解耦,使得系统能够方便集成,更易扩展。具体实现流程如下:
1)广播接收者BroadcastReceiver通过Binder机制向AMS(Activity Manager Service)进行注册;
2)广播发送者通过binder机制向AMS发送广播;
3)AMS查找符合相应条件(IntentFilter/Permission等)的BroadcastReceiver,将广播发送到BroadcastReceiver(一般情况下是Activity)相应的消息循环队列中;
4)消息循环执行拿到此广播,回调BroadcastReceiver中的onReceive()方法。
分析实际应用中的适用性:
第一种情形:同一app内部的同一组件的消息通信(单个或多个线程之间),实际应用中肯定是不会用到广播机制的,无论是适用扩展变量域、基于接口的回调还是Handler-post/Handler-Message等方式,都可以直接处理此类问题,若使用广播机制,显然不太合适。
第二种情形:同一app内部的不同组件之间的消息通信(单个进程),对于此类需求,在有些复杂的情况下单纯的依靠基于接口的回调等方式不好处理,此时可以直接使用EventBus等,相对而言,EventBus由于是针对统一进程,用于处理此类需求非常适合,且轻松解耦。
第三、四、五情形:由于涉及不同进程间的消息通信,此时根据实际业务使用广播机制会显得非常适宜。
广播接收者的具体使用方法:
1)自定义BroadcastReceiver
自定义广播接收者需要继承基类BroadcastReceiver,并实现抽象方法onReceive(context,intent)方法。广播接收器接收到广播后,会自动回到onReceive()方法默认情况下,广播接收器也是运行在UI线程,因此,onReceive方法中不能执行太耗时的操作,否则将导致ANR。一般情况下,根据实际业务需求,onReceive方法中都会涉及到与其他组件之间的交互,如发送Notification、启动Service等。
下面是代码实现自定义BroadcastReceiver:
public class MyBroadcastReceiver extends BroadcastReceiver{
public static final String TAG="MyBroadcastReceiver";
public static int m=1;
@Override
public void onReceive(Context context,Intent intent){
Log.w(TAG,"intent:"+intent);
String name=intent.getStringExtra();
Log.w(TAG,"name:"+name+"m="+m);
m++;
}
}
2)BroadcastReceiver注册类型
分为两种注册类型:静态注册和动态注册。
静态注册:直接在清单文件中进行注册。
<receiver android:enabled=["true" | "false"]
android:exported=["true" | "false"]
android:icon="drawable resource"
android:label="string resource"
android:name="string"
android:permission="string"
android:process="string" >
. . .
</receiver>
注意:android:exported---此BroadcastReceiver能否接收其他APP发出的广播,这个属性默认在是由receiver有无intent-fler(不明白)决定的,如果有intent-filter,默认在为true,否则为false。
常见的注册形式有:
<receiver android:name=".MyBroadcastReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver
其中,intent-filter指定此广播接收器接收特定的广播类型。本示例中给出的是用于接收网络状态改变或开机启动时系统自身所发出的广播。当此APP首次启动时,系统会实例化MyBroadcastReceiver,并注册到系统中。
注:Android3.1以后,app退出后,系统将接收不到对应的广播
动态注册:
动态注册时,无需在AndroidManifest.xml中注册<receiver/>组件。直接在代码中通过调用Context的registerReceiver函数,可以在程序中动态注册BroadcastReceiver.定义形式如下:
registerReceiver(BroadcastReceiver receiver,IntentFilter filter)
registerReceiver(BroadcastReceiver receiver,IntentFilter filter,
String broadcastPermission,Handler scheduler)
典型写法如下:
public class MainActivity extends Activity{
public static final String BROADCAST_ACTION="com.example.corn";
private BroadcastReceiver mBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBroadcastReceiver=new MyBroadcastReceiver();
IntentFilter intentFilter=new IntentFilter();
intentFilter.addAction(BROADCAST_ACTION);
registerReceiver(mBroadcastReceiver,intentFilter);
}
@Override
protected void onDestroy(){
super.onDestroy();
unregisterReceiver(mBroadcastReceiver);
}
}
发送广播
广播的发送和接收,表面上看广播作为Android广播机制中的实体,实际上这一实体本身是并不是以所谓“广播”对象存在的,而是以“意图”(Intent)去表示。定义广播的定义过程,实际就是相应广播“意图的定义过程”,然后通过广播发送者将此“意图”发送出去。被相应的BroadcastReceiver接收后将会回调onReceive()函数。
Intent intent=new Intent();
intent.setAction(BROADCAST_ACTION);
intent.putExtra("name","xxxxxx");
sendBroadcast(intent);