Подтвердить что ты не робот

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

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

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

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

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

Ответ 3

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

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

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

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

Ответ 4

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

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

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

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