andorid Broadcast Receiver

来源:互联网 发布:合众思壮软件 编辑:程序博客网 时间:2024/06/16 01:57

转:http://blog.csdn.net/anddlecn/article/details/51741455

自定义Broadcast Receiver

无论是应用还是系统组件,它们定义Broadcast Receiver的方式都是一样。

定义Broadcast Receiver有两种方式,

  1. 静态定义:将Broadcast Receiver声明到AndroidManifest.xml配置文件当中,它的特点是应用不必运行起来,系统能通过配置文件的描述判断当前系统中的广播是否是这台接收机关注的;

  2. 动态定义:在代码中动态生成Broadcast Receiver,它的特点是应用要运行起来,在运行的过程当中判断当前系统中的广播是否是这台接收机关注的;

静态Broadcast Receiver

首先来看看如何定义一个静态的Broadcast Receiver

  1. 继承BroadcastReceiver类,实现它的onReceive接口,

    public class MyReceiver extends BroadcastReceiver {    public MyReceiver() {    }    //实现onReceive接口,当收到指定的广播后被触发    @Override    public void onReceive(Context context, Intent intent) {        //添加对应的逻辑处理    }}

      2.在AndroidManifest.xml配置文件当中,声明创建的Broadcast Receiver

<receiver    android:name=".MyReceiver"    android:enabled="true"    android:exported="true">    <intent-filter>        <action android:name="custom.action.mybroadcast"/> ---指定关注的广播        <category android:name="android.intent.category.DEFAULT" />    </intent-filter></receiver>

这里intent-filter标签中的action android:name属性设置的值custom.action.mybroadcast,就是这台接收机关注的广播。

当名称为custom.action.mybroadcast的广播在系统中传播的时候,MyReceiver就会被运行起来,并触发它的onReceive()函数。开发者就需要在这里添加对应逻辑处理。

动态Broadcast Receiver

当应用运行起来以后,即使AndroidManifest.xml文件中没有声明过Broadcast Receiver也没有关系,它可以被动态的创建,

  1. 和创建静态Broadcast Receiver类似,首先要继承BroadcastReceiver类,实现它的onReceive接口,

public class MyReceiver extends BroadcastReceiver {    public MyReceiver() {    }    //实现onReceive接口,当收到指定的广播后被触发    @Override    public void onReceive(Context context, Intent intent) {        //添加对应的逻辑处理    }}

      

     2.注册Broadcast Receiver,并告诉系统这个Broadcast Receiver关注哪些广播,可以添加多种关心的广播,

//设置过滤器,确定关心的广播IntentFilter filter = new IntentFilter();filter.addAction("custom.action.mybroadcast");//可以添加多种关心的广播filter.addAction(......);//创建ReceiverMyReceiver receiver = new MyReceiver();//注册到系统当中,完成Receiver的设置registerReceiver(receiver, filter);


3.使用完毕后,一定要注销Broadcast Receiver,否则系统会给出警告提示。

unregisterReceiver(receiver);
动态的Broadcast Receiver在注册使用完成之后一定要注销,不然会占用系统资源、浪费资源。

发送Broadcast

发送出去的广播可以分成两类,一类是无序广播,一类是有序广播。

无序广播

这是一种不需要考虑接收者接收顺序的广播,比如说有3个接收机,都关注custom.action.mybroadcast这种广播,无所谓谁先收到谁后收到。接收机不能阻止其它接收机获取到这条广播。

1 发送

发送无序广播,只要使用ContextsendBroadcast()方法就可以了,

Intent intent = new Intent();    //广播中的action也是自定义的    intent.setAction("custom.action.mybroadcast");        sendBroadcast(intent);

2 接收
<receiver   android:name=".MyReceiver"   android:enabled="true"   android:exported="true">   <intent-filter>       <action android:name="custom.action.mybroadcast"/>       <category android:name="android.intent.category.DEFAULT" />   </intent-filter></receiver>

AndroidManifest.xml中声明静态Broadcast Receiver的时候,


就像前面介绍的那样,不用做什么特别的处理。

有序广播

这是一种需要考虑接收者接收顺序的广播,比如说有3个接收机,都关注custom.action.mybroadcast这种广播,那么安卓系统将根据这3个接收机声明的优先级进行广播的投递。

而且有序广播是可以被阻截的。

比如,一个广播按照顺序传递给3个接收机-A B C,但是B将广播拦截了,因此C将不会收到这个广播。

1.发送

Intent i = new Intent("custom.action.mybroadcast");sendOrderedBroadcast(i, null);

2.接收

接收的时候,需要给intent-filter标签设置android:priority属性,表示这个接收机的优先级。优先级从-1000到1000,数值越大,优先级越高。

<receiver   android:name=".MyReceiver"   android:enabled="true"   android:exported="true">   <intent-filter android:priority="1000">       <action android:name="custom.action.mybroadcast"/>       <category android:name="android.intent.category.DEFAULT" />   </intent-filter></receiver>

接收到广播以后,Broadcast Receiver可以将广播拦截,禁止它往下传播,

public class MyReceiver extends BroadcastReceiver {   public MyReceiver() {   }   //实现onReceive接口   @Override   public void onReceive(Context context, Intent intent) {       //禁止往下传播       abortBroadcast();   }}

如果接收机1onReceive()中,希望把数据传递给下个接收机2

接收机1可以使用setResultExtras()方法,

public class MyReceiver1 extends BroadcastReceiver {    public MyReceiver() {    }    @Override    public void onReceive(Context context, Intent intent) {        Bundle b = new Bundle();        b.putString("data", "this data from MyReceiver");        setResultExtras(b);    }}


接收机2中,

public class MyReceiver2 extends BroadcastReceiver {    public MyReceiver2() {    }    @Override    public void onReceive(Context context, Intent intent) {        Bundle b = getResultExtras(true);        if(b!=null)        {            //data就是前一个接收机1传来的-this data from MyReceiver            String data = b.getString("data");        }    }}


假如希望将数据放到onReceive()传入的Intent当中,是不会传递成功的,

@Overridepublic void onReceive(Context context, Intent intent) {    //这是不会成功的    intent.putExtra("data", "this data from MyReceiver");}

传递数据,一定要通过BroadcastReceiver提供的setResultExtras()方法。

有序广播例子

 public void onClick1(View view) {        Intent intent = new Intent();        intent.setAction("com.example.zdy");        //发送有序广播        //resultReceiver:不需要在清单文件中配置,这个广播接收者只接受该条有序广播,并且是最后一个收到该广播,并且一定可以收到该广播        sendOrderedBroadcast(intent, null, new MyReceiver(), null, 0, "每人发100元", null);    }    //    class MyReceiver extends BroadcastReceiver {        @Override        public void onReceive(Context context, Intent intent) {            String text = getResultData();            System.out.println("广播接收者处理后的结果:" + text);        }    }

广播接收者

public class ShengZF extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        String text = getResultData();        System.out.println("ShengZF收到广播:" + text);        setResultData("每人发80元");    }}

public class ShiZF extends BroadcastReceiver{    @Override    public void onReceive(Context context, Intent intent) {        String text = getResultData();        System.out.println("ShiZF收到"+text);        abortBroadcast();//拦截广播    }}

public class XianZF extends BroadcastReceiver{    @Override    public void onReceive(Context context, Intent intent) {        String text = getResultData();        System.out.println("XianZF:"+text);    }}


<receiver android:name="com.example.location.ShengZF">            <intent-filter android:priority="1000">                <action android:name="com.example.zdy"></action>            </intent-filter>        </receiver>        <receiver android:name="com.example.location.ShiZF">            <intent-filter android:priority="100">                <action android:name="com.example.zdy"></action>            </intent-filter>        </receiver>        <receiver android:name="com.example.location.XianZF">            <intent-filter android:priority="0">                <action android:name="com.example.zdy"></action>            </intent-filter>        </receiver>

-----------------------------------=============================

#IP拨号器
> 原理:接收拨打电话的广播,修改广播内携带的电话 号码
* 定义广播接收者接收打电话广播

    public class CallReceiver extends BroadcastReceiver {

        //当广播接收者接收到广播时,此方法会调用
        @Override
        public void onReceive(Context context, Intent intent) {
            //拿到用户拨打的号码
            String number = getResultData();
            //修改广播内的号码
            setResultData("17951" + number);
        }
    }
* 在清单文件中定义该广播接收者接收的广播类型

        <receiver android:name="com.itheima.ipdialer.CallReceiver">
            <intent-filter >
                <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
            </intent-filter>
        </receiver>
* 接收打电话广播需要权限

        <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
* 即使广播接收者的进程没有启动,当系统发送的广播可以被该接收者接收时,系统会自动启动该接收者所在的进程


#短信拦截器
>系统收到短信时会产生一条广播,广播中包含了短信的号码和内容

* 定义广播接收者接收短信广播

        public void onReceive(Context context, Intent intent) {
        //拿到广播里携带的短信内容
        Bundle bundle = intent.getExtras();
        Object[] objects = (Object[]) bundle.get("pdus");
        for(Object ob : objects ){
            //通过object对象创建一个短信对象
            SmsMessage sms = SmsMessage.createFromPdu((byte[])ob);
            System.out.println(sms.getMessageBody());
            System.out.println(sms.getOriginatingAddress());
        }
    }
* 系统创建广播时,把短信存放到一个数组,然后把数据以pdus为key存入bundle,再把bundle存入intent
* 清单文件中配置广播接收者接收的广播类型,注意要设置优先级属性,要保证优先级高于短信应用,才可以实现拦截

        <receiver android:name="com.itheima.smslistener.SmsReceiver">
            <intent-filter android:priority="1000">
                <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
            </intent-filter>
        </receiver>
* 添加权限

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

---
#监听SD卡状态
* 清单文件中定义广播接收者接收的类型,监听SD卡常见的三种状态,所以广播接收者需要接收三种广播

         <receiver android:name="com.itheima.sdcradlistener.SDCardReceiver">
            <intent-filter >
                <action android:name="android.intent.action.MEDIA_MOUNTED"/>
                <action android:name="android.intent.action.MEDIA_UNMOUNTED"/>
                <action android:name="android.intent.action.MEDIA_REMOVED"/>
                <data android:scheme="file"/>
            </intent-filter>
        </receiver>
* 广播接收者的定义

        public class SDCardReceiver extends BroadcastReceiver {
            @Override
            public void onReceive(Context context, Intent intent) {
                // 区分接收到的是哪个广播
                String action = intent.getAction();
                    
                if(action.equals("android.intent.action.MEDIA_MOUNTED")){
                    System.out.println("sd卡就绪");
                }
                else if(action.equals("android.intent.action.MEDIA_UNMOUNTED")){
                    System.out.println("sd卡被移除");
                }
                else if(action.equals("android.intent.action.MEDIA_REMOVED")){
                    System.out.println("sd卡被拔出");
                }
            }
        }

---
#勒索软件
* 接收开机广播,在广播接收者中启动勒索的Activity
* 清单文件中配置接收开机广播

        <receiver android:name="com.itheima.lesuo.BootReceiver">
            <intent-filter >
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>
* 权限

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

* 定义广播接收者

        @Override
        public void onReceive(Context context, Intent intent) {
            //开机的时候就启动勒索软件
            Intent it = new Intent(context, MainActivity.class);        
            context.startActivity(it);
        }
* 以上代码还不能启动MainActivity,因为广播接收者的启动,并不会创建任务栈,那么没有任务栈,就无法启动activity
* 手动设置创建新任务栈的flag

        it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

---
#监听应用的安装、卸载、更新
> 原理:应用在安装卸载更新时,系统会发送广播,广播里会携带应用的包名
* 清单文件定义广播接收者接收的类型,因为要监听应用的三个动作,所以需要接收三种广播

        <receiver android:name="com.itheima.app.AppReceiver">
            <intent-filter >
                <action android:name="android.intent.action.PACKAGE_ADDED"/>
                <action android:name="android.intent.action.PACKAGE_REPLACED"/>
                <action android:name="android.intent.action.PACKAGE_REMOVED"/>
                <data android:scheme="package"/>
            </intent-filter>
        </receiver>


0 0
原创粉丝点击