Android编程权威指南——broadcast intent


前言

本章,我们继续从两个方面完善PhotoGallery应用。首先,让应用轮询新结果并在有所发现时及时通知用户,即使用户重启设备后还没有打开过应用。其次,保证用户在使用应用时不出现新结果通知。借此升级,我们将学习如何监听系统发送的broadcast intent,以及如何使用broadcast receiver
处理它们。此外,我们会在应用运行时动态发送与接收broadcast intent。最后,还会使用有序broadcast判断应用是否在前台运行。


一 普通 intent 和 broadcast intent

  1. Android设备中,各种事件时有发生。WiFi时有时无,软件装卸,电话接打,短信收发,等等。许多系统组件需要掌握这些动态。为满足这样的需求,Android提供了broadcast intent组件。
    broadcast intent的工作原理类似之前学过的intent,唯一不同的是broadcast intent可同时被多个叫作broadcast receiver的组件接收。
  2. 作为公共API的一部分,无论什么时候,activity和服务应该都可以响应隐式intent。如果是用作私有API,用用显式intent差不多也够了。这样看来,还需要broadcast intent的话,理由只有一个:它可以发送给多个接收者。虽然broadcast receiver也能响应显式intent,但几乎没人这么用,因为显式intent只允许有一个接收者。

二 接收系统 broadcast:重启后唤醒

PhotoGallery应用的后台定时器虽然能用,但还不够完美。如果用户重启了设备,定时器就会失效。设备重启后,那些持续运行的应用通常也需要重启。监听带有BOOT_COMPLETED操作的broadcast intent,可知道设备是否已完成启动。无论何时,只要打开设备,系统就会发送一个BOOT_COMPLETED broadcast intent。要想监听它,可以创建并登记一个standalone broadcast receiver。

1 创建并登记 standalone receiver

standalone receiver是一个在manifest配置文件中声明的broadcast receiver。即便应用进程已消亡,standalone receiver也可以被激活。(稍后还会学习到可以同fragment或activity的生命周期绑定
的dynamic receiver。)与服务和activity一样,broadcast receiver必须在系统中登记后才能用。如果不登记,系统就不知道该向哪里发送intent。自然,broadcast receiver的onReceive(…)方法也就不能按预期被调用了。要登记broadcast receiver,首先要创建它。创建一个StartupReceiver新类,继承android.content.BroadcastReceiver类,如代码清单29-1所示。
代码清单29-1 第一个broadcast receiver(StartupReceiver.java)

public class StartupReceiver extends BroadcastReceiver{
   
 private static final String TAG = "StartupReceiver";
 @Override
 public void onReceive(Context context, Intent intent) {
   
 Log.i(TAG, "Received broadcast intent: " + intent.getAction());
 }
} 

与服务和activity一样,broadcast receiver是接收intent的组件。当有intent发送给StartupReceiver时,它的onReceive(…)方法会被调用。
打开AndroidManifest.xml配置文件,登记上StartupReceiver,如代码清单29-2所示。
代码清单29-2 在manifest文件中添加receiver(AndroidManifest.xml)

<manifest ...>
 <uses-permission android:name="android.permission.INTERNET"/> 
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
 <application
 ...>
 <activity
 android:name=".PhotoGalleryActivity"
 android:label="@string/app_name">
 ...
 </activity>
 <service android:name=".PollService"/>
 <receiver android:name=".StartupReceiver">
 <intent-filter>
 <action android:name="android.intent.action.BOOT_COMPLETED"/>
 </intent-filter>
 </receiver>
 </application>
</manifest> 

签并在其中包含相应的intent-filter。StartupReceiver会监听BOOT_COMPLETED操作,而该操作也需要配置使用权限。因此,还需要添加一个相应的uses-permission标签。设备重启后,StartupReceiver的onReceive(…)方法会被调用吗?现在就来验证。首先,运行更新版PhotoGallery应用。然后,关闭设备。如果是物理设备,按电源键关机。如果是模拟器,关机的最简方法是直接退出模拟器应用。打开设备。如果是物理设备,按电源键开机。如果是模拟器,要么重新运行应用,要么使用AVD Manager启动应用,但要保证使用的是刚关掉的那个模拟器。
现在,选择Tools → Android → Android Device Monitor菜单项打开Android Device Monitor。点击Android Device Monitor的Devices选项卡中的设备。(如果看不到设备列表,请尝试插拔USB设备或重启模拟器。)在Android Device Monitor窗口中,以Received broadcast intent关键字搜素LogCat输出。在LogCat中,可以看到表明receiver运行的日志。但如果在设备标签页查看设备,则可能看不到任何PhotoGallery进程。这是因为进程一运行完broadcast receiver,就随即消亡了。(使用Logcat输出测试receiver的运行不一定总会成功,使用模拟器更有可能。按照上述步骤操作,如果看不到log日志,建议多试几次。还是不行的话,那就暂时放弃,等学习到优化通知
消息时,就会有更可靠的办法来验证receiver的运行了。)

2 使用 receiver

broadcast receiver的生命非常短暂,因而难以有所作为。例如,我们无法使用任何异步API或登记任何监听器,因为一旦onReceive(Context, Intent)方法运行完,receiver就不存在了。
onReceive(Context, Intent)方法同样运行在主线程上,因此不能在该方法内做一些费时费力的事情,如网络连接或数据的永久存储等。
然而,这并不代表receiver一无用处。一些便利型任务就非常适合它,比如启动activity或服务(不需要等返回结果),以及系统重启后重置定时运行的定时器。receiver需要知道定时器的启停状态。为存储它的状态,在QueryPreferences类中添加一个preference常量和两个便利方法,如代码清单29-3所示。
代码清单29-3 添加定时器状态preference(QueryPreferences.java)

public class QueryPreferences {
   
 private static final String PREF_SEARCH_QUERY = "searchQuery";
 private static final String PREF_LAST_RESULT_ID = "lastResultId";
 private static final String PREF_IS_ALARM_ON = "isAlarmOn";
 ...
 public static void setLastResultId(Context context, String lastResultId) {
   
 ...
 }
 public static boolean isAlarmOn(Context context) {
   
 return PreferenceManager.getDefaultSharedPreferences(context)
 .getBoolean(PREF_IS_ALARM_ON, false);
 }
 public static void setAl
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值