我将创建需要每分钟更新其内容的小部件(它显示与时间相关的数据)。

但是,如果小部件当前不可见,则无需更新它,这意味着:

  • 屏幕已关闭
  • 另一个应用程序正在运行
  • 小部件被放置在另一个(不可见的)主屏幕选项卡上

每分钟仅更新可见小部件的最佳方法是什么 - 无需唤醒设备,也不进行不必要的计算?小部件变得可见后,更新之前的小延迟是可以接受的。

有帮助吗?

解决方案

为了防止屏幕关闭时更新,请使用 报警管理器 安排一个不会唤醒手机的重复闹钟。

您问题中的其他两个要点是不可能的。无法检测您的小部件是否位于当前不可见的主屏幕上,也无法确定隐藏主屏幕的应用程序是否正在运行。我已提交票证 http://b.android.com 请求将此功能添加到 Android 中。如果您想为其加注星标,这将有助于它获得优先权: http://code.google.com/p/android/issues/detail?id=5529&q=reporter:mark.r.baird&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars

其他提示

  1. 您可以向 PowerManager 询问 isScreenOn()
  2. 您可以注册意图 ACTION_SCREEN_OFF/ACTION_SCREEN_ON 并相应地打开/关闭计时器。

尽管上面关于 AlarmManager 的答案是正确的,但这可能还不够,因为我观察到许多手机也会发出警报,即使它们不是 *_WAKEUP 类型。如果安装了其他正在唤醒设备的应用程序,则可能会发生这种情况。如果它一旦唤醒,它就会发送所有待处理的警报。

我在一个名为的项目下找到了这个 古尔代码中的24时钟. 。它尝试在用户离开家时不更新小部件:

    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 的答案。尽管它可能无法在其他第三方启动器下工作。

==更新==

几个月后,我突然想到如何检测主屏幕是否显示。我把它放在我的 博客, ,我对我的 Desire 进行了测试,效果很好。方法是查询Android所有已安装的软件包,其中包含“Launcher”能力的软件包,然后检查其是否位于运行堆栈的顶部。如果有人测试过,请也告诉我结果,因为我无法访问其他 Android 设备。

姆贝尔德接受的答案一针见血。拟议的 onVisivilityChange() 方法如果实施,应该涵盖上述所有情况。

与此同时,这对于某些类型的小部件来说仍然是一个真正的问题。jom 引入了注册接收 ACTION_SCREEN_OFF/ACTION_SCREEN_ON 意图的可能性。这很有用,因为依赖非唤醒重复警报是不够的,因为其他服务会导致唤醒。这很困难,因为无法通过 AndroidManifest.xml 订阅此类操作,并且不允许调用 AppWidgetProvider context.registerReceiver(). 。这些问题在其他几个 StackOverflow 问题中进行了讨论,包括 监听 ACTION_SCREEN_OFF, android.intent.action.SCREEN_ON 不能用作接收器意图过滤器Android - 如何接收广播意图ACTION_SCREEN_ON/OFF?.

我已通过创建子公司成功订阅小部件中的 ACTION_SCREEN_OFF/ACTION_SCREEN_ON 意图 BroascastReceiver 实例并使用 context.getApplicationContext().registerReceiver() 来注册它。这很可能是作弊行为,至少在后续的某些 Android 版本中,可能会在注册阶段失败,或者事件可能根本不会被传递。我已经编写了代码来处理这些情况,但目前它可以工作。 当然,不幸的是,如果应用程序被终止,这将会失败。

另一种可能性是使用 isHomeScreenShowing() 一种方法,如上所述 这里, ,由 xandy 的回答引用。那里的想法可能可以通过缓存已安装的生成列表来优化 CATEGORY_HOME 应用程序并监听 ACTION_PACKAGE_ADDED/CHANGED/REMOVED 广播来更新它。

我的策略是:

  • 尽量避免在看不见时被呼叫(通过重复警报)。
  • 调用时,在执行任何昂贵操作之前检查屏幕状态和其他可见性指示器。
  • 然后才调用 IntentService 处理相对昂贵的工作,其中包括持久的网络连接。这对于近实时监控远程服务的状态是必要的。
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top