zoukankan      html  css  js  c++  java
  • Android-BroadcastReceiver具体解释

    什么是Broadcast

    Broadcast即广播,在Android广播是很重要的功能。比如我们想在系统开机之后做某些事情、监控手机的电量、监控手机的网络状态等等。这些功能都须要用到广播。当然我们也能够自己定义广播。

    自己定义广播

    通常实现一个简单的自己定义广播能够通过例如以下几个步骤:

    • 创建一个类继承android.content.BroadcastReceiver,并实现onReceive方法
    • 在AndroidManifest.xml中注冊广播
    • 通过Context的registerReceiver等方法注冊广播
    • 调用Context的sendBroadcast等方法发送广播,在onReceive方法中处理广播
    • 调用Context的unregisterReceiver等方法注销广播

    我们通过代码来解释一下上面的步骤:

    1.创建一个类继承android.content.BroadcastReceiver。并实现onReceive方法

    package com.mark.broadcastreciver;
    
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.util.Log;
    
    /**
     * 创建一个自己定义广播接收者须要继承android.content.BroadcastReceiver,
     * 并实现onReceive方法就可以。
     */
    public class MyReceiver extends BroadcastReceiver {
    
        private final static String TAG = MyReceiver.class.getSimpleName();
    
        public MyReceiver() {
        }
    
        /**
         * 当接收到广播之后会调用此方法
         * @param context 上下文对象
         * @param intent 调用sendBroadcast(intent)传入的Intent实例,当中包括了action、和其它附带信息
         */
        @Override
        public void onReceive(Context context, Intent intent) {
            // 获取msg相应的数据
            String msg = intent.getStringExtra("msg");
            // 打印msg数据
            Log.i(TAG, "msg = " + msg);
            // 打印action字符串
            Log.i(TAG, "action = " + intent.getAction());
        }
    }

    2.在AndroidManifest.xml中注冊广播

    <application>
        <receiver android:name=".MyReceiver">
        </receiver>
    </application>

    3.通过Context的registerReceiver等方法注冊广播
    4.调用Context的sendBroadcast等方法发送广播。在onReceive方法中处理广播
    5.调用Context的unregisterReceiver等方法注销广播

    package com.mark.broadcastreciver;
    
    import android.content.BroadcastReceiver;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    
    public class MainActivity extends AppCompatActivity {
    
        BroadcastReceiver registerReceiver;
        IntentFilter intentFilter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // 创建BroadcastReceiver实例
            registerReceiver = new MyReceiver();
            // 创建IntentFilter。指定其action为com.mark.broadcast.receiver,这个能够自己定义
            intentFilter = new IntentFilter("com.mark.broadcast.receiver");
            // 注冊广播将registerReceiver与intentFilter关联,
            // registerReceiver能够接收到action为com.mark.broadcast.receiver的广播
            registerReceiver(registerReceiver, intentFilter);
    
            findViewById(R.id.btnRegister).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // 发送广播
    
                    // 创建Intent。指定其action为com.mark.broadcast.receiver,与registerReceiver关联的action一致
                    Intent intent = new Intent("com.mark.broadcast.receiver");
                    // 指定要发送的信息
                    intent.putExtra("msg", "Hello, a new message.");
                    sendBroadcast(intent);
                }
            });
    
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unregisterReceiver(registerReceiver);
        }
    }

    通过上述的步骤我们就实现了一个自己定义广播,当我们点击Button在控制台中能够看到例如以下信息:

    04-13 17:12:28.591 16882-16882/com.mark.broadcastreciver I/MyReceiver: msg = Hello, a new message.
    04-13 17:12:28.591 16882-16882/com.mark.broadcastreciver I/MyReceiver: action = com.mark.broadcast.receiver

    注冊广播

    注冊广播的方式有两种:静态注冊和动态注冊。

    静态注冊

    这样的方法是在配置AndroidManifest.xml配置文件里注冊,通过这样的方式注冊的广播为常驻型广播,也就是说假设应用程序关闭了。有相应事件触发。程序还是会被系统自己主动调用执行。

    比如:

    <!-- 在配置文件里注冊BroadcastReceiver能够匹配的Intent -->
    <receiver android:name=“.MyReceiver">
        <intent-filter>
            </action>
            <action android:name=“com.mark.broadcast.reveiver”/>
            <category android:name="android.intent.category.DEFAULT"></category>
        </intent-filter>
    </receiver>

    动态注冊

    这样的方法是通过代码在.Java文件里进行注冊。通过这样的方式注冊的广播为很驻型广播,即它会尾随Activity的生命周期,所以在Activity结束前我们须要调用unregisterReceiver(receiver)方法移除它。比如:

    // 创建BroadcastReceiver实例
    registerReceiver = new MyReceiver();
     // 创建IntentFilter,指定其action为com.mark.broadcast.receiver。这个能够自己定义
     intentFilter = new IntentFilter("com.mark.broadcast.receiver");
     // 注冊广播将registerReceiver与intentFilter关联。
     // registerReceiver能够接收到action为com.mark.broadcast.receiver的广播
    registerReceiver(registerReceiver, intentFilter);

    注意:假设我们在Activity中注冊了BroadcastReceiver,当这个Activity销毁的时候要主动撤销注冊否则会出现异常。方法例如以下:

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

    广播的类型

    Broadcast的类型有两种:普通广播和有序广播。

    Normal broadcasts (普通广播)

    Normal broadcasts是全然异步的能够同一时间被全部的接收者接收到。消息的传递效率比較高。但缺点是接收者不能讲接收的消息的处理信息传递给下一个接收者也不能停止消息的传播。多个普通广播设置同样的IntentFilter,则先注冊的先收到广播。

    Ordered broadcasts (有序广播)

    Ordered broadcasts的接收者依照一定的优先级进行消息的接收。

    如:A,B,C的优先级依次减少。那么消息先传递给A,在传递给B,最后传递给C。

    优先级别声明在中,取值为[-1000,1000]数值越大优先级别越高。优先级也可通过filter.setPriority(10)方式设置。

    另外Ordered broadcasts的接收者能够通过abortBroadcast()的方式取消广播的传播,也能够通过setResultData和setResultExtras方法将处理的结果存入到Broadcast中,传递给下一个接收者。

    然后,下一个接收者通过getResultData()和getResultExtras(true)接收高优先级的接收者存入的数据。

    比如:

    <receiver
        android:name=".FirstReceiver">
    
        <intent-filter
            android:priority="999">
            <action android:name="com.mark.broadcast.receiver" />
    
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>
    <receiver android:name=".MyReceiver" >
        <intent-filter
            android:priority="1000">
            <action android:name="com.mark.broadcast.receiver" />
    
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>

    如上两个receiver我们分别设置为priority为999,和1000。及时MyReceiver是后注冊的,可是其优先级比FirstReceiver高,则MyReceiver会先处理广播。

    sendOrderedBroadcast 发送有序广播

    sendOrderedBroadcast(intent, receiverPermission)方法接收两个參数。比普通广播的发送方式多了一个receiverPermission參数。这是一个String类型的參数,代表具有这个权限的Receiver才干处理收到此广播。假设为null则表明不要求接受者声明指定权限。我们来看一下详细的操作。

    首先我们要自己定义一个权限。比如:

    <permission
        android:name="com.permissions.MY_BROADCAST_RECEIVER"
        android:protectionLevel="normal" />

    然后我们要是当前的程序具有此权限:比如:

    <uses-permission android:name="com.permissions.MY_BROADCAST_RECEIVER" />

    这样当前程序就拥有此权限了。

    我们在发送有序广播是指定其权限为com.permissions.MY_BROADCAST_RECEIVER。注意拼写不要有错误,最好是复制过来。

    发送广播例如以下:

    // 创建Intent,指定其action为com.mark.broadcast.receiver,与registerReceiver关联的action一致
    Intent intent = new Intent("com.mark.broadcast.receiver");
    // 指定要发送的信息
    intent.putExtra("msg", "Hello, a new message.");
    sendOrderedBroadcast(intent, "com.permissions.MY_BROADCAST_RECEIVER");

    这样我们发送广播,并指定其权限为com.permissions.MY_BROADCAST_RECEIVER,由于当前的程序已经使用了此权限了。所以当前程序中的receiver是能够接收并处理此条广播的。否则不能接收此条广播。此处的权限体现了android对安全性的重视。

    sendStickyBroadcast 粘性广播

    粘性广播与其它的广播方式最大的不同在于“异步”,也就是说当一个粘性广播发出去后,能够没有Receiver进行处理。可是这个广播还会一直存在,假如过了一段时间之后有Receiver注冊了此广播,则此Receiver还是能够处理这条广播的。可是细心的朋友们能够看到sendStickyBroadcast的一系列重载方法的參数中并没有上面提到的receiverPermission參数,这也将导致粘性广播在安全性上存在问题。

    所以在API Level 21 上sendStickyBroadcast方法被标记为deprecated。也就是不建议我们使用粘性广播了。由于在安全性和其它方面粘性广播存在许多缺陷。这里我们也就不在重点讨论了。

    总结

    这里我们对广播及广播接收者进行一个简单的总结以及在使用时的一些注意事项。

    1.发送广播的方法都是ContextWrapper中的方法。而Activity、Service都是ContextWrapper的子类,所以在它们中都能够发送和注冊广播
    2.onReceive方法中不能做耗时操作,否则也会导致ANR
    3.依据实际开发须要。尽可能为广播添加权限
    4.尽可能避免使用粘性广播
    5.有序广播的优先级为【-1000 ~ 1000】,数值越大。优先级越高

    上述描写叙述和某些观点可能不是正解,仅供參考,欢迎大家指正、批评。

  • 相关阅读:
    引入包时“”与<>的区别
    Scanners
    一个SQLite数据库的LIKE查询和IN集合查询的代码实例
    @synchronized线程同步互斥锁
    makeKeyAndVisible
    NSString 数字判断
    UILabel UITextField UITextView
    (转载)JAVA SE6.0 中使用SplashScreen
    转帖(http://hi.baidu.com/johnehuang/blog/item/e1e96782a4b04e97f703a6dc.html)
    ce
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/7261282.html
Copyright © 2011-2022 走看看