• Android 广播机制


    1、广播接收者

            广播接收者简单地说就是接收广播意图的Java类,此Java类继承BroadcastReceiver类,并重写onReceive方法

    public void onReceive(Context context,Intent intent),

    其中intent可以获得传递的数据

    定义了三个广播接收者如下: 

                  优先级   ReceiverSelf3  > ReceiverSelf2 > ReceiverSelf1   (注册的代码中可见)

    public class ReceiverSelf1 extends BroadcastReceiver {
    private final String TAG = "ReceiverSelf1";
    @Override
    public void onReceive(Context context, Intent intent) {
    String name = intent.getExtras().getString("name");
    if(isOrderedBroadcast()){
    Log.d(TAG, "onReceive: getExtras in 有序广播"+name);
    }else{
    Log.d(TAG, "onReceive: getExtras in 无序广播"+name);
    }
    //当发送有序广播时,可以让广播不再往下传递。 ReceiverSelf2 不能收到广播(Manifest中ReceiverSelf1的优先级更高 )
    //如果发送的是 无序广播 则会崩溃
    }
    }
    public class ReceiverSelf2 extends BroadcastReceiver {
    private final String TAG = "ReceiverSelf2";
    @Override
    public void onReceive(Context context, Intent intent) {
    String name = intent.getExtras().getString("name");
    if(isOrderedBroadcast()){
    Log.d(TAG, "onReceive: getExtras in 有序广播"+name);
    }else{
    Log.d(TAG, "onReceive: getExtras in 无序广播"+name);
    }
    if(isOrderedBroadcast()){ //判断接受的是否为 有序广播
    Bundle bundle = getResultExtras(false);
    if(bundle != null){
    String orderData = bundle.getString(BroadcastActivity.ORDER_DATA);
    Log.d(TAG, BroadcastActivity.ORDER_DATA+" "+orderData);
    }

    String resultData = getResultData();
    Log.d(TAG, BroadcastActivity.ORDER_DATA+" "+resultData);
    setResultData("优先级为 3 setResultData的数据"); //修改有序广播的数据
    Log.d(TAG, "onReceive: _______________________________________________");
    abortBroadcast();  // 广播不再往下传播
    }
    }
    public class ReceiverSelf3 extends BroadcastReceiver {
    private final String TAG = "ReceiverSelf3";
    @Override
    public void onReceive(Context context, Intent intent) {
    String name = intent.getExtras().getString("name");
    if(isOrderedBroadcast()){
    Log.d(TAG, "onReceive: getExtras in 有序广播"+name);
    }else{
    Log.d(TAG, "onReceive: getExtras in 无序广播"+name);
    }

    if(isOrderedBroadcast()){ //判断接受的是否为 有序广播
    Bundle bundle = getResultExtras(false);
    if(bundle != null){
    String orderData = bundle.getString(BroadcastActivity.ORDER_DATA);
    Log.d(TAG, BroadcastActivity.ORDER_DATA+" "+orderData);
    }

    String resultData = getResultData();
    Log.d(TAG, BroadcastActivity.ORDER_DATA+" "+resultData);
    setResultData("优先级为 3 setResultData的数据"); //修改有序广播的数据
    Log.d(TAG, "onReceive: _______________________________________________");
    }
    }

    BroadcastReceiver所对应的广播分两类:无序广播和有序广播。

    2、注册广播

         广播的注册有两种方式,一种为静态注册,即在AndroidManifest中注册一个广播接收者。另一种动态注册的方式是通过代码注册。

    <receiver android:name=".AndroidBroadcast.ReceiverSelf1">
    <intent-filter android:priority="1">
    <action android:name="com.xiazdong"/>
    </intent-filter>
    </receiver>

    <receiver android:name=".AndroidBroadcast.ReceiverSelf2">
    <intent-filter android:priority="2">
    <action android:name="com.xiazdong"/>
    </intent-filter>
    </receiver>

    <receiver android:name=".AndroidBroadcast.ReceiverSelf3">
    <intent-filter android:priority="3">
    <action android:name="com.xiazdong"/>
    </intent-filter>
    </receiver>

    注: priority 表明接收者的优先级 -1000~1000,优先级越高的接收者先接收到广播。

           intent-filter 定义自己接收广播的意图(可进行过滤)    


    动态注册如下:在代码中通过调用Context的registerReceiver()方法进行动态注册BroadcastReceiver,具体代码如下:

    @Override protected void onResume(){ super.onResume(); //实例化BroadcastReceiver子类 & IntentFilter mBroadcastReceiver mBroadcastReceiver = new mBroadcastReceiver(); IntentFilter intentFilter = new IntentFilter(); //设置接收广播的类型 intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE); //调用Context的registerReceiver()方法进行动态注册 registerReceiver(mBroadcastReceiver, intentFilter); } //注册广播后,要在相应位置记得销毁广播 //即在onPause() 中unregisterReceiver(mBroadcastReceiver) //当此Activity实例化时,会动态将MyBroadcastReceiver注册到系统中 //当此Activity销毁时,动态注册的MyBroadcastReceiver将不再接收到相应的广播。 @Override protected void onPause() { super.onPause(); //销毁在onResume()方法中的广播 unregisterReceiver(mBroadcastReceiver); } }

    注:

    • 动态广播最好在Activity的onResume()注册、onPause()注销。
    • 对于动态广播,有注册就必然得有注销,否则会导致内存泄露,重复注册、重复注销也不允许

    关于广播注册的更多问题关注参考博文的最后一篇。

    3、无序广播

    无序广播即为我们平时经常使用的广播,其主要是通过public abstract void sendBroadcast (Intent intent)方法进行发送,并通过intent传递数据。代码示例如下:

    Intent intent = new Intent();
    intent.setAction("com.xiazdong");
    intent.putExtra("name", "xiazdong");
    //发送无序广播
    this.sendBroadcast(intent);
    Toast.makeText(getApplicationContext(), "发送广播成功", Toast.LENGTH_SHORT).show();

           无序广播会被AndroidMainfest注册了的相应的感兴趣(intent-filter匹配)接收,且顺序是无序的(如果设置了 priority则优先级高的BroadCastReceiver会先收到)。如果发送广播时有相应的权限要求,BroadCastReceiver如果想要接收此广播,也需要有相应的权限。

        无序广播不可以被拦截,不可以被终止,不可以被修改,无序广播任何接收者只要匹配条件都可以接收到。如果想通过无序广播传递数据,则可以调用intent.putExtra方法传递, 接收者可通过intent.get...接收,不可通过getResultData接收。

    4、有序广播

    有序广播可以通过如下两个方法发送:

    public abstract void sendOrderedBroadcast (Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)

    public void sendOrderedBroadcast(Intent intent,
    String receiverPermission)

    下面具体讲解下一每个参数的含义:

    intent: 所有广播接收者的匹配规则

    receiverPermission:指定广播接收器的权限,一般自定义,不常用,可传null

    resultReceiver:指定一个最终的广播接收器,相当于finally功能,不论优先级,最后都要接收一次广播(),而这一次收到的广播为无序广播(可以在BroadcastReceiver中通过boolean orderedBroadcast = isOrderedBroadcast()方法验证),但是却可以通过getResultData等方法取得数据,这就是上面提到的特殊情况。即使前面的广播调用了abortBroadcast(),该接收器仍然可以接收到一个无序广播。


    scheduler:看英文没怎么看懂什么意思,一般传null。
    
    initialCode:指定一个code,一般传Activity.RESULT_OK。
    
    initialData:传一个字符串数据。对应的在BroadcastReceiver中通过String resultData = getResultData()取得数据;通过setResultData("优先级为3的setResultData的数据")修改数据,将数据传给下一个优先级较低的BroadcastReceiver;如果在优先级较高的BroadcastReceiver中没有使用setResultData修改数据,那么优先级较低的接收到的数据还是最原始的数据,即initialData的值。
    
    initialExtras:传一个Bundle对象,也就是可以传多种类型的数据。对应的在BroadcastReceiver中通过Bundle bundle = getResultExtras(false)取得Bundle对象,然后再通过bundle的各种get方法取得数据;通过setResultExtras()传入一个修改过的bundle,将该bundle对象传给下一个优先级较低的BroadcastReceiver;如果在优先级较高的BroadcastReceiver中没有使用setResultExtras修改数据,那么优先级较低的接收到的数据还是最原始的bundle对象,即initialExtras的值。
    发送一个无序广播如下:
    Intent intent = new Intent();
    intent.setAction("com.xiazdong");
    intent.putExtra("name", "xiazdong");
    //发送有序广播
    //this.sendOrderedBroadcast(intent,null);
    //通过 bundle传递数据
    Bundle bundle = new Bundle();
    bundle.putString(ORDER_DATA,"有序广播通过 bundle 传递数据");
    sendOrderedBroadcast(intent,null,null,mHandler, Activity.RESULT_OK,"发送一个有序广播",bundle);
    Toast.makeText(getApplicationContext(), "发送广播成功", Toast.LENGTH_SHORT).show();

    运行的log如下:
           image

    5、通过广播接收锁屏和解屏事件

    android 开发者可以通过注册接收器,监听手机的锁屏和解屏事件,自定义的接收器如下:
     private class ScreenBroadcastReceiver extends BroadcastReceiver {
            private String action = null;
    
            @Override
            public void onReceive(Context context, Intent intent) {
                action = intent.getAction();
                if (Intent.ACTION_SCREEN_ON.equals(action)) { // 开屏
                    mListener.onScreenOn();
                    Log.d(TAG, "onReceive: "+"开屏");
                } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 锁屏
                    mListener.onScreenOff();
                    Log.d(TAG, "onReceive: "+"锁屏");
                }
            }
        }
    同时通过该动态注册的方式注册广播,通过IntentFilter设置该接收器值接收锁屏和解屏事件而不会关心其它事件:
    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_SCREEN_ON);
    filter.addAction(Intent.ACTION_SCREEN_OFF);
    mContext.registerReceiver(mScreenReceiver, filter);
    这样,当锁屏和解屏事件发生时,onReceive回调就会被调用。

    参考:
    http://www.jianshu.com/p/0b3a7b35d76d
    http://blog.csdn.net/xiazdong/article/details/7768807/
    http://www.jianshu.com/p/ca3d87a4cdf3





  • 相关阅读:
    LinkButton(按钮)
    清理SharePoint 2010的SQL Server 2008 R2日志数据库的方法
    Sharepoint日志文件增长巨大的解决办法/缩小日志/删除日志
    PDF2SWF简单使用
    SharePoint 2010 网站备份还原简单介绍
    SolidWorks二次开发的研究
    基于VB语言对SolidWorks参数化设计的二次开发
    什么是PDM?
    SharePoint 2010配置PDF文件全文检索
    《博客园精华集--Sharepoint分册》第三轮结果(转)
  • 原文地址:https://www.cnblogs.com/NeilZhang/p/8367113.html
Copyright © 2020-2023  润新知