-
Android广播(Broadcast)
一、Broadcast简介
Broadcast是android中的四大组件之一,是在组件之间传播数据(Intent)的一种机制。广播的发送者和接收者事先是不需要知道对方的存在的。这样带来的好处便是,系统的各个组件可以松耦合地组织在一起,这样系统就具有高度的可扩展性,容易与其它系统进行集成。
广播具有以下特性:
1.广播接收者的生命周期是非常短暂的,在接收到广播的时候创建,onReceive()方法结束之后销毁
2.广播接收者中不要做一些耗时的工作,否则会弹出Application No Response错误对话框
3.最好也不要在广播接收者中创建子线程做耗时的工作,因为广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉
4.耗时的较长的工作最好放在服务中完成二、Broadcast的分类
-
普通广播(自定义广播)
普通广播是完全异步的,通过Context的sendBroadcast()方法来发送,通过onReceive方法接收。消息传递效率比较高,但所有receivers(接收器)的执行顺序不确定。缺点在于:接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播,直到没有匹配的接收器广播时才能停止传播。
-
系统广播
Android中内置了多个系统广播:只要涉及到手机的基本操作(如开机、网络状态变化、拍照等等),都会发出相应的广波,每个广播都有特定的Intent - Filter(包括具体的action),android常用系统广播action如下:
-
有序广播(Ordered Broadcast)
Android中的有序广播,也是一种比较常用的广播,该种类的广播用sendOrderedBroadcast发送。该广播主要有以下特性:
- 按照接收者的优先顺序来接收广播,优先级别在intent-filter中的priority中声明,-1000到1000之间,值越大优先级越高
- 可以终止广播的继续传播,接受者可以修改intent的内容。
- 同级别接收顺序是随机的,级别低的后收到
- 能截断广播的继续传播,高级别的广播接收器接收广播后能决定时候截断。能处理广播
- 同级别动态注册高于静态注册
-
粘性广播(Sticky Broadcast)
粘性广播的特点是Intent会一直保留到广播事件结束,而这种广播也没有所谓的10秒限制,10秒限制是指普通的广播如果onReceive方法执行时间太长,超过10秒的时候系统会将这个广播置为可以干掉的candidate,一旦系统资源不够的时候,就会干掉这个广播而让它不执行。该广播用sendStickyBroadcast发送。 -
App应用内广播(Local Broadcast)
因为android中的广播是可以跨域的(跨App),因此可能存在一下问题:其他App针对性发出与当前App intent-filter相匹配的广播,由此导致当前App不断接收广播并处理;其他App注册与当前App一致的intent-filter用于接收广播,获取广播具体信息; 即会出现安全性和效率性的问题。
对于上述情况就出现了这种广播,App应用内广播可理解为一种局部广播,广播的发送者和接收者都同属于一个App。相比于全局广播(普通广播),App应用内广播优势体现在:安全性高效率高。
三、BroadcastReceiver
BroadcastReceiver是一种可以让用户接受广播通知且没有用户界面的组件,在android系统中为了响应不同的事件通知,应用程序可以注册不同的BroadcastReceiver,当BroadcastReceiver接受到通知后可以启动Activity作为响应或者通过NotificationManager提醒用户。对于不同注册方式的广播接收器回调OnReceive(Context context,Intent intent)中的context返回值是不一样的:
- 对于静态注册(全局+应用内广播),回调onReceive(context, intent)中的context返回值是:ReceiverRestrictedContext;
- 对于全局广播的动态注册,回调onReceive(context, intent)中的context返回值是:Activity Context;
- 对于应用内广播的动态注册(LocalBroadcastManager方式),回调onReceive(context, intent)中的context返回值是:Application Context。
三、广播的实现
一段比较典型的实现代码为:
(1)实现一个广播接收器
public class MyBroadcastReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Toast.makeText(context, "received in MyBroadcastReceiver", Toast.LENGTH_SHORT).show();abortBroadcast();} }
主要就是继承一个BroadcastReceiver,实现onReceive方法,在其中实现自己的业务逻辑就可以了。
(2)注册广播
public class MainActivity extends AppCompatActivity {private IntentFilter intentFilter;private MyBroadcastReceiver myBroadcastReceiver;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);intentFilter = new IntentFilter();intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");myBroadcastReceiver = new MyBroadcastReceiver();registerReceiver(myBroadcastReceiver, intentFilter);Button button = (Button) findViewById(R.id.button);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent("android.net.conn.CONNECTIVITY_CHANGE");sendBroadcast(intent); // 发送广播}});}@Overrideprotected void onDestroy() {super.onDestroy();unregisterReceiver(myBroadcastReceiver);} }
-
这样MyBroadcastReceiver就可以收到相应的广播消息了。
四、静态注册广播的实现
还是用上面的按个MyBroadcastReceiver,只不过这次采用静态注册的方式
在manifest文件中增加如下的代码:
<receiverandroid:name=".MyBroadcastReceiver"android:enabled="true"android:exported="true"><intent-filter><action android:name="android.net.conn.CONNECTIVITY_CHANGE" /></intent-filter></receiver>
几个相关解释:
android:exported
此BroadcastReceiver能否接收其他App发出的广播(其默认值是由receiver中有无intent-filter决定的,如果有intent-filter,默认值为true,否则为false);android:name
此broadcastReceiver类名;android:permission
如果设置,具有相应权限的广播发送方发送的广播才能被此broadcastReceiver所接收;android:process
broadcastReceiver运行所处的进程。默认为App的进程。可以指定独立的进程(Android四大组件都可以通过此属性指定自己的独立进程);