一、自定义广播
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添加取值。
结果