BroadcastReceiver所对应的广播分两类:普通广播和有序广播。
普通广播:通过Context.sendBroadcast()方法来发送,它是完全异步的。
所有的receivers(接收器)的执行顺序不确定,因此所有的receivers(接收器)接收broadcast的顺序不确定。
这种方式效率更高,但是BroadcastReceiver无法使用setResult系列、getResult系列及abort(中止)系列API
有序广播:是通过Context.sendOrderedBroadcast来发送,所有的receiver依次执行。
BroadcastReceiver可以使用setResult系列函数来结果传给下一个BroadcastReceiver,通过getResult系列函数来取得上个BroadcastReceiver返回的结果,并可以abort系列函数来让系统丢弃该广播,使用该广播不再传送到别的BroadcastReceiver。
可以通过在intent-filter中设置android:priority属性来设置receiver的优先级,优先级相同的receiver其执行顺序不确定。
如果BroadcastReceiver是代码中注册的话,且其intent-filter拥有相同android:priority属性的话,先注册的将先收到广播。
有序广播,即从优先级别最高的广播接收器开始接收,接收完了如果没有丢弃,就下传给下一个次高优先级别的广播接收器进行处理,依次类推,直到最后。如果多个应用程序设置的优先级别相同,则谁先注册的广播,谁就可以优先接收到广播。
这里接收短信的广播是有序广播,因此可以设置你自己的广播接收器的级别高于系统原来的级别,就可以拦截短信,并且不存收件箱,也不会有来信提示音。
普通广播就不多说了,有序的会用,无序没有不会用的。
有序广播核心代码如下:
public class MainActivity extends Activity {
private View btnSendOrderBroadCast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
} public void sendOrderBroadCast() {
Intent intent=new Intent("com.test.mybroadcast");//清单文件中配置的
intent.putExtra("msg", "hello world ");
sendOrderedBroadcast(intent, "com.test.permission");//receiverPermission:是自定义个权限
// sendOrderedBroadcast(intent, null);
}
}
MyOrderBroadcastReciver.java
public class MyOrderBroadcastReciver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String strMsg = intent.getStringExtra("msg");
Log.e("test", "第一个:"+strMsg);
Bundle extras=new Bundle();
extras.putString("msg", "第一个界面传过来的"+strMsg);
setResultExtras(extras); //继续向下川
}
}
MyOrderBroadcastReciverTwo.java
public class MyOrderBroadcastReciverTwo extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
abortBroadcast();//开启此处,可以截断广播,不让它传到third中
String strMsg = intent.getStringExtra("msg"); //获取广播的原始数据
Log.e("test", "第二个:"+strMsg);
Bundle extras=new Bundle();
extras.putString("msg", "第二个界面传过来的"+strMsg);
setResultExtras(extras); //继续向下川
setResultData("第二个:"+strMsg); // "第二个:"+strMsg这是two中新的数据,传递到third中,在third中是用getResultData来获得setResultData("")中的数据
}
}
manifest.xml
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<permission android:name="com.test.permission"
android:protectionLevel="normal"
></permission>
<uses-permission android:name="com.test.permission"/>
<receiver
android:name="com.example.demoorderbroadcast.MyOrderBroadcastReciver"
>
<intent-filter
android:priority="1000"
>
<action android:name="com.test.mybroadcast"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
<receiver
android:name="com.example.demoorderbroadcast.MyOrderBroadcastReciverTwo"
>
<intent-filter
android:priority="999"
>
<action android:name="com.test.mybroadcast"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
有序广播的接收者可以终止广播Intent 的传播,广播Intent 的传播一旦终止,后面的接收者就无法接收到广播,使用abortBroadcast();即可。
<permission>定义:
1. <permission android:description="string resource"
2. "drawable resource"
3. "string resource"
4. "string"
5. "string"
6. "normal" | "dangerous"
7. "signature" | "signatureOrSystem"] />
<uses-permission>用法:
<uses-permission android:name="string" />
为了保证application的正常运行,需要系统授予app的权限声明。这个权限是在用户安装应用的时候授予的。
android:name的值可以是其他app通过<permission>声明的,也可以是系统的权限名称
注:uses-permission的权限要求说明,可能会引起app在Android Market中的过滤
自定义权限如下:
<permission android:label=”自定义权限”
android:description=”@string/hello”
android:name=”com.example.project.PERMITTED_ACTION”
android:protectionLevel=”normal”
android:icon=”@drawable/ic_launcher”>
< /permission>
android:label:权限名字,显示给用户的,值可是一个string数据,例如这里的“自定义权限”。
android:description:比label更长的对权限的描述。值是通过resource文件中获取的,不能直接写string值,例如这里的”@string/hello”。
android:name:权限名字,如果其他app引用该权限需要填写这个名字。
android:protectionLevel:权限级别,分为4个级别:
normal:低风险权限,在安装的时候,系统会自动授予权限给application。
dangerous:高风险权限,系统不会自动授予权限给app,在用到的时候,会给用户提示。
signature:签名权限,在其他app引用声明的权限的时候,需要保证两个app的签名一致。这样系统就会自动授予权限给第三方app,而不提示给用户。
signatureOrSystem:这个权限是引用该权限的app需要有和系统同样的签名才能授予的权限,一般不推荐使用。
各属性具体含义如下:
属性 | 含义 | 是否必须 |
name | 自定义的权限名称,需要遵循Android权限定义命名方案:*.permission.* | 是 |
protectionLevel | 义与权限相关的"风险级别"。必须是以下值之一: | 是 |
permissionGroup | 可以将权限放在一个组中,但对于自定期义权限,应该避免设置此属性。如果确实希望设置此属性,可能使用以下属性代替:android.permisson-group.SYSTEM_TOOLS | 否 |
label | 可使用它对权限进行简短描述 | 否 |
description | 使用它提供对权限用途和所保护对象的更有用的描述 | 否 |
icon | 权限可以与资源目录以外的图标相关联 ( 比如@drawable/myicon) | 否 |
protectionLevel的使用:
(1)Normal
权限被声明为Normal级别,任何应用都可以申请,在安装应用时,不会直接提示给用户,点击全部才会展示。
(2)Dangerous
权限被声明为Dangerous级别,任何应用都可以申请,在安装应用时,会直接提示给用户。
(3)Signature
权限被声明为Signature级别,只有和该apk(定义了这个权限的apk)用相同的私钥签名的应用才可以申请该权限。
frameworks/base/core/res/AndroidManifest.xml声明的权限为Signature级别,那么只有Android官方使用相同私钥签名的应用才可以申请该权限。
(4)SignatureOrSystem
权限被声明为SignatureOrSystem级别,有两种应用可以申请该权限。
1)和该apk(定义了这个权限的apk)用相同的私钥签名的应用
2)在/system/app目录下的应用
android:priority 属性
最大值不是1000,而是2147483647,这个数字怎么来的呢?熟悉数据结构的童鞋都知道,Integer 的最大值。
而且动态注册要比静态注册的优先级高。
动态注册:
1. IntentFilter filter = new
2. filter.addAction("android.provider.Telephony.SMS_RECEIVED");
3. filter.setPriority(Integer.MAX_VALUE);
4. registerReceiver(new SmsReceiver(), filter);