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

义与权限相关的"风险级别"。必须是以下值之一:
normal, dangerous, signature, signatureOrSystem ,取决于保护级别,在确定是否授予权限时,系统可能采取不同的操作。
normal 表示权限是低风险的,不会对系统、用户或其他应用程序造成危害;
dangerous 表示权限是高风险的,系统将可能要求用户输入相关信息,才会授予此权限;
signature 表示只有当应用程序所用数字签名与声明引权限的应用程序所用数字签名相同时,才能将权限授给它;
signatureOrSystem 表示将权限授给具有相同数字签名的应用程序或android 包类。这一保护级别适和于非常特殊的情况,比如多个供应商需要通过系统映像共享功能时


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);