BroadcastReceiver 使用详解

2017-10-30  本文已影响158人  johnnycmj

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
上一篇下一篇

猜你喜欢

热点阅读