当前位置: 代码迷 >> 综合 >> Android四大组件之一:BroadcastReceiver(广播接收者)
  详细解决方案

Android四大组件之一:BroadcastReceiver(广播接收者)

热度:17   发布时间:2023-11-21 10:25:50.0

一,简介:

1,broadcast(广播)

既然有广播接收者,那就必须有广播这个东西,就像收音机,有了收音机,没有广播频道,你听个卵。broadcast(广播):是一种广泛运用于应用程序之间传输信息的机制。这个广播可以是自己程序中发出的,也可以是系统发出的,比如说,你的手机没有了网络,那么系统就会发出一个网络断开的广播,一些App就会接收到这个广播,然后做出相应操作,比如提醒用户,你断网了!

2,BroadcastReceive(广播接收者)

广播接收者是对发送出来的广播进行过滤接收并响应的一类组件,就是用来接收来自系统或者应用中的广播。

3,android为啥要这样设计?

如果没有广播这个东西,很多很多东西我们都有自己去做,比如上面说的网络监测,要自己去写程序来完成,这样就很麻烦,但是有了这个广播,而且基本上开发需要的,系统都会为我们做好,我们只要去等待系统发来的广播,然后进行过滤接收并响应,就可以了。大大的减少了开发的工作量和开发周期,作为开发者,不需要去关系一些底层的东西,只需要掌握BroadcastReceive即可,


二,BroadcastReceive(广播接收者)创建

创建一个类,让其继承BroadcastReceive,并实现onReceive ()方法,如下代码:

public class MyBroadcastRecevie extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {}
}

onReceive ()方法中有两个参数;参数1,是上下文,参数2是Intent对象,这个intent中保存了接收到的广播传来的数据;这样完成了BroadcastReceive(广播接收者)的创建。

三,注册BroadcastReceive;

上面创建了BroadcastReceive,但是并没有告诉这个接收者要接听哪个广播,所以必须对其进行注册,注册分两种,

1,静态注册,就是在AndroidMainifest.xml中注册

<receiver android:name=".broadcast.MyBroadcastRecevie"><intent-filter><action android:name="动作名"></action></intent-filter></receiver>

代码中有个action(动作),处在intent-filter(过滤器)中,对广播进行过滤,只要与这里的注册中的action匹配才能接收,举个栗子,系统一次性发送了很多的广播,但是这里只接收(当短信发来时的动作),那么这个接收者就对发来的广播进行过滤,找到与自己action匹配的广播,如果有,就响应。(一些系统动作名会在后面给出);

2,动态注册

//定义一个MyBroadcastRecevie对象        
MyBroadcastRecevie recevie=new MyBroadcastRecevie();
//定义一个过滤器,参数就是对应的action,是不是和静态注册一个意思,IntentFilter intentFilter=new IntentFilter("对应的action");
//注册registerReceiver(recevie,intentFilter)//解除注册
//unregisterReceive(receive);


静态与动态注册的区别:静态注册的广播的程序运行一次后,以后能一直保持广播接收的状态,只要有对应的广播就能接收它的广播信息。而动态注册的广播需要程序在运行中才能接收广播。

自此,广播接收者就定义完成了。


四,找波源

以下将用:应用内自定义发送和接收广播和接收系统广播并响应两个例子来说BroadcastReceive;

1,自定义广播:

  1.1看看效果:


1.2代码:

broadcast.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="match_parent"android:layout_height="match_parent">
<Buttonandroid:id="@+id/send1"android:layout_width="match_parent"android:layout_height="50dp"android:onClick="send"android:text="发送自定义广播"/>
</LinearLayout>


MyBroadcastReceive.java:

public class MyBroadcastRecevie extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Toast.makeText(context,"接收到广播:"+intent.getStringExtra("msg"),Toast.LENGTH_SHORT).show();}
}


testBroadcast.java:

public class testBroadcast extends Activity {@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.broadcast);}public  void send(View v){switch (v.getId()){case R.id.send1://定义一个intent,用于保存数据Intent intent1=new Intent();//在intent1里放一条消息intent1.putExtra("msg","这是一天自定义的广播");//设置action,必须对应相应的注册的Broadcastreceive的action,还德保证唯一,一般用包名+...intent1.setAction("send1");//然后发送广播sendBroadcast(intent1);break;}}
}

1.3:优先级的讨论

上面只是一个普通的广播发送,但是广播发送分两种,普通广播和有序广播。下面会谈论,在谈论之前先来说说优先级。

优先级的设置也有静态和动态两种:

静态方法:

   <intent-filter android:priority="100">

动态方法:

      MyBroadcastRecevie recevie=new MyBroadcastRecevie();IntentFilter intentFilter=new IntentFilter("对应的action");intentFilter.setPriority(100);//这里设置registerReceiver(recevie,intentFilter);


为了展现优先级的效果,还是来个小demo吧,我们在添加一个BroadcastReceive;

把第一个的优先级设置为100,第二个的优先级设置为200。同时让两个接收同一种广播。如下代码中的action都为send1;

 <receiver android:name=".broadcast.MyBroadcastReceive"><intent-filter android:priority="100"><action android:name="send1"></action></intent-filter></receiver><receiver android:name=".broadcast.MyBroadcastReceive1"><intent-filter android:priority="200"><action android:name="send1"></action></intent-filter></receiver>


看效果:


1.4:发送广播

对比:

普通广播:方法:sendBroadcast(intent);

同级别接收到的先后顺序是随机的(无序),

级别低的后收到广播,

接收器不能截断广播的继续传播,也不能处理广播,

同级别动态注册高于静态注册。


有序广播:方法:sendOrderedBroadcast(intent1,null);

同级别接收到的先后顺序是有序的;

能截断广播的继续传播,也能处理广播;

同级别动态注册高于静态注册,


从中我们用demo来对比一下普通广播和有序广播的截断广播的功能;

截断方法:abortBroadcast();

效果:

点击发送普通广播:


点击发送有序广播:


可以看到:普通发送并没有截断广播;而有序发送截断了广播的传递。

代码:

两个BroadcastReceive:

public class MyBroadcastReceive extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Toast.makeText(context,"第一个接收者:"+intent.getStringExtra("msg"),Toast.LENGTH_SHORT).show();abortBroadcast();}
}public class MyBroadcastReceive1 extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Toast.makeText(context,"第二个接收者:"+intent.getStringExtra("msg"),Toast.LENGTH_SHORT).show();abortBroadcast();}
}


在xml文件中添加:

 <Buttonandroid:id="@+id/send3"android:layout_width="match_parent"android:layout_height="50dp"android:onClick="send"android:text="发送普通广播"/><Buttonandroid:id="@+id/send4"android:layout_width="match_parent"android:layout_height="50dp"android:onClick="send"android:text="发送有序广播"/>

在主java中添加:

  case R.id.send3://定义一个intent,用于保存数据Intent intent3=new Intent();//在intent1里放一条消息intent3.putExtra("msg","接收到广播");//设置action,必须对应相应的注册的Broadcastreceive的action,还德保证唯一,一般用包名+...intent3.setAction("send1");//然后发送普通广播sendBroadcast(intent3);break;case R.id.send4://定义一个intent,用于保存数据Intent intent4=new Intent();//在intent1里放一条消息intent4.putExtra("msg","接收到广播");//设置action,必须对应相应的注册的Broadcastreceive的action,还德保证唯一,一般用包名+...intent4.setAction("send1");//然后发送有序广播sendOrderedBroadcast(intent4,null);break;


2,接收系统广播(这里以当手机接收到短信时,系统发出的广播为例,

2.1:效果:

先打开运用,然后去发短信,你会看到Toast一条信息。


2.2,:代码:

当系统收到短信时,会发出一个action名称为android.provier.Telephony.SMS_RECEIVED的广播Intent,该Intent存放了接收到的短信内容,使用名称 “pdus”即可从Intent中获取短信内容。

pdus是一个object类型的数组,每一个object都是一个byte[]字节数组,每一项为一条短信。


public class SMSBroadcastReceiver extends BroadcastReceiver {private static final String action = "android.provider.Telephony.SMS_RECEIVED";@Overridepublic void onReceive(Context context, Intent intent) {if (intent.getAction().equals(action)) {Object[] pduses = (Object[]) intent.getExtras().get("pdus");String mobile = "";String content = "";String time = "";System.out.println(pduses.length);for (Object pdus : pduses) {byte[] pdusmessage = (byte[]) pdus;SmsMessage sms = SmsMessage.createFromPdu(pdusmessage);mobile = sms.getOriginatingAddress();// 发送短信的手机号码content = sms.getMessageBody(); // 短信内容Date date = new Date(sms.getTimestampMillis());// 发送日                期SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");time = format.format(date); // 得到发送时间}String show = "发送者:" + mobile + " 内容:" + content + "      时间:" + time;Toast.makeText(context, show, Toast.LENGTH_LONG).show();}abortBroadcast();}}


注册:注意action哦。

 <receiver android:name=".broadcast.SMSBroadcastReceiver"><intent-filter android:priority="1001"><action android:name="android.provider.Telephony.SMS_RECEIVED" /></intent-filter></receiver>

添加权限:

<uses-permission android:name="android.permission.RECEIVE_SMS"/>
注意:如果实在真机运行,需要在手机的权限管理中心给此App,读取短信的权限。当然你也可以, 提示用户选择相应权限

五,系统广播定义的一些action值

1.Intent.ACTION_AIRPLANE_M; 关闭或打开飞行模式时的广播 
2.Intent.ACTION_BATTERY_CH; (1)充电状态,或者电池的电量发生变化; (2)电池的充电状态、电荷级别改变,不能通过组建声; 
3.Intent.ACTION_AIRPLANE_MODE_CHANGED; 关闭或打开飞行模式时的广播 
4.Intent.ACTION_BATTERY_CHANGED; (1)充电状态,或者电池的电量发生变化 (2)电池的充电状态、电荷级别改变,不能通过组建声明 接收这个广播,只有通过registerReceiver()注册 
5.Intent.ACTION_BATTERY_LOW; 表示电池电量低 
6 .Intent.ACTION_BATTERY_OKAY; 表示电池电量充足,即从电池电量低变化到饱满时会发出广播 
7.Intent.ACTION_BOOT_COMPLETED; 在系统启动完成后的广播,这个动作被广播一次(只有一次)。 
8.Intent.ACTION_CAMERA_BUTTON; 按下照相时的拍照按键(硬件按键)时发出的广播 
9.Intent.ACTION_CLOSE_SYSTEM_DIALOGS; 当屏幕超时进行锁屏时,当用户按下电源按钮,长按或短按(不管有没跳出话框),进行锁屏时,android系统都会广播此Action消息 
10.Intent.ACTION_CONFIGURATION_CHANGED; 设备当前设置被改变时发出的广播(包括的改变:界面语言,设备方向,等,请参考Configuration.java) 
11.Intent.ACTION_DATE_CHANGED; 设备日期发生改变时会发出此广播 
12.Intent.ACTION_DEVICE_STORAGE_LOW; 设备内存不足时发出的广播,此广播只能由系统使用,其它APP不可用 
13.Intent.ACTION_DEVICE_STORAGE_OK; 设备内存从不足到充足时发出的广播,此广播       只能由系统使用,其它APP不可用 
14.Intent.ACTION_DOCK_EVENT; 发出此广播的地方 
frameworks\base\services\java\com\android\server\DockObserver.java 
15.Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE; 移动APP完成之后,发出的广播(移动是指:APP2SD) 
16.Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE; 正在移动APP时,发出的广播(移动是指:APP2SD) 17. 
17.Intent.ACTION_GTALK_SERVICE_CONNECTED; Gtalk已建立连接时发出的广播 
18.Intent.ACTION_GTALK_SERVICE_DISCONNECTED; Gtalk已断开连接时发出的广播 
19.Intent.ACTION_HEADSET_PLUG; 在耳机口上插入耳机时发出的广播 
20.Intent.ACTION_INPUT_METHOD_CHANGED; 改变输入法时发出的广播 
21.Intent.ACTION_LOCALE_CHANGED; 设备当前区域设置已更改时发出的广播 
22.Intent.ACTION_MANAGE_PACKAGE_STORAGE; 表示用户和包管理所承认的低内存状态通知应该开始。 
23. Intent.ACTION_MEDIA_BAD_REMOVAL; 未正确移除SD卡(正确移除SD卡的方法:设置–SD卡和设备内存–卸载SD卡),但已把SD卡取出来时发出的广播 ,扩展介质(扩展卡)已经从 SD 卡插槽拔出,但是挂载点 (mountpoint) 还没解除 (unmount) 
24.Intent.ACTION_MEDIA_BUTTON; 按下”Media Button” 按键时发出的广播,假如有”Media Button” 按键的话(硬件按键) 
25. Intent.ACTION_MEDIA_CHECKING; 插入外部储存装置,比如SD卡时,系统会检验SD卡,此时发出的广播。 
26.Intent.ACTION_MEDIA_EJECT; 已拔掉外部大容量储存设备发出的广播(比如SD卡,或移动硬盘),不管有没有正确卸载都会发出此广播, 用户想要移除扩展介质(拔掉扩展卡)。 
27.Intent.ACTION_MEDIA_MOUNTED; 插入SD卡并且已正确安装(识别)时发出的广播, 扩展介质被插入,而且已经被挂载。 
28.Intent.ACTION_MEDIA_NOFS; 拓展介质存在,但使用不兼容FS(或为空)的路径安装点检查介质包含在Intent.mData领域。 
29. Intent.ACTION_MEDIA_REMOVED; 外部储存设备已被移除,不管有没正确卸载,都会发出此广播, 扩展介质被移除。 
30.Intent.ACTION_MEDIA_SCANNER_FINISHED; 广播:已经扫描完介质的一个目录 
31.Intent.ACTION_MEDIA_SCANNER_SCAN_FILE; 请求媒体扫描仪扫描文件并将其添加到媒体数据库。 
32.Intent.ACTION_MEDIA_SCANNER_STARTED; 广播:开始扫描介质的一个目录 
33. Intent.ACTION_MEDIA_SHARED; 广播:扩展介质的挂载被解除 (unmount),因为它已经作为 USB 大容量存储被共享。 
34.Intent.ACTION_MEDIA_UNMOUNTABLE; 
35.Intent.ACTION_MEDIA_UNMOUNTED 广播:扩展介质存在,但是还没有被挂载 (mount) 
36.Intent.ACTION_NEW_OUTGOING_CALL; 
37. Intent.ACTION_PACKAGE_ADDED; (1)成功的安装APK之后 (2)广播:设备上新安装了一个应用程序包。 (3)一个新应用包已经安装在设备上,数据包括包名(最新安装的包程序不能接收到这个广播) 
38.Intent.ACTION_PACKAGE_CHANGED; 一个已存在的应用程序包已经改变,包括包名 
39.Intent.ACTION_PACKAGE_DATA_CLEARED; (1)清除一个应用程序的数据时发出的广播(在设置--应用管理--选中某个应用,之后点清除数据时?) (2)用户已经清除一个包的数据,包括包名(清除包程序不能接收到这个广播) 
40.Intent.ACTION_PACKAGE_INSTALL; 触发一个下载并且完成安装时发出的广播,比如在电子市场里下载应用? 
41.Intent.ACTION_PACKAGE_REMOVED; 成功的删除某个APK之后发出的广播, 一个已存在的应用程序包已经从设备上移除,包括包名(正在被安装的包程序不能接收到这个广播) 
42.Intent.ACTION_PACKAGE_REPLACED; 替换一个现有的安装包时发出的广播(不管现在安装的APP比之前的新还是旧,都会发出此广播?) 
43.Intent.ACTION_PACKAGE_RESTARTED; 用户重新开始一个包,包的所有进程将被杀死,所有与其联系的运行时间状态应该被移除,包括包名(重新开始包程序不能接收到这个广播) 
44.Intent.ACTION_POWER_CONNECTED; 插上外部电源时发出的广播 
45.Intent.ACTION_POWER_DISCONNECTED; 已断开外部电源连接时发出的广播 
46.Intent.ACTION_PROVIDER_CHANGED; 
47.Intent.ACTION_REBOOT; 重启设备时的广播 
48.Intent.ACTION_SCREEN_OFF; 屏幕被关闭之后的广播 
49. Intent.ACTION_SCREEN_ON; 屏幕被打开之后的广播 
50.Intent.ACTION_SHUTDOWN; 关闭系统时发出的广播 
51. Intent.ACTION_TIMEZONE_CHANGED; 时区发生改变时发出的广播 
52.Intent.ACTION_TIME_CHANGED; 时间被设置时发出的广播 
53.Intent.ACTION_TIME_TICK; 广播:当前时间已经变化(正常的时间流逝), 当前时间改变,每分钟都发送,不能通过组件声明来接收 ,只有通过Context.registerReceiver()方法来注册 
54. Intent.ACTION_UID_REMOVED; 一个用户ID已经从系统中移除发出的广播 
55. Intent.ACTION_UMS_CONNECTED; 
设备已进入USB大容量储存状态时发出的广播? 
56.Intent.ACTION_UMS_DISCONNECTED; 设备已从USB大容量储存状态转为正常状态时发出的广播? 
57.Intent.ACTION_USER_PRESENT; 
58.Intent.ACTION_WALLPAPER_CHANGED; 设备墙纸已改变时发出的广播


六,总结

BroadcastReceive广播接收器在Android开发中用着很重要的地位,四个组件之一。好好练习!

  相关解决方案