12

好的,所以我正在开发一个 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 个这样的 Log 调用,并说它正在接收 ACTION_BATTERY_CHANGED。这不应该只为每减少一个百分比而广播吗?它实际上导致我的整个启动器滞后,我不得不卸载它。这不可能。

4

2 回答 2

24

我的代码如下所示:

您无法BroadcastReceiver从另一个注册一个BroadcastReceiver并获得可靠的结果。Android 将终止您的进程,因为它认为没有任何东西在运行。监听的唯一方法ACTION_BATTERY_CHANGED是从活动或服务中注册该接收器。

这不应该只为每减少一个百分比而广播吗?

你在哪里看到记录的?AFAIK,ACTION_BATTERY_CHANGED只要有硬件感觉就会广播。另外,请记住,其他数据会在其中发生变化Intent,例如温度。

如果您想实现此应用程序小部件,请不要ACTION_BATTERY_CHANGED按您的方式注册。反而:

  • 允许用户通过 a 选择轮询周期SharedPreference(例如,每分钟一次,每 15 分钟一次)
  • 用于AlarmManager让您通过getBroadcast() PendingIntent
  • 在那BroadcastReceiver,调用但使用registerReceiver()BroadcastReceiver 因为这将返回给您为该操作广播的最后一个(注意:您仍然需要使用它)ACTION_BATTERY_CHANGED nullIntentgetApplicationContext()
  • 使用AppWidgetManagerIntent您在上一步中检索到的电池电量来更新您的应用小部件实例(注意:如果您将它们都设置为相同,则不需要遍历 ID -updateAppWidget()使用aComponentName作为参数)

这有几个优点:

  1. 你不在乎多久ACTION_BATTERY_CHANGED播出一次
  2. 用户可以通过执行这些检查来控制您消耗多少电池(如果您将轮询时间保持在一分钟或更长时间,则应该可以忽略不计)
  3. 您的进程可以在两次轮询之间安全终止,从而降低用户使用任务杀手攻击您并半永久性地弄乱您的应用程序的可能性
于 2011-10-02T12:25:45.750 回答
0

Well, your onUpdate is registering its own class as receiver for the batteryinfo intent. This intent is then immediately triggered for the first info. Your onReceive is calling your onUpdate again. We call this a loop. Hence the 100 logs a second ...

于 2017-05-31T01:02:13.363 回答