Android – как часто виджет обновления, но только когда он виден?

Я собираюсь создать виджет, который должен обновлять его содержимое каждую минуту (он показывает данные, относящиеся к времени).

Однако нет необходимости обновлять виджет, если он в настоящее время невидим, а это значит:

  • Экран выключен
  • Другое приложение запущено
  • Виджет размещается на другой (невидимой) вкладке главного экрана

Каков наилучший способ обновить только видимый виджет каждую минуту – без пробуждения устройства и ненужных вычислений? После того, как виджет становится видимым, допустимо небольшое отставание до обновления.

Solutions Collecting From Web of "Android – как часто виджет обновления, но только когда он виден?"

Чтобы не обновляться, когда экран выключен, используйте 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% 20Owner% 20Summary% 20Stars

  1. Вы можете спросить PowerManager о isScreenOn ()
  2. Вы можете зарегистрироваться для Intent ACTION_SCREEN_OFF / ACTION_SCREEN_ON и соответственно включить таймер.

Несмотря на то, что ответ выше, касающийся AlarmManager, верен, этого может быть недостаточно, так как я заметил, что многие телефоны также выдают сигналы тревоги, даже если они не относятся к типу * _WAKEUP. Это может произойти, если есть другие приложения, которые пробуждают устройство. И если он проснулся, он доставляет все ожидающие тревоги.

Я нашел это в проекте под названием 24clock в коде goole . Попробуйте Не обновлять виджет, пока пользователь находится вне дома:

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. Хотя это может не работать под другими сторонними пусковыми установками.

== Обновление ==

Несколько месяцев спустя у меня внезапно возникла мысль о том, как определить, отображается ли главный экран. Я положил его в свой блог , и я провел тест на своем Желании, и он отлично работает. Метод состоит в том, чтобы запросить Android для всех установленных пакетов, в котором один из них содержит способность «Launcher», а затем проверить, находится ли он на вершине запущенного стека. Если кто-нибудь проверил, пожалуйста, дайте мне знать результат, потому что у меня нет доступа к другим устройствам Android.

Принятый ответ от mbaird ударяет ноготь по голове. Предлагаемый 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() BroascastReceiver context.getApplicationContext().registerReceiver() чтобы зарегистрировать его. Это может быть обманом и, по крайней мере, в некоторых последующих версиях Android, может выйти из строя на стадии регистрации или, возможно, события просто не будут доставлены. Я закодировал для обработки этих случаев, но пока это работает. К сожалению, это, конечно, не удастся, если и когда приложение будет убито.

Другая возможность заключается в использовании isHomeScreenShowing() , как описано здесь , на который ссылается ответ xandy. Идеи, которые там, вероятно, могут быть оптимизированы путем кэширования сгенерированного списка установленных приложений CATEGORY_HOME и прослушивания ACTION_PACKAGE_ADDED / CHANGED / REMOVED, чтобы обновить его.

Моя стратегия:

  • Старайтесь избегать вызова (с помощью повторяющегося сигнала тревоги), когда он не отображается.
  • Когда вы вызываете, проверяйте состояние экрана и другие индикаторы видимости, прежде чем делать что-то дорогое.
  • Только тогда вызовите IntentService для обработки относительно дорогостоящей работы, которая включает постоянное сетевое соединение. Это необходимо для мониторинга состояния удаленной службы в ближайшем реальном времени.