Android 四大组件详解(四) BroadcastReceiver

来源:互联网 发布:数组java定义 编辑:程序博客网 时间:2024/05/23 12:24

  首次接触到BroadCast是在这样的一个场景下,应用在注册的时候会发送验证码然后填写验证码,需求是在收到验证码的时候自动帮用户把验证码填写上去,提高用户体验。要实现这样的效果就首先要监听系统接收到信息的广播,然后对其做相应的处理,所以对BroadCast的相关知识梳理了一下,下面会从几个方面介绍BroadcastReceiver的使用:

1. 注册BroadCastReceiver ( 动态注册(Java代码中配置)跟静态注册(AndroidManifest.xml中配置) )

2. 自定义广播

3. BroadCastReceiver应用-获取收到信息内容并显示( 注册系统广播 )

4. Demo源码


一、注册广播

动态注册广播

比较简单的注册方式就是动态注册广播了,首先需要生成一个IntentFilter对象,然后设置它会拦截的ACTION(通过addAction方法),最后再调用registerReceiver方法就可以注册一个动态广播。下面以动态注册系统USB事件广播为例

        /**         * 动态注册系统广播         */        IntentFilter filter_system = new IntentFilter();        filter_system.addAction(USB_ACTION);        registerReceiver(new BroadcastReceiver() {            @Override            public void onReceive(Context context, Intent intent) {                Log.i(TAG, "接受到了系统广播消息!");                if (intent.getAction().equals(USB_ACTION)) {                    String message = "USB插入或者拔出";                    showToast(message);                }            }        }, filter_system);

其中USB_ACTION为一个字符串(也就是USB广播的Uri)

    private static final String USB_ACTION = Intent.ACTION_POWER_CONNECTED; //USE设备连接(系统广播)

showToast是一个显示Toast信息的方法

    /**     * 显示 Toast信息     * @param content 信息内容     */    private void showToast(String content){        Toast.makeText(MainActivity.this, content, Toast.LENGTH_SHORT).show();    }

只要注册了这个广播,就可以在USB插入的时候接受到相应的广播,然后就可以在BroadcastReceiver的onReceive中执行相应的操作。


静态注册广播

首先先要生成一个继承自BroadcastReceiver类(这里以 LowBatteryReceiver 接收低电量广播为例),LowBatteryReceiver 重写 onReceive方法 在里面执行相应的接受到低电量广播时应该要有的逻辑处理,然后在 AndroidManifest.xml 的 application标签 下注册一个receiver,具体看如下代码

LowBatteryReceiver类

package com.scut.jayme;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.util.Log;import android.widget.Toast;/** * 静态注册系统低电量广播 */public class LowBatteryReceiver extends BroadcastReceiver {    public LowBatteryReceiver(){}    @Override    public void onReceive(Context context, Intent intent) {        if(intent.getAction().equals(Intent.ACTION_BATTERY_LOW)){            Log.e("LowBatteryReceiver", "电量低提示");            Toast.makeText(context, "电量过低", Toast.LENGTH_SHORT).show();        }    }}

在manifest中application标签下注册receiver

        <receiver android:name=".LowBatteryReceiver">            <intent-filter>                <action android:name="ANDROID.INTENT.ACTION.BATTERY_LOW"/>            </intent-filter>        </receiver>

通过上面的操作就可以在系统发出低电量广播的时候执行到LowBatteryReceiver中onReceive中的处理逻辑代码。


二、自定义广播

自定义广播只要又一个唯一的ACTION就可以,然后发送广播跟接收广播都是根据这个ACTION来

private static final String DYNAMIC_ACTION = "com.scut.jayme.dynamic";

上面的是自定义的动态注册的自定义广播ACTION

然后就是发送自定义广播,只要利用一下Intent,然后调用Activity的sendBroadcast方法就可以发送自定义广播。

发送自定义广播

                                Intent intent = new Intent();                intent.setAction(DYNAMIC_ACTION);                intent.putExtra("message", "接受动态注册广播成功!");                sendBroadcast(intent);

动态注册自定义广播BroadReceiver

        /**         * 动态注册自定义广播         */        IntentFilter filter_dynamic = new IntentFilter();        filter_dynamic.addAction(DYNAMIC_ACTION);        registerReceiver(new BroadcastReceiver() {            @Override            public void onReceive(Context context, Intent intent) {                Log.i(TAG, "接受到了自定义广播消息!");                if (intent.getAction().equals(DYNAMIC_ACTION)) {                    String message = intent.getStringExtra("message");                    showToast(message);                }            }        }, filter_dynamic);

静态方式注册自定义BroadReceiver是跟上面一样,只不过要把manifest中receiver标签中action改为自定义的Uri。

三、BroadCastReceiver应用-获取收到信息内容并显示

首先我们要知道收到短信广播对应的ACTION

    private static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED"; //收到短信(系统广播)

然后就可以通过动态或者静态注册BroadcastReceiver的方式进行监听,获取到收到信息的ACTION后(也就是在onReceive中),从Intent中获取到信息的相关内容。

        /**         * 动态注册接收到信息的广播         */        IntentFilter smsFilter = new IntentFilter();        smsFilter.addAction(SMS_RECEIVED_ACTION);        registerReceiver(new BroadcastReceiver() {            @Override            public void onReceive(Context context, Intent intent) {                if (SMS_RECEIVED_ACTION.equals(intent.getAction())) {                    Log.i(TAG, "接收到信息!!!");                    SmsMessage[] smsMessages = getMessageFromIntent(intent);                    StringBuilder stringBuilder = new StringBuilder();                    if (null != smsMessages && smsMessages.length > 0) {                        for(SmsMessage smsMessage : smsMessages){                            stringBuilder.append("发送人: ");                            stringBuilder.append(smsMessage.getDisplayOriginatingAddress());                            stringBuilder.append("\n------短信内容-------\n");                            stringBuilder.append(smsMessage.getDisplayMessageBody());                        }                    }                    mSmsMessageTextView.setText(stringBuilder.toString());                }            }        }, smsFilter);

上面代码中从Intent中获取SmsMessage的方法

    /**     * 从接收到短信的广播的intent中获取到SmsMessage信息     * @param intent    接收到信息广播对应的intent     * @return          广播中携带的SmsMessage信息     */    public static SmsMessage[] getMessageFromIntent(Intent intent) {        Bundle bundle = intent.getExtras();        Object pdus[] = (Object[]) bundle.get("pdus");        SmsMessage[] smsMessages = new SmsMessage[pdus.length];        for (int i = 0; i < pdus.length; i++) {            byte[] byteData = (byte[]) pdus[i];            smsMessages[i]  = SmsMessage.createFromPdu(byteData);        }        return smsMessages;    }

其中mSmsMessageTextView是用来显示信息的TextView,后面layout文件中可以查到

这样我们就实现了监听收到信息的广播然后把信息内容跟发信人显示出来的功能。


四、Demo源码



MainActivity.java 源码

package com.scut.jayme;import android.app.Activity;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.os.Bundle;import android.telephony.SmsMessage;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends Activity implements View.OnClickListener{    private static final String TAG = "MainActivity";    private Button mSendStaticButton;    private Button mSendDynamicButton;    private TextView mSmsMessageTextView;    private static final String STATIC_ACTION = "com.scut.jayme.static";    private static final String DYNAMIC_ACTION = "com.scut.jayme.dynamic";    private static final String USB_ACTION = Intent.ACTION_POWER_CONNECTED; //USE设备连接(系统广播)    private static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED"; //收到短信(系统广播)    public MainActivity(){}    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        findViews();        initListeners();    }    @Override    protected void onStart() {        super.onStart();        registerBroadCast();    }    /**     * 初始化控件     */    private void findViews(){        mSendDynamicButton = (Button)findViewById(R.id.broadcast_btn_send_dynamic);        mSendStaticButton = (Button)findViewById(R.id.broadcast_btn_send_static);        mSmsMessageTextView = (TextView) findViewById(R.id.main_tv_sms_message);    }    /**     * 设置监听     */    private void initListeners(){        mSendStaticButton.setOnClickListener(this);        mSendDynamicButton.setOnClickListener(this);    }    /**     * 动态注册广播     */    private void registerBroadCast(){        /**         * 动态注册自定义广播         */        IntentFilter filter_dynamic = new IntentFilter();        filter_dynamic.addAction(DYNAMIC_ACTION);        registerReceiver(new BroadcastReceiver() {            @Override            public void onReceive(Context context, Intent intent) {                Log.i(TAG, "接受到了自定义广播消息!");                if (intent.getAction().equals(DYNAMIC_ACTION)) {                    String message = intent.getStringExtra("message");                    showToast(message);                }            }        }, filter_dynamic);        /**         * 动态注册系统广播         */        IntentFilter filter_system = new IntentFilter();        filter_system.addAction(USB_ACTION);        registerReceiver(new BroadcastReceiver() {            @Override            public void onReceive(Context context, Intent intent) {                Log.i(TAG, "接受到了系统广播消息!");                if (intent.getAction().equals(USB_ACTION)) {                    String message = "USB插入或者拔出";                    showToast(message);                }            }        }, filter_system);        /**         * 动态注册接收到信息的广播         */        IntentFilter smsFilter = new IntentFilter();        smsFilter.addAction(SMS_RECEIVED_ACTION);        registerReceiver(new BroadcastReceiver() {            @Override            public void onReceive(Context context, Intent intent) {                if (SMS_RECEIVED_ACTION.equals(intent.getAction())) {                    Log.i(TAG, "接收到信息!!!");                    SmsMessage[] smsMessages = getMessageFromIntent(intent);                    StringBuilder stringBuilder = new StringBuilder();                    if (null != smsMessages && smsMessages.length > 0) {                        for(SmsMessage smsMessage : smsMessages){                            stringBuilder.append("发送人: ");                            stringBuilder.append(smsMessage.getDisplayOriginatingAddress());                            stringBuilder.append("\n------短信内容-------\n");                            stringBuilder.append(smsMessage.getDisplayMessageBody());                        }                    }                    mSmsMessageTextView.setText(stringBuilder.toString());                }            }        }, smsFilter);    }    /**     * 从接收到短信的广播的intent中获取到SmsMessage信息     * @param intent    接收到信息广播对应的intent     * @return          广播中携带的SmsMessage信息     */    public static SmsMessage[] getMessageFromIntent(Intent intent) {        Bundle bundle = intent.getExtras();        Object pdus[] = (Object[]) bundle.get("pdus");        SmsMessage[] smsMessages = new SmsMessage[pdus.length];        for (int i = 0; i < pdus.length; i++) {            byte[] byteData = (byte[]) pdus[i];            smsMessages[i]  = SmsMessage.createFromPdu(byteData);        }        return smsMessages;    }    @Override    public void onClick(View v) {        Intent intent = new Intent();        switch (v.getId()){            case R.id.broadcast_btn_send_dynamic:                Log.i(TAG, "发送自定义动态注册广播消息!");                intent.setAction(DYNAMIC_ACTION);                intent.putExtra("message", "接受动态注册广播成功!");                sendBroadcast(intent);                break;            case R.id.broadcast_btn_send_static:                Log.i(TAG, "发送自定义静态注册广播消息!");                intent.setAction(STATIC_ACTION);                intent.putExtra("message", "接受静态注册广播成功!");                sendBroadcast(intent);                break;        }    }    /**     * 显示 Toast信息     * @param content 信息内容     */    private void showToast(String content){        Toast.makeText(MainActivity.this, content, Toast.LENGTH_SHORT).show();    }}

activity_main.xml layout文件

<?xml version="1.0" encoding="utf-8"?><ScrollView    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"><LinearLayout    android:layout_height="match_parent"    android:layout_width="match_parent"    android:gravity="center_horizontal"    android:orientation="vertical">    <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="发送自定义静态注册广播"        android:id="@+id/broadcast_btn_send_static"        android:layout_alignParentTop="true"        android:layout_alignParentLeft="true"        android:layout_alignParentStart="true" />    <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="发送自定义动态注册广播"        android:id="@+id/broadcast_btn_send_dynamic"        android:layout_below="@+id/broadcast_btn_send_static"        android:layout_alignParentLeft="true"        android:layout_alignParentStart="true" />    <TextView        android:id="@+id/main_tv_sms_message"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="50dp"        android:minHeight="100dp"        android:gravity="center"        android:background="#ecf0f1"        android:textColor="#11cd6e"        android:text="接受到信息将会显示在这里"/></LinearLayout></ScrollView>

AndroidManifest.xml源码

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.scut.jayme" >    <uses-permission android:name="android.permission.RECEIVE_SMS"/>    <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true"        android:theme="@style/AppTheme" >        <activity android:name=".MainActivity" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <receiver android:name=".StaticReceiver">            <intent-filter>                <action android:name="com.scut.jayme.static"/>            </intent-filter>        </receiver>        <receiver android:name=".LowBatteryReceiver">            <intent-filter>                <action android:name="ANDROID.INTENT.ACTION.BATTERY_LOW"/>            </intent-filter>        </receiver>    </application></manifest>



总结:

总体上讲了如何使用两种注册方式注册广播监听(动态注册跟静态注册),如何实现自定义的广播,跟利用广播实现监听收到信息的广播然后打印信息内容。以上的观点都是个人的一些理解,如果有不足或者错误之处还希望指出,谢谢!

如果需要下载项目源码的可以去我的资源页那里下载或者点击 demo源码




0 0