我问你答-简述 Android 广播机制

以下内容是对官方文档的理解翻译而来

广播消息

应用可以接收系统或其他应用发出的广播消息,同样也能给其他应用发送消息,这类似于消息订阅模式。例如系统启动或者设备充电时就会触发发送相关的广播消息。应用可以自定义一些广播消息,发送给对这个消息感兴趣的应用。

应用需要注册接收器,这样当消息被发送出来,系统就能自动路由消息给这些应用了,这就是说的订阅过程。

通常来说,广播机制可用于跨应用或者应用内任意位置的消息传递,不过这也不能滥用,并且接收回调里也不能随便什么事情都做,不然会影响用户体验和系统性能。

广播消息是通过 Intent 来包装的,action 属性用来指明什么广播,其他附带的信息可通过 bundle 传递。

接收广播消息

前面说到,想要接收消息首先要注册(即订阅操作),有两种方式可以实现注册:

  • 通过 Manifest 定义接收器

    通过继承 BroadcastReceiver 实现 MyBroadcastReceiver,并在 Manifest 文件里声明

public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        //处理接收逻辑,注意这里不能做耗时操作,至多 10s 处理完
    }
}

    
        
    

这种方式声明的接收器会在应用被安装时就注册上,特殊点在于即使应用没有启动,若是接收到了广播消息,这是应用就能被系统启动并接收到广播消息。

  • 通过代码中动态注册接收器

首先同样需要继承 BroadcastReceiver 实现自定义接收器,然后通过代码实现注册及注销逻辑。

BroadcastReceiver receiver = new MyBroadcastReceiver();
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
this.registerReceiver(receiver, filter);

注意这种方式要在不需要广播消息的时候注销接收器

this.unregisterReceiver(receiver);

原因在于这个广播接收器的生命周期依赖于主动注册的宿主(有可能是 Activity,有可能是 Application),所以要注意使用完就注销。

此外,当接收器正在接收处理消息时,其所在的应用进程将不会被系统回收,此时的优先级等级是最高的。之后,还是有可能由于资源不足被回收的。基于这个原因(onReceive() 方法做完后,进程优先级就降低了),就不能在 onReceive() 方法里启动线程,而应该通过 goAsync() 或者启动一个 JobService 来去做一些耗时任务。

发送广播消息

系统提供了 3 种方式来发送广播:

  • sendOrderedBroadcast(Intent, String)

    发送有序广播,这个消息一次只被一个接收器接收(谁先接收到,可通过配置优先级来决定,如果优先级相同,那么顺序就随机了),随后接收器有权中断或者继续让下一个接收器接收。

  • sendBroadcast(Intent)

    普通方式,消息发出后真正的广播给所有接收器。

  • LocalBroadcastManager.sendBroadcast

    本地应用内的广播发送,通常不想其他应用收到这个消息的话,就可以用这种方式。这种方式更安全,更有效。

代码样例:

Intent intent = new Intent();
intent.setAction("com.my.broadcast.MY_NOTIFICATIONS");
intent.putExtra("data", "data");
sendBroadcast(intent);

发送和接收广播消息时,也可带上权限限定。
即发送广播消息时带上权限入参,同时应用也要申请相应权限,才能发送广播。
接收方同样要申请相应权限,并在注册接收器时显示指定权限。

版本兼容

Android 9
如果应用运行在 Android 9 或更高版本,NETWORK_STATE_CHANGED_ACTION 广播将不再包含用户信息,例如 SSIDs, BSSIDs, 连接信息等,取而代之的是调用 getConnectionInfo() 方法。

Android 8.0
如果应用的目标版本是 Android 8.0 或更高版本,我们将不能在 Manifest 中定义一些隐式广播接收器(那些没有明确指明应用的广播),不过仍然可以通过代码注册实现。意思就是更推荐代码动态注册广播接收器。

Android 7.0
如果应用的目标版本是 Android 7.0 或更高版本,将不能再发送 ACTION_NEW_PICTURE, ACTION_NEW_VIDEO,这两个系统广播。CONNECTIVITY_ACTION 必须通过代码注册的方式注册广播接收器,不能再用 Manifest 来注册了。

你可能感兴趣的:(我问你答-简述 Android 广播机制)