ACTION_BATTERY_CHANGED стреляет как сумасшедший - PullRequest
12 голосов
/ 02 октября 2011

Хорошо, я работаю над AppWidget, который проверяет уровень заряда батареи и отображает его в TextView. Мой код выглядит так:

public class BattWidget extends AppWidgetProvider {

private RemoteViews views = new RemoteViews("com.nickavv.cleanwidgets", R.layout.battlayout);

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int appWidgetIds[]) {
    final int N = appWidgetIds.length;
    context.getApplicationContext().registerReceiver(this,new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
    for (int i = 0; i < N; i++) {
        int appWidgetId = appWidgetIds[i];
        appWidgetManager.updateAppWidget(appWidgetId, views);
    }
}

@Override
public void onReceive(Context context, Intent intent) {
    super.onReceive(context, intent);
    Log.d("onReceive", "Received intent " + intent);
    if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
        Integer level = intent.getIntExtra("level", -1);
        views.setTextViewText(R.id.batteryText, level+"%");
        AppWidgetManager myAWM = AppWidgetManager.getInstance(context);
        ComponentName cn = new ComponentName(context, AirWidget.class);
        onUpdate(context, myAWM, myAWM.getAppWidgetIds(cn));
    }
}
}

И меня это беспокоит, потому что, как только я уронил виджет на домашний экран, он начинает запускать около 100 вызовов журнала в секунду, говоря, что получает ACTION_BATTERY_CHANGED. Разве это не должно транслироваться только для каждого процентного снижения? Это фактически вызвало зависание всего моего модуля запуска, мне пришлось удалить его. Это не может быть правдой.

Ответы [ 2 ]

23 голосов
/ 02 октября 2011

Мой код выглядит так:

Вы не можете зарегистрировать BroadcastReceiver от другого BroadcastReceiver и получить достоверные результаты. Android прекратит ваш процесс, потому что он не думает, что что-то работает. Единственный способ прослушать ACTION_BATTERY_CHANGED - это зарегистрировать этого получателя из активности или службы.

Разве это не должно транслироваться только для каждого уменьшения процента?

Где вы видите это документально? AFAIK, ACTION_BATTERY_CHANGED будет транслироваться всякий раз, когда аппаратное обеспечение чувствует, что это нравится. Также имейте в виду, что в этом Intent изменяются и другие данные, например, температура.

Если вы хотите реализовать этот виджет приложения, не регистрируйтесь на ACTION_BATTERY_CHANGED таким, какой вы есть. Вместо этого:

  • Разрешить пользователю выбирать период опроса с помощью SharedPreference (например, раз в минуту, раз в 15 минут)
  • Используйте AlarmManager, чтобы дать вам контроль над этим периодом опроса через getBroadcast() PendingIntent
  • В этом BroadcastReceiver, позвоните registerReceiver() для ACTION_BATTERY_CHANGED , но с null BroadcastReceiver , так как это вернет вам последний Intent, который был передан для этого действия (примечание : вам все равно нужно будет использовать getApplicationContext() для этого)
  • Используйте AppWidgetManager, чтобы обновить экземпляры виджета вашего приложения с уровнем заряда батареи, извлеченным из Intent, который вы получили на предыдущем шаге (примечание: если вы устанавливаете их все одинаково, вам не нужно повторять поверх идентификаторов - используйте updateAppWidget(), который принимает ComponentName в качестве параметра)

Это имеет несколько преимуществ:

  1. Вам все равно, как часто ACTION_BATTERY_CHANGED транслируется
  2. Пользователь получает возможность контролировать, сколько батареи вы потребляете, выполняя эти проверки (должно быть незначительным, если вы держите период опроса до минуты или более)
  3. Ваш процесс может быть безопасно остановлен между опросами, благодаря чему снижается вероятность того, что пользователи будут атаковать вас с помощью программ-убийц и почти навсегда испортят ваше приложение
0 голосов
/ 31 мая 2017

Что ж, ваш onUpdate регистрирует свой собственный класс в качестве получателя для намерения batteryinfo. Это намерение тогда немедленно вызвано для первой информации. Ваш onReceive снова вызывает ваш onUpdate. Мы называем это петлей. Следовательно 100 журналов в секунду ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...