广播接收者和自定义广播
广播接收者
监听广播的步骤
定义一个类,这个类继承BroadCastReceiver,实现它的onReceive()方法
SdcardReceive extends BroadcastReceiver
去清单文件中注册这个类,添加意图过滤器
//广播也和activity一样需要注册 <receiver android:name="com.liuwen.receiver.SdcardReceive" > <intent-filter> //action:这个是你要监听的广播,这个广播可以是系统发出来的,也可以是别的 //应用程序发的,也可以是你自己在本程序中自定义的 //data 发送广播的那个程序有没有定义,如果定义了我们就要添加相对应的data,不然这个 //广播就会监听失败 <!-- sd卡被卸载的广播,这个广播要加data不然监听不到 --> <action android:name="android.intent.action.MEDIA_UNMOUNTED" > </action> <data android:scheme="file"></data> </intent-filter> </receiver>
在onReceive()方法中写你的逻辑代码
//当成功接收到了广播就会触发这个方法 public void onReceive(Context context, Intent intent) { //里面写你接收到广播之后要运行的逻辑代码 //getAction()获取动作 //在4.0以上的版本监听这个开机广播要添加权限,不然监听不成功 //Intent.ACTION_BOOT_COMPLETED //当我们监听了多个广播的时候我们可以用这种判断来区别详细的广播,然后写对应的 //逻辑代码 if(intent.getAction().equals(Intent.ACTION_MEDIA_UNMOUNTED)){ Toast.makeText(context, "外置存储开被卸载了,部分应用不可用", 0).show(); } }
多个广播接收者示例
开机启动
高版本要记得加权限 <action android:name="android.intent.action.BOOT_COMPLETED"/>
向外呼叫电话
权限: <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
监听软件的安装和卸载
<!-- 3.监听指定的action动作,并且要记得带上scheme --> <intent-filter> <action android:name="android.intent.action.PACKAGE_ADDED" /> <action android:name="android.intent.action.PACKAGE_REMOVED" /> <data android:scheme="package"/> </intent-filter>
监听短信到来的广播
<receiver android:name="com.itheima.smslistener.SmsReceiver"> <intent-filter > <action android:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver> 权限: <uses-permission android:name="android.permission.RECEIVE_SMS"/>
广播接收者在不同版本下的特点
- 低版本 –2.3
就算强制停止了应用,当广播事件到来,那么应用进程也会随之启动,让广播接受者去处理这条广播,说白了也就是就算不启动应用,也能收到广播。
- 高版本–4.1.2
如果强制停止了应用,广播到来时,应用也不会启动,不会收到广播。
发送自定义的无序广播及接收这个自定义的广播的步骤
发送自定义广播
定义意图对象
Intent intent = new Intent();
指定发送的动作及数据
//指定动作事件,实际上就是要发送的广播的频道 intent.setAction("com.liuwen.uunorderbroadcast.action.HAHA"); //指定广播带上数据 //这个数据可以用Intent对象直接的传递,也可以通过Bundle对象打包传送 intent.putExtra("key", "你们能接受到这个广播的数据么?");
发送广播
//发送一条无序广播 sendBroadcast(intent);
接收自定义广播
- 定义一个类继承BroadcastReceiver
去清单文件注册这个类,并添加要接收的广播频道
//注册 <receiver android:name="com.liuwen.unorderbroadcast.CustomReceiver"> <intent-filter > //添加我们自定义的广播到动作中 <action android:name="com.liuwen.uunorderbroadcast.action.HAHA"/> </intent-filter> </receiver>
在onReceive()方法中写你的逻辑代码
@Override public void onReceive(Context context, Intent intent) { //接受自定义的广播,并把自定义广播传递过来的数据获取出来 // if(intent.getAction().equals("com.liuwen.uunorderbroadcast.action.HAHA")){ //这边的取数据的方式跟据自定义广播发送端的发送方式而改变 String value = intent.getStringExtra("key"); System.out.println(value); } }
发送自定义的有序广播和接收这个有序广播
定义这个有序广播的步骤:
定义意图对象
Intent intent = new Intent();
指定发送的动作及数据
//设置广播 intent.setAction("com.liuwen.orderbroadcast.action.PATATO");
发送广播
//发送一个有序广播 sendOrderedBroadcast( intent, //意图对象,用于指定action动作 null, //receiverPermission接受这个广播所需要的权限 new MyResiver(), //resultReceiver,//最终的结果接受者,返回的数据是最终传给接收广播的接收者所接收到的数据; null, //handle对象,用来处理广播的分发 0, //initialCode,//初始代码 "主席宣布,每个村民发10斤土豆", //initialData,//初始数据 null); //initialExtras额外的数据,如果觉得初始只传递一个字符串的数据太少了,可以通过这个handle对象来传递更多的数据
}
接收这个自定义的有序广播
- 定义一个类继承BroadcastReceiver
去清单文件注册这个类,并添加要接收的广播频道
//这个注册和上面唯一的差别就是要在 <intent-filter android:priority="1000" > //这里指定一个android:priority=""属性,这个属性是指定这个广播接收者接收这个 //有序广播的优先级,优先级的范围是(-1000~1000)数越大,优先级越高 <receiver android:name="com.liuwen.jieshouorder.ShengZhangReceiver" > <intent-filter android:priority="1000" > <action android:name="com.liuwen.orderbroadcast.action.PATATO" > </action> </intent-filter> </receiver> <receiver android:name="com.liuwen.jieshouorder.ShiZhangReceiver" > <intent-filter android:priority="700" > <action android:name="com.liuwen.orderbroadcast.action.PATATO" > </action> </intent-filter> </receiver> <receiver android:name="com.liuwen.jieshouorder.XianZhangReceiver" > <intent-filter android:priority="400" > <action android:name="com.liuwen.orderbroadcast.action.PATATO" > </action> </intent-filter>
在onReceive()方法中写你的逻辑代码
//逻辑代码,和无序广播的区别是,有序广播高优先级收到广播后可以选择处理广播传递过来的 //数据,可以改变这个数据,也可以直接终止这个数据,不让这个数据传递给别的广播,而无序广 //广播是不能处理广播传递过来的数据的,接收数据也没有先后之分,只要注册了就可以接收 @Override public void onReceive(Context context, Intent intent) { if(intent.getAction().equals("com.liuwen.orderbroadcast.action.PATATO")){ System.out.println("省长收到的信息是:"+getResultData()); //改变广播信息,发给下一个最高优先级的广播 //setResultData("主席宣布,每个村民发8斤土豆"); //终止广播的传输 abortBroadcast(); } }
有序广播和无序广播的总结
- 有序广播
广播接受者收广播是有先后顺序的,权限级别高的广播接受者先收到广播,级别低的广播接受者后收到广播,并且级别高的广播接受者可以修改广播里面的内容,甚至是终止广播的传输。 效率低
注意: 在发送有序广播的时候,是可以给广播接收者指定优先级别高低的。就算其中一个广播接收者终止了广播,但是发布广播时的最终结果接收者一定会受到这条广播。
例子:类似中央文件的层层下发
- 无序广播
广播接受者收到广播是同时得到,没有谁先谁后,也谈不上修改数据甚至是终止广播的传输。 效率高
例子:类似晚上7点钟的新闻联播,各地卫视都是同时播放节目。
只能在代码里面注册的广播接收者
系统里面有一类广播事件出现的频率极高,Android是不允许广播接受者在清单文件中注册的,只允许在代码里面注册,一旦这个依附的界面被销毁,那么广播接受者也就失去了效力,广播到来,也就不会在处理了。
这一类广播事件有: 屏幕的点亮和锁定、电池电量的变更.
- 内存泄露
- 注意:
- 当你在代码中注册的广播接收者,最后没有解除注册广播接受者的话,那么会报内存泄露异常
在代码中注册广播接收者的步骤
创建一个类,这个类继承BoardCastReceiver
public class ScreenStatusReceiver extends BroadcastReceiver { Override public void onReceive(Context context, Intent intent) { if(intent.getAction().equals(Intent.ACTION_SCREEN_ON)){ System.out.println("屏幕点亮了"); }else if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF)){ System.out.println("屏幕锁定了"); } } }
在Activity的onCreate()方法中,注册广播接收者
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //注册广播接受者 //创建广播接受者的对象 receiver = new ScreenStatusReceiver(); //指定该广播接受者收听什么样的动作广播 IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); //注册 registerReceiver(receiver, filter); }
3.程序这个activity退出的时候要在onDestroy()方法中解除注册
@Override protected void onDestroy() { super.onDestroy(); //一定要在程序退出的时候把这个广播给解除绑定,不然会出现内存泄露 unregisterReceiver(receiver); }
在清单文件中注册的广播接收者和在代码中注册的广播接收者的区别
在清单文件中注册的广播接收者,可以不启动这个程序,只要广播来了就能接收到,而在代码中注册的
广播接收者,一旦这个依附的界面被销毁,那么广播接受者也就失去了效力,广播到来,也就不会在处理了。