ACTION_BATTERY_CHANGED стреляет как сумасшедший
Итак, я работаю над 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 ответа
Мой код выглядит так:
Вы не можете зарегистрировать BroadcastReceiver
От другого BroadcastReceiver
и получить достоверные результаты. Android остановит ваш процесс, потому что он не думает, что что-то работает. Единственный способ слушать ACTION_BATTERY_CHANGED
будет зарегистрировать этого получателя от деятельности или службы.
Разве это не должно быть транслировано только на каждый процент снижения?
Где вы видите это документально? НАСКОЛЬКО МНЕ ИЗВЕСТНО, 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
как параметр)
Это имеет несколько преимуществ:
- Вам все равно, как часто
ACTION_BATTERY_CHANGED
транслируется - С помощью этих проверок пользователь получает возможность контролировать, сколько батареи вы потребляете (должно быть незначительным, если вы держите период опроса до минуты или более)
- Ваш процесс может быть безопасно остановлен между опросами, что снижает вероятность того, что пользователи будут атаковать вас убийцами задач и наполовину навредить вашему приложению
Ну, ваш onUpdate регистрирует свой собственный класс в качестве получателя для намерения batteryinfo. Это намерение тогда немедленно вызвано для первой информации. Ваш onReceive снова вызывает ваш onUpdate. Мы называем это петлей. Следовательно 100 журналов в секунду...