关闭

Android之BroadcastReceiver(接收广播消息)学习笔记(一)

标签: 安卓四大组件androidbroadcast广播接收者
121人阅读 评论(0) 收藏 举报
分类:

Android之BroadcastReceiver(接收广播消息)学习笔记(一)

  BroadcastReceiver是四大组件之一,这种组件本质上就是一个全局监听器,用于监听系统全局的广播消息。这种实现,就是我们典型的观察者设计模式了,谁需要监听广播,就注册一个相应的广播即可。
  
  BoradcastReceiver用于接收程序所有发出的Broadcast Intent,与应用程序启动Activity,Service相同的是,程序启动BoradcastReceiver也只需要两步。
  
  1. 创建需要启动的BoradcastReceiver的Intent。
  2. 掉用Context的sendBroadcast()或者sendOrderedBroadcast()方法来启动指定的BoradcastReceiver。
  
  当应用程序发送一个Broadcast Intent只有,所有注册了该广播的Intent的BoradcastReceiver都有可能被启动。
  
  与Activity、Service具有 完整的生命周期不同,BoradcastReceiver本质上只是一个系统级的监听器——它专门负责监听各程序所发出的Broadcast。
  
  由于BoradcastReceiver本质上属于一个监听器,因此实现BoradcastReceiver的方法也十分简单,只要重写BoradcastReceiver的onReceive(Context context, Intent intent)方法即可。
  只要实现了BoradcastReceiver,然后就是要指定该BoradcastReceiver能匹配的Intent了,对于指定Intent,我们通常有两种方式。
  1. 使用代码指定:

IntentFilter filter = new IntentFilter("android.normal.first.broadcast");
MyReceiver receiver = new MyReceiver();
registerReceiver(receiver, filter);

对于上面的注册,首先建立一个IntentFilter对象,对应的参数就是我们指定的action,对于action,可以是自定义的,也可以是定义好的,这个取决与自己的具体实现。receiver对象,是我们自定义的一个BroadcastReceiver对象。最后通过添加registerReceiver(receiver, filter)即可

  2. 直接在AndroidManifest.xml中配置。

<receiver
     android:name=".MyReceiver"
     android:enabled="true"
     android:exported="true">
     <intent-filter>
         <action android:name="android.normal.first.broadcast" />
     </intent-filter>
</receiver>

  每次系统Broadcast事件发生只有,系统就会创建新的对应的BroadcastReceiver实例,并自动触发它的onReceive()方法,onReceive方法执行完后,BroadcastReceiver实例就会被销毁。
  
  BroadcastReceiver与Activity还有一个区别就是,当我们通过Intent启动指定的Activity组件时,如果系统没有找到合适的Activity组件,则会导致程序崩溃,而BroadcastReceiver找不到指定的Intent时,则不会出现任何问题。
  
  需要注意的是,如果在BroadcastReceiver的onReceive()方法中不能在10秒内执行完成,则会出现ANR,程序无响应,所以我们也不能在BroadcastReceiver中执行耗时操作。并且我们也不能在BroadcastReceiver的onReceive()方法中去创建新的线程来完成耗时操作,因为BroadcastReceiver本身的生命周期非常短,可能出现的情况是,子线程还没有结束,BroadcastReceiver就已经退出了,如果BroadcastReceiver进程结束了,虽然该进程中还有用户启动的新线程,但由于该进程内不包含任何活动组件,因此系统可能在内存紧张时优先结束该进程。这样就可能导致BroadcastReceiver启动的子线程不能执行完成。
  
  通常广播分为两种方式;
  
  1. 无序广播,对于无序广播,他的优点完全是采用异步的方式进行广播,可以在同一时刻被所有的接受者收到,消息传递效率比较高。缺点是接受者不能将处理结果传递给下一个接受者,并且无法终止Broadcast Intent的传播。
  2. 有序广播,按照BroadcastReceiver的优先级来一次接收Broadcast,比如A > B > C,则最先接收到的是A,其实是B,最后是C,优先级别设置有两种方式,一种是在xml中配置,一种是在代码中通过filter.setPriority()设置优先级别,具体的将在以下代码中来实现。

下面先来实现无序广播方式(通过代码方式注册广播)

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    >

    <Button
        android:id="@+id/mNormalB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="发送无序广播" />


</RelativeLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button mNormalB;
    private boolean flag = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        event();
    }

    private void event() {
        mNormalB.setOnClickListener(this);
    }

    private void init() {
        mNormalB = ((Button) findViewById(R.id.mNormalB));
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.mNormalB:
                sendNormalBroadCast1();
                break;
        }
    }

    private void sendNormalBroadCast1() {
        if(flag){
            //只需要注册一次即可
            normalBroad();
            flag = false;
        }
        //设置Intent
        Intent intent = new Intent("android.normal.first.broadcast");
        //设置传递的数据
        Bundle bundle = new Bundle();
        bundle.putInt("num1", 58);
        bundle.putString("msg", "消息1");
        intent.putExtras(bundle);
        //发送无序广播
        sendBroadcast(intent);
    }

    private void normalBroad() {
        IntentFilter filter = new IntentFilter("android.normal.first.broadcast");
        MyReceiver1 receiver1 = new MyReceiver1();
        MyReceiver2 receiver2 = new MyReceiver2();
        MyReceiver3 receiver3 = new MyReceiver3();
        registerReceiver(receiver1, filter);
        registerReceiver(receiver2, filter);
        registerReceiver(receiver3, filter);
    }
}

两个接收者:
MyReceiver1 .java

public class MyReceiver1 extends BroadcastReceiver {
    public MyReceiver1() {
    }

     /**
     * 实现该方法即可,系统会自动调用处理
     * @param context 上下文
     * @param intent 对应的Intent
     */
    @Override
    public void onReceive(Context context, Intent intent) {
        //获取Intent中携带的数据
        Bundle bundle = intent.getExtras();
        if(bundle != null){
            int num1 = bundle.getInt("num1");
            String msg = bundle.getString("msg");
            Log.i("IT_Real", "onReceive1: num1  = " + num1 + "msg = " + msg);
        }
    }
}

MyReceiver2.java

public class MyReceiver2 extends BroadcastReceiver {
    public MyReceiver2() {
    }

     /**
     * 实现该方法即可,系统会自动调用处理
     * @param context 上下文
     * @param intent 对应的Intent
     */
    @Override
    public void onReceive(Context context, Intent intent) {
        //获取Intent中携带的数据
        Bundle bundle = intent.getExtras();
        if(bundle != null){
            int num1 = bundle.getInt("num1");
            String msg = bundle.getString("msg");
            Log.i("IT_Real", "onReceive1: num1  = " + num1 + "msg = " + msg);
        }
    }
}

当MainActivity通过点击发送按钮,则这两个BroadcastReceiver会接收到对应的广播消息。

无序广播方式(清单方式注册广播)

MainActiviy.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button mNormalB;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        event();
    }

    private void event() {
        mNormalB.setOnClickListener(this);
    }

    private void init() {
        mNormalB = ((Button) findViewById(R.id.mNormalB));
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.mNormalB:
                sendNormalBroadCast1();
                break;
        }
    }
    private void sendNormalBroadCast1() {
        Intent intent = new Intent("android.normal.first.broadcast");
        Bundle bundle = new Bundle();
        bundle.putInt("num1",58);
        bundle.putString("msg","消息1");
        intent.putExtras(bundle);
        sendBroadcast(intent);
    }
}

AndroidManifest.xml

     <receiver
            android:name=".MyReceiver1"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.normal.first.broadcast" />
            </intent-filter>
        </receiver>
        <receiver
            android:name=".MyReceiver2"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.normal.first.broadcast" />
            </intent-filter>
        </receiver>

其中,注册的BroadcastReceiver和上面的MyReceiver1、 MyReceiver2 一样。无序广播的两种方式就实现了。非常简单。

有序广播的实现(代码注册方式)

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    >



    <Button
        android:id="@+id/mOrderB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="发送有序广播" />
</RelativeLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button mOrderB;
    private boolean flag = true;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        event();
    }

    private void event() {
        mOrderB.setOnClickListener(this);
    }

    private void init() {
        mOrderB = ((Button) findViewById(R.id.mOrderB));
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.mOrderB:
                sendOrderBroadCast1();
                break;
        }
    }
    private void sendOrderBroadCast1() {
        if(flag){
            //只需要注册一次即可
            orderBroad();
            flag = false;
        }
        //Intent
        Intent intent = new Intent("android.order.first.broadcast");
        //存放对应的数据
        Bundle bundle = new Bundle();
        bundle.putInt("num1",58);
        bundle.putString("msg","消息1");
        intent.putExtras(bundle);
        //发送有序广播
        sendOrderedBroadcast(intent,null);
    }
    private void orderBroad(){
        IntentFilter filter = new IntentFilter("android.order.first.broadcast");
        MyReceiverOrder1 receiver1 = new MyReceiverOrder1();
        MyReceiverOrder2 receiver2 = new MyReceiverOrder2();
        MyReceiverOrder3 receiver3 = new MyReceiverOrder3();
        MyReceiverOrder4 receiver4 = new MyReceiverOrder4();
        //filter.setPriority(300);
        registerReceiver(receiver1, filter);
        //filter.setPriority(1000);
        registerReceiver(receiver2,filter);
        //filter.setPriority(500);
        registerReceiver(receiver3,filter);
        //filter.setPriority(100);
        registerReceiver(receiver4,filter);
    }
}

四个自定义的广播接收者

MyReceiverOrder1 .java

public class MyReceiverOrder1 extends BroadcastReceiver {
    public MyReceiverOrder1() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle bundle = intent.getExtras();
        if(bundle != null){
            int num1 = bundle.getInt("num1");
            String msg = bundle.getString("msg");
            Log.i("IT_Real", "onReceive1: " + num1 + "msg = " + msg);
            bundle.putString("msg2","省级消息");
            setResultExtras(bundle);
        }
        //abortBroadcast();//这里表示在某个接收者中可以中断该广播,之后的所有低于该广播接收的则都接不到广播消息。
        }
    }

MyReceiverOrder2.java

public class MyReceiverOrder2 extends BroadcastReceiver {
    public MyReceiverOrder2() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle bundle = getResultExtras(true);
        if(bundle != null){
            int num1 = bundle.getInt("num1");
            String msg = bundle.getString("msg");
            String msg2 = bundle.getString("msg2");
            Log.i("IT_Real", "onReceive2: " + num1 + "msg = " + msg + "msg2 = " + msg2);
            bundle.putString("msg3","市级消息");
            setResultExtras(bundle);
        }
    }
}

MyReceiverOrder3 .java

public class MyReceiverOrder3 extends BroadcastReceiver {
    public MyReceiverOrder3() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle bundle = getResultExtras(true);
        if(bundle != null){
            int num1 = bundle.getInt("num1");
            String msg = bundle.getString("msg");
            String msg3 = bundle.getString("msg3");
            Log.i("IT_Real", "onReceive3: " + num1 + "msg = " + msg + "msg3 = " + msg3);
            bundle.putString("msg4","县级消息");
            setResultExtras(bundle);
        }
    }
}

MyReceiverOrder4.java

public class MyReceiverOrder4 extends BroadcastReceiver {
    public MyReceiverOrder4() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle bundle = getResultExtras(true);
        if(bundle != null){
            int num1 = bundle.getInt("num1");
            String msg = bundle.getString("msg");
            String msg4 = bundle.getString("msg4");
            Log.i("IT_Real", "onReceive4: " + num1 + "msg = " + msg + "msg4 = " + msg4);
        }
    }
}

上面就是一个有序的广播实现,上面没有设置对应的优先级别,所以默认的级别是从registerReceiver(receiver1, filter);注册的顺序依次下来的,receiver1  >  receiver2  > receiver3 > receiver4,如果要设置对应的优先级,比如  receiver2 >  receiver3 > receiver1 > receiver4,则只要将上面的注释去掉即可,即setPriority(int number)里面的number数值越大,优先级别越高。这里的四个广播接受者,按照我们默认的顺序来接受广播,这里刚好模拟了一个领导发送消息的功能,国家发送消息给省级receiver1,市级receiver2接受了省级receiver1的消息,receiver1里面多加了一消息,依次到最后,receiver4为普通老百姓。即国家发消息给——省级(receiver1)——市级(receiver2)——县级(receiver3)——老百姓(receiver4)  

有序广播的实现(清单注册方式)

MainActiviy.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button mOrderB;
    private boolean flag = true;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        event();
    }

    private void event() {
        mOrderB.setOnClickListener(this);
    }

    private void init() {
        mOrderB = ((Button) findViewById(R.id.mOrderB));
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.mOrderB:
                sendOrderBroadCast1();
                break;
        }
    }
    private void sendOrderBroadCast1() {
        //Intent
        Intent intent = new Intent("android.order.first.broadcast");
        //存放对应的数据
        Bundle bundle = new Bundle();
        bundle.putInt("num1",58);
        bundle.putString("msg","消息1");
        intent.putExtras(bundle);
        //发送有序广播
        sendOrderedBroadcast(intent,null);
    }
}

AndroidManifest.xml中的注册形式

        <receiver
            android:name=".MyReceiverOrder1"
            android:enabled="true"
            android:exported="true">
            <intent-filter android:priority="1000">
                <action android:name="android.order.first.broadcast"/>
            </intent-filter>
        </receiver>
        <receiver
            android:name=".MyReceiverOrder2"
            android:enabled="true"
            android:exported="true">
            <intent-filter android:priority="500">
                <action android:name="android.order.first.broadcast"/>
            </intent-filter>
        </receiver>
        <receiver
            android:name=".MyReceiverOrder3"
            android:enabled="true"
            android:exported="true">
            <intent-filter android:priority="300">
                <action android:name="android.order.first.broadcast"/>
            </intent-filter>
        </receiver>
        <receiver
            android:name=".MyReceiverOrder4"
            android:enabled="true"
            android:exported="true">
            <intent-filter android:priority="100">
                <action android:name="android.order.first.broadcast"/>
            </intent-filter>intent-filter
        </receiver>

android:priority 表示的是设置优先级别,这些注册必须在<application> </application>

这样就完成了有序广播的两种实现方式。

1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:34518次
    • 积分:1014
    • 等级:
    • 排名:千里之外
    • 原创:58篇
    • 转载:6篇
    • 译文:2篇
    • 评论:21条
    博客专栏
    文章存档
    最新评论