broadcast基础知识介绍

通过命令行执行adb shell am broadcast发送广播通知。

adb shell am broadcast 后面的参数有:

[-a <ACTION>]
[-d <DATA_URI>]
[-t <MIME_TYPE>] 
[-c <CATEGORY> [-c <CATEGORY>] ...] 
[-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...] 
[--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...] 
[-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...] 
[-n <COMPONENT>]
[-f <FLAGS>] [<URI>]

例如:adb shell am broadcast -a com.android.test --es test_string "this is test string" --ei test_int 100 --ez test_boolean true

------------------------------------

Android广播的分类:

1、 普通广播:这种广播几乎同时传递给各个处理器去处理。
2、 有序广播:这种广播在处理器端的处理顺序是按照处理器的不同优先级来区分的,高优先级的处理器会优先截获这个消息,并且可以将这个消息删除。
     静态接收器在AndroidManifest.xml中定义接收器优先级,动态接收器则通过intentfilter.setPriority()来设置
     优先级数字范围为-1000~1000, 判断是否是有序广播使用isOrderedBroadcast(),销毁广播使用函数abortBroadcast()
3、 粘性消息:粘性消息在发送后就一直存在于系统的消息容器里面,等待对应的处理器去处理,如果暂时没有处理器处理这个消息则一直在消息容器里面处于等待状态。

    sticky broadcast在任意时间发送都可以,也就是只发送一次就可以了,看源码说发送完会驻留在sticky cache中

Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter)
Intent     registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)
Returns: The first sticky intent found that matches filter, or null if there are none.

//粘性广播:检测耳机是否存在的例子
if (mHeadsetPlugUnplugBroadcastReceiver == null) mHeadsetPlugUnplugBroadcastReceiver = new HeadsetPlugUnplugBroadcastReceiver(); // sticky intent - use last value if exists, otherwise no headset Intent intent = registerReceiver(mHeadsetPlugUnplugBroadcastReceiver, new IntentFilter( Intent.ACTION_HEADSET_PLUG)); if (intent != null) { mHeadsetPlugUnplugBroadcastReceiver.onReceive(this, intent); } else { wiredHeadsetIsOn(false); }

Intent intent = registerReceiver(null, new IntentFilter( Intent.ACTION_HEADSET_PLUG)); 这样写也可以收到该粘性广播。

粘性广播可以被移除 ,我们可以接收到 广播后调用 removeStickyBroadcast(intent);

 

注意:

<1>普通广播和粘性广播不可被截获,而有序广播是可以被终止的,广播被终止后,优先级低的接收器就收不到广播了;
<2>普通广播和有序广播BroadcastReceiver 中的单个onReceiver()10s内必须处理完本次接受的处理过程,否则系统会认为该程序无响应(可能会ANR)。所以不推荐在onReceiver()中处理耗时的事情;
<3>onReceiver()中不推荐启动子线程来处理这个耗时的事情,因为BroadcastReceiver可能会很快就结束了,此时子线程可能还没处理完。由于该线程不含有任何活动组件,如果内存紧张,那么该线程可能被强行结束;
<4>比较推荐的办法是可以考虑启动一个Service来处理。

onReceive方法必须在10秒内完成,如果没有完成,则抛“Application No Response”当广播接收者onReceive方法需要执行很长时间时,最好将此耗时工作通过Intent发送给Service,由Service完成,并且不能使用子线程解决,因为BroadcastReceiver是接收到广播后才创建的,并且生命周期很短,因此子线程可能在没有执行完就已经被杀死了。

public void onReceive(Context context,Intent intent){
    Intent intent = new Intent(context, “com.example.xx”);
    context.startService(intent);
}

 

处理器的注册:  
1、 在代码中用函数代码动态的方式注册。动态注册的处理器必须用代码动态的销毁,每次用来处理消息的就一个实例对象

IntentFilter intentfilter = new IntentFilter();
   //为IntentFilter对象添加Action,也相当于在AndroidManifest.xml定义一样,定义的目的是过滤器只许当安卓的操作系统产生短消息的事件咱
//们自定义的这个BroadcastReceiver类才能来接收短消息这个广播,我们才能进行代码的进一步处理
intentfilter.addAction("org.crazyit.action.CRAZY_BROADCAST");
intentfilter.setPriority(100);//可以不设置广播优先级
//注册广播接收器  registerReceiver(receiver, intentfilter);//receiver = new BroadcastReceiver(){~~~~~~~};

2、 在配置文件AndroidManifest.xml里面静态注册。静态注册有个特点,那就是一旦注册就会一直存在于系统里面。

而且当处理该消息时,生成该处理器的实例,处理完以后会杀死该线程。所以里面放static变量是不合理的。

public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent){
        Toast.makeText(context , "接收到的Intent的Action为:"
            + intent.getAction() 
            + "\n消息内容是:" + intent.getStringExtra("msg") //如果有msg
            , 5000)
            .show();
    }
}
//AndroidManifest.xml
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".BroadcastMain"
                  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="20"> //这里设置优先级为20 可以不用设置
                <action android:name="org.crazyit.action.CRAZY_BROADCAST" />
            </intent-filter>        
        </receiver>
    </application>

 广播的发送

普通广播:

// 创建Intent对象
Intent intent = new Intent();
// 设置Intent的Action属性
intent.setAction("org.crazyit.action.CRAZY_BROADCAST");
//intent.putExtra("msg" , "简单的消息");
// 发送广播
sendBroadcast(intent);

有序广播:

// 创建Intent对象
Intent intent = new Intent();
intent.setAction("org.crazyit.action.CRAZY_BROADCAST");
//intent.putExtra("msg" , "简单的消息");
// 发送有序广播
sendOrderedBroadcast(intent , null);

优先接收到Broadcast的Receiver可通过setResultExtras(Bundle)方法将处理结果存入Broadcast中,
下一个Receiver 通过 Bundle bundle=getResultExtras(true)方法获取上一个 Receiver传来的数据

 粘性广播:

Intent intent=new Intent();
intent.setAction(“org.crazyit.action.CRAZY_BROADCAST”); 
sendStickyBroadCast(intent);

发送粘性广播还需要发送粘性广播的权限:<uses-permission android:name="android.permission.BROADCAST_STICKY" />

-----------------------------------------------------------------------------------------------

广播监听器注册多次时,仅且仅有一次有效, 广播只能主线程收,可以在子线程注册。

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("org.crazyit.action.CRAZY_BROADCAST");        
        registerReceiver(mReceiver, intentFilter);
        registerReceiver(mReceiver, intentFilter);
        registerReceiver(mReceiver, intentFilter);

这里注册了3次,实际上是只收到一次。

 

posted @ 2014-12-08 20:01  牧 天  阅读(1017)  评论(0)    收藏  举报