BroadcastReceiver 使用详解

BroadcastReceiver作为Android四大组件之一,即广播。广播分为发送者和接收者。要想使用广播,首先必须先注册广播接收者,然后接着发送广播。最后在接收者中处理广播。
其中广播接收者需继承BroadcastReceiver并重写onReceive来实现,onReceive就是最终处理广播的方法。

注意:Android中规定了BroadCastReceiver不能处理复杂长时间的逻辑操作,如果在onReceive方法在10s内没法执行完毕,则系统会视之为未响应状态,可能会报ANR错误。可以将这些耗时操作放在Service中开辟子线程去执行。

BroadcastReceiver分以下几个来写:

  1. 静态注册
  2. 动态注册
  3. 有序广播
  4. 本地广播
  5. 图解BroadcastReceiver源码处理过程

静态注册广播

静态广播注册:在AndroidManifest.xml中注册BroadcastReceiver。
首先定一个广播接收者StaticReceiver.java

/**
 * <pre>
 *     author: chmj
 *     time  : 2017/8/23
 *     desc  : 广播接收者,需要继承BroadcastReceiver,并且重写onReceive方法。其中intent参数就是发送的时候的Intent。
 * </pre>
 */

public class StaticReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //获取广播的数据.
        String msg = intent.getStringExtra("test");
        LogHelper.i("静态广播接收消息....." + msg);
    }
}

接着在在AndroidManifest中注册:

 <receiver android:name=".activity.broadcastreceiver.staticregist.StaticReceiver">
    <intent-filter>
        <action android:name="com.broadcast.static"/>
    </intent-filter>
</receiver>

注意这里的action,这个属性是这个广播的标志。在我们发送广播的时候会加入广播标志,在接收的时候只有改广播标志对上的才能接收。

在Activity中发送广播。

findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        /**
         * 1、通过sendBroadcast将广播的Intent发送出去,Intent可以携带数据.
         * 2、setAction表示为intent设置上一个action,即给这个广播添加一个标志,
         * 后续只有和这个标志匹配的广播接收者才可以收到。
         */
        Intent intent = new Intent();

        //广播标志. 在静态注册中即在在AndroidManifest中需拦截这个action。
        intent.setAction("com.broadcast.static");
        //数据.
        intent.putExtra("test","test data 123");
        //发送广播
        sendBroadcast(intent);
    }
});

动态注册广播

动态注册,即在代码中注册,用到IntentFileter这个类包装Receiver然后通过registerReceiver去注册。动态注册可以反注册,静态注册的广播不能取消,一直存在到app退出。一般动态注册在onCreate中注册。在onDestroy中进行反注册.

同样定一个广播接收者DynamicReceiver.java

/**
 * <pre>
 *     author: chmj
 *     time  : 2017/8/23
 *     desc  : 广播接收者,需要继承BroadcastReceiver,并且重写onReceive方法。其中intent参数就是发送的时候的Intent。
 * </pre>
 */

public class DynamicReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //获取广播的数据.
        String msg = intent.getStringExtra("test");
        LogHelper.i("动态广播接收消息....." + msg);
    }
}

动态注册即在代码中注册,我们一般在onCreate里面注册。通过IntentFileter这个类包装Receiver然后通过registerReceiver去注册。

private DynamicReceiver mDynamicReceiver;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.test_common_broad_cast_context);
    //包装Receiver
    IntentFilter intentFilter = new IntentFilter();
    //添加标志
    intentFilter.addAction("com.broadcast.dynamic");
    mDynamicReceiver = new DynamicReceiver();
    //动态注册广播
    registerReceiver(mDynamicReceiver,intentFilter);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    unregisterReceiver(mDynamicReceiver);
}

注册完,然后发送广播。

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

        //广播标志. 在静态注册中即在在AndroidManifest中需拦截这个action。
        intent.setAction("com.broadcast.dynamic");
        //数据.
        intent.putExtra("test","test data 123");
        //发送广播
        sendBroadcast(intent);
    }
});

有序广播

上面那两种广播发送方式都是无序的,有序广播通过sendOrderedBroadcast发送,而接受者Receiver的Action是同一个,只不过他们通过priority属性进行优先级的判定。priority越大优先级越高,优先级最高的会第一个拦截广播并处理,然后才会往下传递.

首先我们定义3个广播接收者:

FirstReceiver

public class FirstReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        String msg = intent.getStringExtra("msg");
        LogHelper.i("This is the First msg from Activity " + msg);

        /**
         * 接着发送消息,action是一样的,下面的Receiver根据priority优先级来判断由谁来接收.
         *
         */
        setResultData("FirstReceiver send msg ");
        setResultCode(100);
    }
}

接收到广播处理之后,要想在传数据给下一个广播接收者使用,就用setResultData,setResultExtras等方法。而下一个广播接收者要想获取上一个广播接收者传过来的信息,就用getResultData,getResultExtras等。

SecondReceiver

public class SecondReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //获取上一个广播传过来的信息
        String msg = getResultData();
        //获取code
        int code = getResultCode();

        /**
         * getResultExtras:参数为true的时候如果Bundle是空的,则会创建一个Bundle返回,如果是false,则直接返回Bundle对象.
         */
        Bundle bundle1 = getResultExtras(false);
        Bundle bundle2 = getResultExtras(true);

        LogHelper.i("----idOrderBroadcast----" + isOrderedBroadcast());
        LogHelper.i("---bundle1--" + bundle1 + "  bundle2  " + bundle2);
        LogHelper.i("---msg--" + msg + "  code  " + code);

        Bundle bundle = new Bundle();
        bundle.putString("test","444444");
        setResultExtras(bundle);

    }
}

这里getResultExtras:参数为true的时候如果Bundle是空的,则会创建一个Bundle返回,如果是false,则直接返回Bundle对象.

ThirdReveiver

public class ThirdReveiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle bundle = getResultExtras(false);
        String msg = bundle.getString("test");

        LogHelper.i("ThirdReveiver msg " + msg);
    }
}

注册三个广播接收者

<receiver
    android:name=".activity.broadcastreceiver.orderregist.FirstReceiver">
    <intent-filter android:priority="300">
        <action android:name="com.broadcast.order"/>
    </intent-filter>

</receiver>

<receiver
    android:name=".activity.broadcastreceiver.orderregist.SecondReceiver">
    <intent-filter android:priority="200">
        <action android:name="com.broadcast.order"/>
    </intent-filter>

</receiver>

<receiver
    android:name=".activity.broadcastreceiver.orderregist.ThirdReveiver">
    <intent-filter android:priority="100">
        <action android:name="com.broadcast.order"/>
    </intent-filter>

</receiver>

这里注意priority这个参数,priority值越高越优先,在这边FirstReceiver优先级最高,则从activity发出来的广播,最先被它拦截处理。

发送广播通过sendOrderedBroadcast;

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

        //广播标志. 在静态注册中即在在AndroidManifest中需拦截这个action。
        intent.setAction("com.broadcast.order");
        //数据.
        intent.putExtra("test","test data 123");
        //发送广播
        sendOrderedBroadcast(intent,null);
    }
});

本地广播

本地广播,通过LocalBroadcastManager来注册,不需要考虑安全问题,因为它只在应用内部有效。是安全的广播。

同样定一个广播接收者DynamicReceiver

public class DynamicReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //获取广播的数据.
        String msg = intent.getStringExtra("test");
        LogHelper.i("动态广播接收消息....." + msg);
    }
}

注册的时候需通过LocalBroadcastManager来注册。

private LocalBroadcastManager mLocalBroadcastManager;
private LocalReceiver mLocalReceiver;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.test_common_broad_cast_context);
    mLocalBroadcastManager = LocalBroadcastManager.getInstance(mContext);
    mLocalReceiver = new LocalReceiver();
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("com.broadcast.local");

    //本地广播注册.
    mLocalBroadcastManager.registerReceiver(mLocalReceiver,intentFilter);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    mLocalBroadcastManager.unregisterReceiver(mLocalReceiver);
}

发送广播也是通过LocalBroadcastManager来发送。

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

        intent.setAction("com.broadcast.local");
        //数据.
        intent.putExtra("msg","test data 123");
        //发送本地广播需要通过LocalBroadcastManager来发送.
        mLocalBroadcastManager.sendBroadcast(intent);
    }
});

用三张图来看看源码处理广播的过程。

注册过程

BroadcastReceiver注册.jpg

发送过程

BroadcastReceiver发送流程.jpg

处理过程

BroadcastReceiver处理流程.jpg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,045评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,114评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,120评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,902评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,828评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,132评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,590评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,258评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,408评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,335评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,385评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,068评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,660评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,747评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,967评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,406评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,970评论 2 341

推荐阅读更多精彩内容