我将创建需要每分钟更新其内容的小部件(它显示与时间相关的数据)。
但是,如果小部件当前不可见,则无需更新小部件,这意味着:
- 屏幕已关闭
- 另一个应用程序正在运行
- 小部件放置在另一个(不可见的)主屏幕选项卡上
每分钟只更新可见小部件的最佳方法是什么 - 无需唤醒设备或进行不必要的计算?小部件变得可见后,更新前的小延迟是可以接受的。
我将创建需要每分钟更新其内容的小部件(它显示与时间相关的数据)。
但是,如果小部件当前不可见,则无需更新小部件,这意味着:
每分钟只更新可见小部件的最佳方法是什么 - 无需唤醒设备或进行不必要的计算?小部件变得可见后,更新前的小延迟是可以接受的。
为了避免在屏幕关闭时更新,请使用AlarmManager安排一个不会唤醒手机的重复警报。
您在问题中的其他两个要点是不可能的。无法检测您的小部件是否位于当前不可见的主屏幕上,也无法确定是否正在运行隐藏主屏幕的应用程序。我已经在http://b.android.com上提交了一张票,要求将此功能添加到 Android。如果您想主演它,它将帮助它获得优先权:http ://code.google.com/p/android/issues/detail?id=5529&q=reporter:mark.r.baird&colspec=ID%20Type%20Status% 20所有者%20总结%20星
尽管上面关于 AlarmManager 的答案是正确的,但这可能还不够,因为我观察到许多电话也会发出警报,即使它们不是 *_WAKEUP 类型。如果安装了其他正在唤醒设备的应用程序,则可能会发生这种情况。如果它一旦醒来,它就会提供所有待处理的警报。
我在goole 代码中名为 24clock 的项目下找到了这个。当用户不在家时,它会尝试不更新小部件:
ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> runningTasks = am.getRunningTasks(2);
for (RunningTaskInfo t : runningTasks) {
if (t != null && t.numRunning > 0) {
ComponentName cn = t.baseActivity;
if (cn == null) continue;
String clz = cn.getClassName();
String pkg = cn.getPackageName();
// TODO make this configurable
if (pkg != null && pkg.startsWith("com.android.launcher")) {
return true;
}
return false;
}
}
这可能是您要求 2 的答案。虽然它可能无法在其他 3rd 方启动器下工作。
== 更新 ==
几个月后,我突然想到如何检测主屏幕是否正在显示。我把它放在我的博客上,我对我的 Desire 进行了测试,它运行良好。方法是在Android中查询所有已安装的包,其中一个包含“Launcher”能力,然后检查它是否在运行堆栈的顶部。如果有人测试过,也请告诉我结果,因为我无法访问其他 Android 设备。
mbaird 接受的答案一针见血。建议的onVisivilityChange()
方法,如果实施,应涵盖上述所有情况。
与此同时,对于某些类型的小部件来说,这仍然是一个真正的问题。jom 引入了注册以接收 ACTION_SCREEN_OFF/ACTION_SCREEN_ON 意图的可能性。这很有用,因为依靠非唤醒重复警报是不够的,因为其他服务会导致唤醒。这很困难,因为无法通过 AndroidManifest.xml 订阅此类操作,并且不允许 AppWidgetProvider 调用context.registerReceiver()
。这些问题在其他几个 StackOverflow 问题中进行了讨论,包括Listening for ACTION_SCREEN_OFF、android.intent.action.SCREEN_ON 不能作为接收器意图过滤器和Android - 如何接收广播意图 ACTION_SCREEN_ON/OFF?.
当然,不幸的是,如果应用程序被终止,这将失败。BroascastReceiver
通过创建一个附属实例并使用context.getApplicationContext().registerReceiver()
它来注册它,我已成功订阅小部件中的 ACTION_SCREEN_OFF/ACTION_SCREEN_ON 意图。这很可能是作弊,至少在随后的某些 Android 版本中,可能会在注册阶段失败,或者事件可能根本无法交付。我已经编写了代码来处理这些情况,但现在它可以工作了。
另一种可能性是使用一种isHomeScreenShowing()
方法,如此处所述,由xandy的回答引用。CATEGORY_HOME
通过缓存生成的已安装应用程序列表并收听 ACTION_PACKAGE_ADDED/CHANGED/REMOVED 广播以更新它,可以优化那里的想法。
我的策略是:
IntentService
来处理相对昂贵的工作,其中包括一个持久的网络连接。这对于近乎实时地监控远程服务的状态是必要的。