Android之广播Broadcast

一、自定义广播

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/beijing"
    tools:context=".MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="50dp"
        android:background="#FFD2D2"
        android:onClick="send"
        android:paddingLeft="5dp"
        android:paddingRight="5dp"
        android:text="发送求救广播"
        android:textSize="20sp" />
</RelativeLayout>

广播接受者MyBroadcastReceiver1.java

public class MyBroadcastReceiver1 extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("test", "自定义的广播接收者,接收到了求救广播事件");
        Log.i("test", intent.getAction());
    }
}

AndroidManifest.xml注册静态广播

       <receiver
            android:name=".MyBroadcastReceiver1"
            android:enabled="true"
            android:exported="true">
               <intent-filter>
                    <action android:name="Help_Stitch" />
               </intent-filter>
        </receiver>

1.静态注册

注意intent.setAction(“Help_Stitch”);参数要与AndroidManifest.xml注册的广播名一致,不然接收不到广播。
MainActivity.java

public class MainActivity extends AppCompatActivity {

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

    public void send(View view) {
        Log.v("test", "send");
        Intent intent = new Intent();
        //静态广播使用Component
        //包路径项目名,包路径接受者
        intent.setComponent(new ComponentName("com.example.ch6", "com.example.ch6.MyBroadcastReceiver1"));
        // 定义广播的事件类型
        intent.setAction("Help_Stitch");//参数要与onCreate()里的IntentFilter()的参数一致,不然接收不到广播
        // 发送广播
        sendBroadcast(intent);
    }
}

结果
在这里插入图片描述

2.动态注册

注释掉AndroidManifest.xml的静态广播的注册

<!--        <receiver-->
<!--            android:name=".MyBroadcastReceiver1"-->
<!--            android:enabled="true"-->
<!--            android:exported="true">-->
<!--            <intent-filter>-->
<!--                <action android:name="Help_Stitch" />-->
<!--            </intent-filter>-->
<!--        </receiver>-->

修改MainActivity.java
注释掉

intent.setComponent(new ComponentName("com.example.ch6", "com.example.ch6.MyBroadcastReceiver1"));

添加全局变量,在onCreate注册广播,添加onDestroy()方法注销广播。
注意intent.setAction(“Help_Stitch”);参数要与onCreate()里的IntentFilter(“Help_Stitch”)的参数一致

	//全局变量,用来注册和注销
	private MyBroadcastReceiver1 mMyBroadcastReceiver1;

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

        //注册广播
        mMyBroadcastReceiver1 = new MyBroadcastReceiver1();
        IntentFilter intentFilter = new IntentFilter("Help_Stitch");
        registerReceiver(mMyBroadcastReceiver1, intentFilter);
    }
    public void send(View view) {
        Log.v("test", "send");
        Intent intent = new Intent();
        // 定义广播的事件类型
        //参数要与onCreate()里的IntentFilter()的参数一致,不然接收不到
        intent.setAction("Help_Stitch");
        // 发送广播
        sendBroadcast(intent);
    }

	//动态广播注销广播接受者
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mMyBroadcastReceiver1 != null)
            unregisterReceiver(mMyBroadcastReceiver1);
    }

结果如上

二、有序和无序广播

使用到优先级
新建三个接受者

public class MyBroadcastReceiver1 extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("test", "自定义的广播接收者【Receiver1】,接收到了求救广播事件");
        Log.i("test", intent.getAction());
    }
}
public class MyBroadcastReceiver2 extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("test", "自定义的广播接收者【Receiver2】,接收到了求救广播事件");
        Log.i("test", intent.getAction());
    }
}
public class MyBroadcastReceiver3 extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("test", "自定义的广播接收者【Receiver3】,接收到了求救广播事件");
        Log.i("test", intent.getAction());
    }
}

1.静态注册

注意AndroidManifest.xml要注册到

        <receiver
            android:name=".MyBroadcastReceiver1"
            android:enabled="true"
            android:exported="true">
            <intent-filter android:priority="300">
                <action android:name="Broadcast" />
            </intent-filter>
        </receiver>
        <receiver
            android:name=".MyBroadcastReceiver2"
            android:enabled="true"
            android:exported="true">
            <intent-filter android:priority="500">
                <action android:name="Broadcast" />
            </intent-filter>
        </receiver>
        <receiver
            android:name=".MyBroadcastReceiver3"
            android:enabled="true"
            android:exported="true">
            <intent-filter android:priority="400">
                <action android:name="Broadcast" />
            </intent-filter>
        </receiver>

优先级:android:priority=“500” 优先级越高则越先注册。
如上使用静态注册,如果没有优先级则注册顺序为1、2、3,但是加了优先级后顺序就为2、3、1。
修改MainActivity.java

public class MainActivity extends AppCompatActivity {

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

    public void send(View view) {
        Log.v("test", "send");
        Intent intent = new Intent();
        // 定义广播的事件类型
        //参数要与onCreate()里的IntentFilter()的参数一致,不然接收不到
        intent.setAction("Broadcast");
        //静态广播使用Component注册每个广播
        //包路径项目名,包路径接受者
        intent.setComponent(new ComponentName("com.example.ch6", "com.example.ch6.MyBroadcastReceiver1"));
        intent.setComponent(new ComponentName("com.example.ch6", "com.example.ch6.MyBroadcastReceiver2"));
        intent.setComponent(new ComponentName("com.example.ch6", "com.example.ch6.MyBroadcastReceiver3"));

        // 发送广播
        sendOrderedBroadcast(intent,null);
    }

结果
在这里插入图片描述
只有3!
将intent.setComponent()的顺序换一下

        //静态广播使用Component
        //包路径项目名,包路径接受者
        intent.setComponent(new ComponentName("com.example.ch6", "com.example.ch6.MyBroadcastReceiver3"));
        intent.setComponent(new ComponentName("com.example.ch6", "com.example.ch6.MyBroadcastReceiver1"));
        intent.setComponent(new ComponentName("com.example.ch6", "com.example.ch6.MyBroadcastReceiver2"));

结果为2!
在这里插入图片描述
然后把最后一个2的intent.setComponent()注释掉

        //静态广播使用Component
        //包路径项目名,包路径接受者
        intent.setComponent(new ComponentName("com.example.ch6", "com.example.ch6.MyBroadcastReceiver3"));
        intent.setComponent(new ComponentName("com.example.ch6", "com.example.ch6.MyBroadcastReceiver1"));
//        intent.setComponent(new ComponentName("com.example.ch6", "com.example.ch6.MyBroadcastReceiver2"));

结果是1。
在这里插入图片描述
结论:最后一个intent.setComponent()覆盖了前面的,所以只广播了最后一个。
要想广播全部则需要将三个intent.setComponent()注释掉,改为intent.setPackage()。

public void send(View view) {
        Log.v("test", "send");
        Intent intent = new Intent();
        // 定义广播的事件类型
        //参数要与onCreate()里的IntentFilter()的参数一致,不然接收不到
        intent.setAction("Broadcast");
        //静态广播使用Component
        //包路径项目名,包路径接受者
//        intent.setComponent(new ComponentName("com.example.ch6", "com.example.ch6.MyBroadcastReceiver3"));
//        intent.setComponent(new ComponentName("com.example.ch6", "com.example.ch6.MyBroadcastReceiver1"));
//        intent.setComponent(new ComponentName("com.example.ch6", "com.example.ch6.MyBroadcastReceiver2"));

        intent.setPackage("com.example.ch6");

        // 发送广播
        sendOrderedBroadcast(intent,null);
    }

结果为2、3、1 。

所以多个广播接受者需要用setPackage()。
在这里插入图片描述
如果把AndroidManifest.xml优先级都改成一样的,则顺序为注册顺序1、2、3 。
结果
在这里插入图片描述
还是把优先级设置回来,在send()里同时设置setComponent()和setPackage()

        //静态广播使用Component
        //包路径项目名,包路径接受者
        intent.setComponent(new ComponentName("com.example.ch6", "com.example.ch6.MyBroadcastReceiver1"));
        intent.setComponent(new ComponentName("com.example.ch6", "com.example.ch6.MyBroadcastReceiver2"));
        intent.setComponent(new ComponentName("com.example.ch6", "com.example.ch6.MyBroadcastReceiver3"));

        intent.setPackage("com.example.ch6");

观察到结果只有3!并不是2、3、1,也不是1、2、3 。
在这里插入图片描述
所以得出结论:setComponent()比setPackage()调用的优先级高。

2.动态注册

修改MainActivity.java
添加MyBroadcastReceiver1、2、3的全局变量,并在onCreate()中注册(注册顺序为1、2、3),先不设置优先级。在onDestroy()设置MyBroadcastReceiver1、2、3的注销。

public class MainActivity extends AppCompatActivity {

    private MyBroadcastReceiver1 mMyBroadcastReceiver1;
    private MyBroadcastReceiver2 mMyBroadcastReceiver2;
    private MyBroadcastReceiver3 mMyBroadcastReceiver3;

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

        IntentFilter intentFilter = new IntentFilter("Broadcast");
        //注册广播
        mMyBroadcastReceiver1 = new MyBroadcastReceiver1();
        registerReceiver(mMyBroadcastReceiver1, intentFilter);
        mMyBroadcastReceiver2 = new MyBroadcastReceiver2();
        registerReceiver(mMyBroadcastReceiver2, intentFilter);
        mMyBroadcastReceiver3 = new MyBroadcastReceiver3();
        registerReceiver(mMyBroadcastReceiver3, intentFilter);
    }

    public void send(View view) {
        Log.v("test", "send");
        Intent intent = new Intent();
        // 定义广播的事件类型
        //参数要与onCreate()里的IntentFilter()的参数一致,不然接收不到
        intent.setAction("Broadcast");
        sendOrderedBroadcast(intent, null,mMyBroadcastReceiver3,
                null,0,null,null);
    }

    //动态广播注销广播接受者
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mMyBroadcastReceiver1 != null)
            unregisterReceiver(mMyBroadcastReceiver1);
        if (mMyBroadcastReceiver2 != null)
            unregisterReceiver(mMyBroadcastReceiver2);
        if (mMyBroadcastReceiver3 != null)
            unregisterReceiver(mMyBroadcastReceiver3);
    }
}

此时AndroidManifest.xml没有改变,即在AndroidManifest.xml中注册顺序为1、2、3,而优先级为2、3、1 。
结果
在这里插入图片描述
然后把MyBroadcastReceiver的位置换一下,动态注册顺序为3、1、2。
结果为3、1、2。
在这里插入图片描述
结论:动态注册未设置优先级时执行顺序和注册顺序一样,且与AndroidManifest.xml无关。
然后给每个mMyBroadcastReceiver添加优先级:setPriority(100);参数为优先级大小。
这里设置3为100,1为300,2为500;注册顺序依旧为3、1、2 。
结果
在这里插入图片描述
结论:动态注册设置了优先级时,执行顺序和优先级有关,优先级越大越先执行,且与AndroidManifest.xml无关。

3.广播拦截机制

沿用上面例子,执行顺序为2、1、3 。
在MyBroadcastReceiver1设置拦截:abortBroadcast();
结果拦截了3 。
在这里插入图片描述
然后注释掉该拦截,在MyBroadcastReceiver2设置拦截:abortBroadcast();
结果只有2!2之后的所有广播都被拦截了。
在这里插入图片描述
如果只想拦截1,且能接收到3,应该在MyBroadcastReceiver2设置拦截,应该在MainActivity.java修改send()的发送广播的sendOrderedBroadcast()函数的参数。

sendOrderedBroadcast(intent, null);

改为

sendOrderedBroadcast(intent, null,mMyBroadcastReceiver3,null,0,null,null);

即指定接收mMyBroadcastReceiver3 。
结果
在这里插入图片描述

4.一个receiver接收多个携带数据的广播

首先让MyBroadcastReceiver2接收两个广播。
修改MyBroadcastReceiver2.java,注释拦截语句

public class MyBroadcastReceiver2 extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action.equals("Broadcast")) {
            Log.i("test", "自定义的广播接收者【Receiver2】处理广播"+intent.getAction());

        } else if (action.equals("Broadcast_2")) {
            Log.i("test", "自定义的广播接收者【Receiver2】处理广播"+intent.getAction());

        } else {
            assert false;
        }
    }
}

再修改MainActivity.java
在**onCreate()**函数中绑定路由,再注册,添加

        IntentFilter intentFilter_2 = new IntentFilter();
        intentFilter_2.addAction("Broadcast_2");
        registerReceiver(mMyBroadcastReceiver2, intentFilter_2);

**send()**函数添加

        Intent intent_2= new Intent();
        intent_2.setAction("Broadcast_2");
		//发送广播
		sendOrderedBroadcast(intent_2,null);

注意:一定要一一对应:addAction()和setAction()参数一样
结果 2接收了两个广播。
在这里插入图片描述
接下来添加传递的数据
1)在发送时,调用Intent的putExtra方法,放入键值对;
2)在receiver中用getStringExtra、getIntExtra等方法来取;

在MainActivity.java的send()函数添加键值对
在这里插入图片描述
在MyBroadcastReceiver2.java添加取值。
在这里插入图片描述
结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值