普通广播和有序广播

安卓的广播分为普通广播和有序广播

  • 1.普通广播

    对于普通广播来说,多个Receiver都可以接收到同一条广播
    同样拿检测飞行模式的例子来示范,先新建三个Receiver类,实现onReceiver方法,除了第二个类中多了一个abortBroadcast方法外,其他两个类都没有这个方法。下面给出第二个类的代码
    MyReceiver2.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    package com.example.ahtcfg24.broadcastreceiverdemo3;

    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.util.Log;

    public class MyReceiver2 extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
    Log.i("2", "--->Received");
    abortBroadcast();//终止广播的发送

    }
    }

三个Receiver类建好之后去清单文件静态注册这三个Receiver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<receiver
android:name=".MyReceiver">

<intent-filter>
<action android:name="android.intent.action.AIRPLANE_MODE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
<receiver
android:name=".MyReceiver2">

<intent-filter>
<action android:name="android.intent.action.AIRPLANE_MODE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
<receiver
android:name=".MyReceiver3">

<intent-filter>
<action android:name="android.intent.action.AIRPLANE_MODE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>

然后运行程序,在改变飞行模式时,依然能在Logcat的info中看到
三个Receiver都接收到了
这表明abortBroadcast方法不能终止普通广播

查看代码

  • 2.有序广播

    有序广播的传播原理是优先级最高的Receiver收到,然后由它传递给优先级低的广播,依次传递
    优先级的范围是(-1000~1000),数值越大优先级越高。
    发送有序广播时使用sendOrderBroadcast方法,这个方法的第二个参数如果为null,就表示接收者不需要声明特定权限就可以接收到这条广播。像安卓系统的短信就是一种有序广播。如果接收者是一款负责拦截垃圾短信的软件,那么就要给这个软件声明接收短信的权限,以让这款软件接收到短信的广播,收到垃圾短信时终止广播,这样垃圾短信就不会被短信软件收到,从而用户就无法收到垃圾短信。

同样用三个Receiver来做示例
首先,我们在Activity中设定要发送的广播内容以及广播地址和自定义的接收广播的权限名称

MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.example.ahtcfg24.broadcastreceiverdemo4;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity {
private Button button;
private Intent intent;

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

button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
send();
}
});
}

private void send() {
intent = new Intent("android.intent.action.MyOrderBroadcast");//设定广播地址
intent.putExtra("广播", "这是自定义发出的一条广播");
sendOrderedBroadcast(intent, "android.permission.RECEIVE_MYBROADCAST");//接收者需要声明权限
}


}

然后我们分别建立三个Receiver,其中第二个Receiver中调用了abortBroadcast方法
MyReceiver.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.example.ahtcfg24.broadcastreceiverdemo4;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

public class MyReceiver extends BroadcastReceiver {

private Bundle bundle;

@Override


public void onReceive(Context context, Intent intent) {
String msg = intent.getStringExtra("广播");
Log.i("FirstReceiver", "--->" + msg);
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
putBundle(msg);//加工接收到的源广播

}

/**
* 如果下一个Receiver能够接收到这里的bundle,则证明广播确实是从高级别的Receiver传向低级别
*
* @param msg 从广播源接收到的消息
*/

private void putBundle(String msg) {
bundle = new Bundle();
bundle.putString("msg1", msg + ",被第一个Receiver处理过了");
setResultExtras(bundle);
}
}

MyReceiver2.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.example.ahtcfg24.broadcastreceiverdemo4;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

public class MyReceiver2 extends BroadcastReceiver {
private Bundle bundle;

@Override
public void onReceive(Context context, Intent intent) {
String msg = getResultExtras(true).getString("msg1");
Log.i("SecondReceiver", "--->" + msg);
Toast.makeText(context, msg, Toast.LENGTH_LONG).show();

putBundle(msg);

abortBroadcast();//停止广播

}

private void putBundle(String msg) {
bundle = new Bundle();
bundle.putString("msg2", msg + ",被第二个Receiver处理过了");
setResultExtras(bundle);
}
}

MyReceiver3.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.example.ahtcfg24.broadcastreceiverdemo4;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

public class MyReceiver3 extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
String msg = getResultExtras(true).getString("msg2");
Log.i("ThirdReceiver", "--->" + msg);
Toast.makeText(context, msg, Toast.LENGTH_LONG).show();

}

}

然后在清单文件中为每个Receiver设定优先级,并设定要接收的广播地址,并且还要声明一个接收此广播的权限,并使用此权限。
AndroidManifest.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?xml version="1.0" encoding="utf-8"?>
<manifest
package="com.example.ahtcfg24.broadcastreceiverdemo4"
xmlns:android="http://schemas.android.com/apk/res/android">


<permission
android:name="android.permission.RECEIVE_MYBROADCAST"
android:protectionLevel="normal"/>

<uses-permission android:name="android.permission.RECEIVE_MYBROADCAST"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">

<activity
android:name=".MainActivity"
android:label="@string/app_name">

<intent-filter>
<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>

<receiver
android:name=".MyReceiver">

<intent-filter android:priority="500">
<action android:name="android.intent.action.MyOrderBroadcast"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
<receiver
android:name=".MyReceiver2">

<intent-filter android:priority="200">
<action android:name="android.intent.action.MyOrderBroadcast"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
<receiver
android:name=".MyReceiver3">

<intent-filter android:priority="-200">
<action android:name="android.intent.action.MyOrderBroadcast"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
</application>
</manifest>

布局文件忽略

这样当我们点击发送按钮时,就能看到如下结果:
结果
从结果中我们能看出,MyReceiver接收到广播之后进行处理,然后交给MyReceiver2接收,然后MyReceiver2执行了终止广播方法,导致MyReceiver3没有收到广播

参考资料

(本文系作者原创,转载请注明出处)