《第一行代码》读书笔记(四)

Author Avatar
wshunli 3月 12, 2018
  • 在其它设备中阅读本文章

《第一行代码》读书笔记 — 应用组件之 BroadcastReceiver

《第一行代码》读书笔记(一)— 平台架构 (第1章)
《第一行代码》读书笔记(二)— 应用组件之 Activity (第2、4章)
《第一行代码》读书笔记(三)— 应用组件之 Service (第10章)
《第一行代码》读书笔记(四)— 应用组件之 BroadcastReceiver (第5章)
《第一行代码》读书笔记(五)— 应用组件之 ContentProvider (第7章)
《第一行代码》读书笔记(六)— 数据存储方案 (第6章)
《第一行代码》读书笔记(七)— 多媒体资源 (第8章)
《第一行代码》读书笔记(八)— 网络编程 (第9章)

第5章 全局大喇叭

BroadcastReceiver,广播接收者,它是一个系统全局的监听器,用于监听系统全局的 Broadcast 消息,所以它可以很方便的进行系统组件之间的通信。

BroadcastReceiver 属于系统级的监听器,它拥有自己的进程,只要存在与之匹配的 Broadcast 被以 Intent 的形式发送出来,BroadcastReceiver 就会被激活。

广播的使用场景:
(1)同一 APP 具有多进程的不同组件之间的信息通信。
(2)不同 APP 之间的组件之间信息通信。

Android中的广播分为两种类型,标准广播和有序广播

(1)标准广播
标准广播是一种完全异步执行的广播,在广播发出后所有的广播接收器会在同一时间接收到这条广播,之间没有先后顺序,效率比较高,且无法被截断。
(2)有序广播
有序广播是一种同步执行的广播,在广播发出后同一时刻只有一个广播接收器能够接收到, 优先级高的广播接收器会优先接收,当优先级高的广播接收器的 onReceiver() 方法运行结束后,广播才会继续传递,且前面的广播接收器可以选择截断广播,这样后面的广播接收器就无法接收到这条广播了。

接收系统广播

动态注册

动态注册 BroadcastReceiver 是在代码中定义并设置好一个 IntentFilter 对象,然后在需要注册的地方调用 Context.registerReceiver() 方法,调用 Context.unregisterReceiver() 方法取消注册,此时就不需要在清单文件中注册。

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private IntentFilter intentFilter;
    private NetWorkBroadcastReceiver netWorkBroadcastReceiver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        intentFilter = new IntentFilter();
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");

        netWorkBroadcastReceiver = new NetWorkBroadcastReceiver();
        registerReceiver(netWorkBroadcastReceiver, intentFilter);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(netWorkBroadcastReceiver);
    }

    class NetWorkBroadcastReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "onReceive: "+"network changes");
        }
    }
}

动态注册广播接收器可以自由地控制注册与注销,但是必须程序启动之后才能收到广播,因为注册的逻辑是写在 onCreate() 方法中。

静态注册

静态注册即在清单文件中为 BroadcastReceiver 进行注册,使用 < receiver > 标签声明,并在标签内用 < intent-filter > 标签设置过滤器。

这种形式的 BroadcastReceiver 的生命周期伴随着整个应用,如果这种方式处理的是系统广播,那么不管应用是否在运行,该广播接收器都能接收到该广播。

public class BootCompleteReceiver extends BroadcastReceiver {
    private static final String TAG = "BootCompleteReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "onReceive: "+"Boot Complete");
    }
}

manifest 文件中声明:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<receiver
    android:name=".BootCompleteReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

发送自定义广播

前面是同通过广播接收器接收系统广播,接下来是发送自定义广播。

首先注册广播接收器,这里选择静态注册方法:

public class CustomReceiver extends BroadcastReceiver {
    private static final String TAG = "CustomReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "onReceive: "+"接收到自定义广播");
    }
}

然后在 manifest 中声明 广播接收器:

<receiver
    android:name=".CustomReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="com.wshunli.broadcastreceiverdemo.CUSTOM_BROADCAST" />
    </intent-filter>
</receiver>

发送标准广播

发送标准广播调用的是 sendBroadcast(Intent) 方法

sendBroadcast(new Intent("com.wshunli.broadcastreceiverdemo.CUSTOM_BROADCAST"));

发送有序广播

发送有序广播调用的是 sendOrderedBroadcast(Intent , String) 方法,String 参数值在自定义权限时使用。

sendOrderedBroadcast(new Intent("com.wshunli.broadcastreceiverdemo.CUSTOM_BROADCAST"),null);

Receiver 接收广播时不仅因为 “priority” 属性存在先后顺序,且 Receiver 之间也能够传递数据。

此外,BroadcastReceiver 也能调用 abortBroadcast() 方法截断广播,这样低优先级的广播接收器就无法接收到广播了。

使用本地广播

之前发送和接收到的广播全都是属于系统全局广播,即发出的广播可以被其他应用接收到,而且也可以接收到其他应用发送出的广播,这样可能会有不安全因素。

因此,在某些情况下可以采用本地广播机制,使用这个机制发出的广播只能在应用内部进行传递,而且广播接收器也只能接收本应用内自身发出的广播。

本地广播是使用 LocalBroadcastManager 来对广播进行管理。

首先,创建一个 BroadcastReceiver 用于接收本地广播:

class LocalReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "onReceive: " + "LocalReceiver");
    }
}

然后使用 LocalBroadcastManager 注册或者注销 广播接收器:

private IntentFilter intentFilter;
private LocalReceiver localReceiver;
private LocalBroadcastManager localBroadcastManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    intentFilter = new IntentFilter();
    intentFilter.addAction("com.wshunli.broadcastreceiverdemo.LOCAL_BROADCAST");
    localReceiver = new LocalReceiver();

    localBroadcastManager = LocalBroadcastManager.getInstance(this);
    localBroadcastManager.registerReceiver(localReceiver, intentFilter);
}
@Override
protected void onDestroy() {
    super.onDestroy();
    localBroadcastManager.unregisterReceiver(localReceiver);
}

最后通过 LocalBroadcastManager 发送本地广播:

localBroadcastManager.sendBroadcast(new Intent("com.wshunli.broadcastreceiverdemo.LOCAL_BROADCAST"));

需要注意的是,本地广播是无法通过静态注册的方式来接收的,因为静态注册广播主要是为了在程序未启动的情况下也能接收广播,而本地广播是应用自己发送的,此时应用肯定是启动的了。

本地广播的优势:
(1)发送的广播不会离开我们的应用程序,所以不必担心机密数据泄露;
(2)其他程序的广播也无法发送到我们程序内部,不用担心会有安全漏洞;
(3)本地广播比发送系统全局广播将更加有效。

参考资料
1、Broadcasts | Android Developers
https://developer.android.com/guide/components/broadcasts.html
2、Android之BroadcastReceiver | 吴小龙同學
http://wuxiaolong.me/2015/11/03/BroadcastReceiver/
3、Android BroadcastReceiver使用详解 - 简书
https://www.jianshu.com/p/f348f6d7fe59
4、Android深入四大组件(四)广播的注册、发送和接收过程 | 刘望舒的博客
http://liuwangshu.cn/framework/component/4-broadcastreceiver.html

如果本文对您有所帮助,且您手头还很宽裕,欢迎打赏赞助我,以支付网站服务器和域名费用。 https://paypal.me/wshunli 您的鼓励与支持是我更新的最大动力,我会铭记于心,倾于博客。
本文链接:https://www.wshunli.com/posts/4c8f7dec.html