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

一,简介:

1,broadcast(广播)

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

2,BroadcastReceive(广播接收者)

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

3,android为啥要这样设计?

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


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

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

public class MyBroadcastRecevie extends BroadcastReceiver {
    @Override
    public 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">
<Button
    android: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 {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context,"接收到广播:"+intent.getStringExtra("msg"),Toast.LENGTH_SHORT).show();
    }
}


testBroadcast.java:

public class testBroadcast extends Activity {
    @Override
    protected 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 {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context,"第一个接收者:"+intent.getStringExtra("msg"),Toast.LENGTH_SHORT).show();
        abortBroadcast();
    }
}

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


在xml文件中添加:

 <Button
        android:id="@+id/send3"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:onClick="send"
        android:text="发送普通广播"/>
    <Button
        android: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";

    @Override
    public 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开发中用着很重要的地位,四个组件之一。好好练习!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值