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

wshunli
2018-03-12 / 0 评论 / 101 阅读 / 正在检测是否收录...

《第一行代码》读书笔记 -- 应用组件之 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

0

评论 (0)

取消