广播接收者--Broadcast

什么是Broadcast

BroadcastReceiver是安卓中的四大组件之一。

广播接收器,也被称为全局事件,或系统事件。

Android系统中任何程序有动作时,如果想通知其他程序,采用广播的方式进行传播是非常有效的。广播从理论上说,可以将一个动作传播给任意多个程序(当然,广播接收器的数量会受到系统限制)。

 

Android中,有一些操作完成以后,会发送广播,比如说发出一条短信,或打出一个电话,如果某个程序接收了这个广播,就会做相应的处理。这个广播跟我们传统意义中的电台广播有些相似之处。之所以叫做广播,就是因为它只负责“说”而不管你“听不听”,也就是不管你接收方如何处理。另外,广播可以被不只一个应用程序所接收,当然也可能不被任何应用程序所接收。

广播机制最大的特点就是发送方并不关心接收方是否接到数据,也不关心接收方是如何处理数据的。

Android中广播的是操作系统中产生的各种各样的事件。例如,收到一条短信就会产生一个收到短信息的事件。而Android操作系统一旦内部产生了这些事件,就会向所有的广播接收器对象来广播这些事件。

广播机制的三要素

Android广播机制包含三个基本要素:

1、广播(Broadcast) - 用于发送广播;

2、广播接收器(BroadcastReceiver) - 用于接收广播;

3、意图内容(Intent)-用于保存广播相关信息的媒介。

Broadcast是一种广泛运用的在应用程序之间传输信息的机制。而BroadcastReceiver是对发送出来的Broadcast进行过滤接受并响应的一类组件。

广播的生命周期

1、广播接收器仅在它执行这个方法时处于活跃状态。当onReceive()返回后,它即为失活状态。

2、拥有一个活跃状态的广播接收器的进程被保护起来而不会被杀死,但仅拥有失活状态组件的进程则会在其它进程需要它所占有的内存的时候随时被杀掉。

3、如果响应一个广播信息需要很长的一段时间,一般会将其纳入一个衍生的线程中去完成,而不是在主线程内完成它,从而保证用户交互过程的流畅。广播接收程序的时间限制为10秒。

广播的分类

Android中广播主要分为2:标准广播和有序广播

  1. 标准广播:标准广播(Normal broadcasts)是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎都会在同一时刻接收到这条广播消息,因此它们之间没有任何先后顺序可言。这种广播的效率会比较高,但同时也意味着它是无法被截断的。

  1. 有序广播(Ordered broadcasts)则是一种同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递。所以此时的广播接收器是有先后顺序的,优先级高的广播接收器就可以先收到广播消息,并且前面的广播接收器还可以截断正在传递的广播,这样后面的广播接收器就无法收到广播消息了,甚至前面的广播可以修改广播内容再传递给下一个广播。

 

 

发送标准广播

//创建意图对象,并指明action,那么意图过滤器与这个action匹配的广播接受者会

//接收到这个广播

Intent intent = new Intent("com.qianfeng.MY_BROADCAST");  

//发送出去广播

sendBroadcast(intent);

注:发送广播的方法都是上下文对象中的方法。

发送有序广播

Intent intent = new Intent("com.qianfeng.MY_BROADCAST");  

 

//发送有序广播。  参数一:意图对象  参数二:权限。是否需要接受者需要选取才可//以收到广播

sendOrderedBroadcast(intent, null);

发送指定接收者的广播(必须是有序广播)

//由于发送有序广播的时候,中间会有可能被拦截掉,参数三则指定了一个这个广播

//的最终接受者,也就说即使中间有人拦截了广播,则参数三指定的接

//受者也会最终接收到这个广播。

//其余的参数给null0即可

sendOrderedBroadcast(it, null, receiver, null, 0, null, null);

/* 

                      *参数一:意图对象,发送什么样的广播

 * 参数二:权限  一般不需要

 * 参数三:是最后一个收到广播的接受者,他可以不用注册,也能收到

 * 参数四:指明最终的接受者执行的线程(如果Handler对象时在子线程创建则handMessage方法是在子线程执行)。传null,怎默认是在主线程执行

 * 参数五:初始化的code

 * 参数六:初始化的数据

 * 参数七:传递比较复杂的数据可以使用Bundle对象

 * 

 * 最终的接收者收到的数据是有可能被中间的接收者篡改

 */

 

 

注意:

1、发送有序广播的时候,先接到广播的可以通过下面的方法来取消广播,导致后面的优先级低的广播接收者收不到广播。

abortBroadcast();  //放弃当前的广播,则优先级低的无法收到当前广播

2、如果优先级高的广播接收者想给优先级低的广播接收者传递数据可以通过下面的方法:

setResult()

setResultData()

setResultCode()

setResultExtra()

对方用getResultData()获得数据


1、静态创建广播接收者

    发送端:
        Intent i = new Intent();
        i.setAction(" mybroadcast ");
        i.putExtra(" msg " , " 这是附带的消息 " );
        sendBroadcast( i ); //使用这个发送的是标准广播(无序),使用sendOrderBroadcast(i);发送的是无序广播
    接收端:
        需要创建一个类,并且继承 BroadcastRecevier 重写构造方法 和 onReceive方法
        在onReceive方法中,接收广播发送的消息
        String content = Intent.getStringExtra( "msg" );
        当是静态广播接收的时候,需要 在清单文件中设置需要接收的指定广播的名称,(一旦在清单文件设置,就属于系统级别的,无论接收者所属的程序是否退出,都能够继续接收消息)
        <intent-filter>
            <action android:name=" 广播发送时setAction中的名称 "/>
        </intent-filter> 

        完整的清单文件中的内容:
       
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="msg.app"/>
</intent-filter>
</receiver>

2、动态广播接收者
        动态是指在程序代码中创建接收者对象,以及设定接收指定广播的名称,再在代码中注册广播接收者
        MyReceiver receiver = new MyReceiver(); //这是和上面接收端一样的类--接收和发送都是一样的,只是不是在清单文件中设置
        IntentFilter filter = new IntentFileter();
        filter.addAction(" 广播发送时setAction中的名称 ");
        registerRecevier( receiver , filter ); //注册接收者

        2.1、动态注册广播接收者的时候,还需要在程序销毁的时候进行解除注册的操作,否则 可能 会出现内存泄漏
                在重写的onDestroy方法中进行解除
                 @Override 
                    protected void onDestrou(){
                            supter.onDestroy();
                            unregisterReceiver( 创建的接收者对象 );
                    }
 

使用LocalBroadcastManager

LocalBroadcastManagerAndroid Support包提供了一个工具,是用来在同一个应用内的不同组件间发送Broadcast的。

使用LocalBroadcastManager有如下好处:

发送的广播只会在自己App内传播,不会泄露给其他App,确保隐私数据不会泄露

其他App也无法向你的App发送该广播,不用担心其他App会来搞破坏

比系统全局广播更加高效

和系统广播使用方式类似:

先通过LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); 获取实例

然后通过函数 registerReceiver来注册监听器

        lbm.registerReceiver(new BroadcastReceiver() {

                @Override

                public void onReceive(Context context, Intent intent) {

                // TODO Handle the received local broadcast

                }

            }, new IntentFilter(LOCAL_ACTION));

 

通过 sendBroadcast 函数来发送广播
lbm.sendBroadcast(new Intent(LOCAL_ACTION));

短信拦截
@Override
    public void onReceive(Context context, Intent intent) {
        Bundle extras = intent.getExtras();//获得存储相关对象的bundle
        if(extras == null)
            return;
        //获得一个存储新的数据的Object数组
        Object[] pdus = (Object[]) extras.get("pdus");
        for (int i = 0; i < pdus.length; i++) {
            //数组中的每个元素
            SmsMessage message = SmsMessage.createFromPdu((byte[])pdus[i]);
            //获得发信息的号码
            String phoneNumber = message.getOriginatingAddress();
            //获得信息内容
            String content = message.getMessageBody().toString();
            Toast.makeText(context,"Tel:"+phoneNumber+"\n"+content,Toast.LENGTH_LONG).show();
            if(phoneNumber.endsWith("6336")){
                SmsManager manager = SmsManager.getDefault();
                manager.sendTextMessage(phoneNumber,null,"yeah",null,null);
            }
        }
    }

action
<intent-filter android:priority="1000">
                <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
 </intent-filter>
权限
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
    <uses-permission android:name="android.permission.SEND_SMS"/>

电话拦截

String number = getResultData();

String number = getResultData();


action

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

  <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>  

 <action android:name="android.intent.action.BOOT_COMPLETED"/>  

</intent-filter>

权限

<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>


开机启动
@Override
    public void onReceive(Context context, Intent intent) {
        Intent intent1 = new Intent();
        intent1.setComponent(new ComponentName("peng.jiansong.com.boot","peng.jiansong.com.boot.MainActivity"));
        intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        Toast.makeText(context,"开机启动",Toast.LENGTH_LONG).show();
        context.startActivity(intent1);
    }
action
<intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

检测网络状态
 @Override
    public void onReceive(Context context, Intent intent) {
        boolean mobile = false;
        boolean wifi = false;
        //获得网络服务
        ConnectivityManager manager = (ConnectivityManager)
                context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo.State state = manager.getNetworkInfo
                (ConnectivityManager.TYPE_MOBILE).getState();
        if(NetworkInfo.State.CONNECTED == state){
            mobile = true;
        }

        if(!mobile){
            Toast.makeText(context,"移动网络连接失败:"+state,Toast.LENGTH_LONG).show();
        }else{
            Toast.makeText(context,"移动网络连接成功:"+state,Toast.LENGTH_LONG).show();
        }

        NetworkInfo.State state1 = manager.getNetworkInfo
                (ConnectivityManager.TYPE_WIFI).getState();
        if(NetworkInfo.State.CONNECTED == state1){
            wifi = true;
        }

        if(!wifi){
            Toast.makeText(context,"WIFI连接失败:"+state1,Toast.LENGTH_LONG).show();
        }else{
            Toast.makeText(context,"WIFI连接成功:"+state1,Toast.LENGTH_LONG).show();

        }
    }
action
<intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
  </intent-filter>
权限
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
获得电量信息

public class MainActivity extends Activity {

 

private ProgressBar bar;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

bar = (ProgressBar) findViewById(R.id.bar);

IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);

MyReceiver receiver = new MyReceiver();

this.registerReceiver(receiver, filter);

}

 

class MyReceiver extends BroadcastReceiver{

@Override

public void onReceive(Context context, Intent intent) {

int current = intent.getExtras().getInt("level");

int count = intent.getExtras().getInt("scale");

bar.setMax(count);

bar.setProgress(current);

}

}

}


系统的Broadcast Action

系统在合适的时间发送广播,我们的app通过接收这些广播可以实现一些比较实用的功能。如:系统启动完成、用户外拨电话、短信来到等等,系统都会发出相应的广播。

ACTION_TIME_CHANGED :系统时间被改变;

ACTION_DATE_CHANGED : 系统日期被改变;

ACTION_TIMEZONE_CHANGED :系统时区被改变;

ACTION_BOOT_COMPLETED :系统启动完成;

ACTION_BATTERY_CHANGED : 电池电量改变;

ACTION_SHUTDOWN : 系统被关闭;

Action_BATTRY_LOW : 电池电量低;


android.intent.action.BATTERY_CHANGED  

    充电状态,或者电池的电量发生变化  

      

    android.intent.action.BOOT_COMPLETED  

    在系统启动后,这个动作被广播一次(只有一次)   

      

    android.intent.action.CFF  

    语音电话的呼叫转移状态已经改变  

      

    android.intent.action.CONFIGURATION_CHANGED   

    设备的配置信息已经改变,参见 Resources.Configuration  

      

    android.intent.action.DATA_ACTIVITY  

    电话的数据活动(data activity)状态(即收发数据的状态)已经改变   

      

    android.intent.action.DATA_STATE  

    电话的数据连接状态已经改变  

      

    android.intent.action.DATE_CHANGED  

    日期被改变  

   android.server.checkin.FOTA_CANCEL  

    取消所有被挂起的 (pending) 更新下载   

      

    android.server.checkin.FOTA_INSTALL  

    更新已经被确认,马上就要开始安装  

      

    android.server.checkin.FOTA_READY  

    更新已经被下载,可以开始安装  

      

    android.server.checkin.FOTA_RESTART  

    恢复已经停止的更新下载  

      

    android.server.checkin.FOTA_UPDATE  

    通过 OTA 下载并安装操作系统更新  

      

    android.intent.action.MEDIABUTTON   

    用户按下了"Media Button"  

      

    android.intent.action.MEDIA_BAD_REMOVAL   

    扩展介质(扩展卡)已经从 SD 卡插槽拔出,但是挂载点 (mount point) 还没解除 (unmount)  

      

    android.intent.action.MEDIA_EJECT  

    用户想要移除扩展介质(拔掉扩展卡)  

      

    android.intent.action.MEDIA_MOUNTED  

    扩展介质被插入,而且已经被挂载  

      

    android.intent.action.MEDIA_REMOVED  

    扩展介质被移除   

      

    android.intent.action.MEDIA_SCANNER_FINISHED  

    已经扫描完介质的一个目录  

      

    android.intent.action.MEDIA_SCANNER_STARTED  

    开始扫描介质的一个目录  

      

    android.intent.action.MEDIA_SHARED  

    扩展介质的挂载被解除 (unmount),因为它已经作为 USB 大容量存储被共享  

      

    android.intent.action.MEDIA_UNMOUNTED   

    扩展介质存在,但是还没有被挂载 (mount)   

      

    android.intent.action.MWI  

    电话的消息等待(语音邮件)状态已经改变   


   android.intent.action.NETWORK_TICKLE_RECEIVED  

    设备收到了新的网络 "tickle" 通知  

      

    android.intent.action.PACKAGE_ADDED  

    设备上新安装了一个应用程序包   

      

    android.intent.action.PACKAGE_REMOVED  

    设备上删除了一个应用程序包  

      

    android.intent.action.PHONE_STATE  

    电话状态已经改变  

      

    android.intent.action.PROVIDER_CHANGED  

    更新将要(真正)被安装   

      

    android.intent.action.PROVISIONING_CHECK   

    要求 polling of provisioning service 下载最新的设置   

      

    android.intent.action.SCREEN_OFF  

    屏幕被关闭  

      

    android.intent.action.SCREEN_ON  

    屏幕已经被打开  

      

    android.intent.action.SERVICE_STATE  

    电话服务的状态已经改变  

      

    android.intent.action.SIG_STR  

    电话的信号强度已经改变  

      

    android.intent.action.STATISTICS_REPORT  

    要求 receivers 报告自己的统计信息   

      

    android.intent.action.STATISTICS_STATE_CHANGED  

    统计信息服务的状态已经改变   

      

    android.intent.action.TIMEZONE_CHANGED   

    时区已经改变  

      

    android.intent.action.TIME_SET   

    时间已经改变(重新设置)  

      

    android.intent.action.TIME_TICK   

    当前时间已经变化(正常的时间流逝)  

      

    android.intent.action.UMS_CONNECTED 

     设备进入 USB 大容量存储模式。  

      

    android.intent.action.UMS_DISCONNECTED  

    设备从 USB 大容量存储模式退出  

      

    android.intent.action.WALLPAPER_CHANGED   

    系统的墙纸已经改变  

      

    android.intent.action.XMPP_CONNECTED  

    XMPP 连接已经被建立  

      

    android.intent.action.XMPP_DI    

    XMPP 连接已经被断开 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值