什么是BroadcastReceiver
BroadcastReceiver是Android体系的四大组件之一,本质上是一种全局的监听器,用于监听系统全局的广播消息,正式因为其本质为全局监听,因此可以非常方便的实现系统中不同组件之间的通信。也方便我们自己的app针对系统开机、电量低等广播做出相应反映。同时我们也可以自己发送广播,来实现不同组件之间的通信
系统接收短信广播,然后弹出Toast:
package cn.lixyz.broadcastreceiver; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.util.Log; import android.widget.Toast; public class MainActivity extends Activity { private IntentFilter filter; private SMSReceiver sms; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED"); sms = new SMSReceiver(); registerReceiver(sms, filter); } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); unregisterReceiver(sms); } class SMSReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "有短信", Toast.LENGTH_SHORT).show(); Log.d("TTTT", "~~~~~~~"); } } }
还需要添加权限:
<uses-permission android:name="android.permission.RECEIVE_SMS" />
运行结果:
Android的大量系统事件都会对外发送广播,下面是常见的广播常量:
ACTION_TIME_CHANGED 系统时间被改变
ACTION_DATE_CHANGED 系统日期被改变
ACTION_TIMEZONE_CHANGED 系统时区被改变
ACTION_BOOT_COMPLETED 系统启动完成
ACTION_PACKAGE_ADDED 系统添加包
ACTION_PACKAGE_CHANGED 系统的包改变
ACTION_PACKAGE_REMOVED 系统的包被删除
ACTION_PACKAGE_RESTARTED 系统的包被重启
ACTION_PACKAGE_DATA_CLEARED 系统的包数据被清空
ACTION_BATTERY_CHANGED 电池电量改变
ACTION_BATTERY_LOW 电池电量低
ACTION_POWER_CONNECTED 系统连接电源
ACTION_POWER_DISCONNECTED 系统与电源断开
ACTION_SHUTDOWN 系统被关闭
Broadcast的类型
广播分为标准广播和有序广播
标准广播是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎在同一时间都会接收到这条广播,没有顺序可言,这种广播效率高,但无法截断。
有序广播则是一种同步执行的广播,在广播发出后,同一时刻只会有一个广播接收器能够接收到这条广播消息,当这个广播接收器中的逻辑执行完毕之后,广播才会继续传递。优先级高的广播接收器可以先接收到,并且可以截断广播,广播被截断后,后面的广播接收器就无法再接收到了。
运行原理
当其他程序发出广播消息之后,所有注册了广播接收器的应用程序都将会检测注册时的过滤器是否与发出的广播消息向匹配,匹配则会调用BroadcastReciver的onReceive()方法进行处理。所以开发BroadcastReciver应用,主要是对onReceive()方法的实现
广播的注册
创建完BroadcastReceiver之后,还不能够使它进入工作状态,我们需要为它注册一个指定的广播地址,否则无法接收广播
静态注册:写在AndroidManifest.xml文件中,注册的广播接收器必须继承BroadReceiver
动态注册:写在代码中使用Context.registerReceiver注册,由Intent来传递注册时用到的Action
广播的收发
刚才说过了,广播分为有序广播和标准广播,那么发送广播的形式也不同
标准广播发送:使用sendBroadcast()发送
有序广播发送:使用sendOrderBroadcast()发送
广播的收取:定义一个继承BroadcastReceiver的类,继承该类后覆盖其onReceiver()方法,并在该方法中响应事件。
有序广播的优先级
有序广播接收器通过intent-filter的priority参数来确定哪个接收器先接收到广播,数值越大,优先级越高,趋势范围在-1000~1000之间,也可以通过abortBroadcast()来阻断广播,阻断之后,之后的接收器则不会再接收到。
本地广播
之前我们看到的都是全局广播,也就是说我们发出的广播,其他应用也可以收到,这就存在安全问题,为了简单的解决安全性问题,Android引入了一套本地广播机制,使用这个机制发出的广播只能够在应用内部进行传递,并且广播接收器也只能接收来自应用程序本身发出的广播。
本地广播使用LocalBroadcastManager来对广播进行管理,并提供了发送广播和注册广播接收器的方法。
package cn.lixyz.broadcastreceiver; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import android.view.View; import android.widget.Button; public class MainActivity extends Activity { private IntentFilter intentFilter; private LocalBroadcastManager localBroadcastManager; private LocalReceiver localReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 获取LocalBroadcastReceiver实例 localBroadcastManager = LocalBroadcastManager.getInstance(this); Button button = (Button) findViewById(R.id.sendlocalBroadcast); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent("cn.lixyz.broadcastreceiver.localreceiver"); // 发送本地广播 localBroadcastManager.sendBroadcast(intent); } }); intentFilter = new IntentFilter(); intentFilter.addAction("cn.lixyz.broadcastreceiver.localreceiver"); localReceiver = new LocalReceiver(); localBroadcastManager.registerReceiver(localReceiver, intentFilter); } @Override protected void onDestroy() { super.onDestroy(); // unregisterReceiver(myBroadcastReciver); } class LocalReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.d("TTTT", "接收到了本地广播"); } } }