ACTION_BATTERY_CHANGED 疯狂放电

发布于 2024-12-08 02:19:06 字数 1335 浏览 1 评论 0原文

好的,所以我正在开发一个 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。这不是应该只在每减少一个百分比时就广播吗?它实际上导致我的整个启动器滞后,我不得不卸载它。那是不对的。

Okay, so I'm working on an AppWidget that checks the battery level and displays it on a TextView. My code looks like this:

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));
    }
}
}

And I'm getting concerned because as soon as I drop the widget onto my homescreen it begins firing off about 100 of those Log calls a second, saying it's receiving ACTION_BATTERY_CHANGED. Isn't this only supposed to be broadcast for each percent decrease? It actually caused my entire launcher to lag, I had to uninstall it. That can't be right.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

何处潇湘 2024-12-15 02:19:06

我的代码如下所示:

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

这不是应该只在每次下降百分比时广播吗?

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

如果您想实现此应用小部件,请不要像现在这样注册 ACTION_BATTERY_CHANGED。相反:

  • 允许用户通过 SharedPreference 选择轮询周期(例如,每分钟一次、每 15 分钟一次)。
  • 使用 AlarmManager 让您通过以下方式控制该轮询周期: a getBroadcast() PendingIntent
  • 在该 BroadcastReceiver 中,调用 registerReceiver() ACTION_BATTERY_CHANGED 但使用 null BroadcastReceiver,因为这将返回为该操作广播的最后一个 Intent (注意:为此,您仍然需要使用 getApplicationContext()
  • 使用 AppWidgetManager 来更新您的应用小部件实例,并从 Intent< 中提取电池电量。 /代码> 你在上一步中检索(注意:如果您将它们设置为相同,则无需迭代 ID - 使用采用 ComponentName< 的 updateAppWidget() /code> 作为参数)

这有几个优点:

  1. 您不关心 ACTION_BATTERY_CHANGED 的广播频率
  2. 用户可以通过执行这些检查来控制您消耗的电池电量(如果您保留轮询时间为一分钟或更长时间)
  3. 您的进程可以在轮询之间安全终止,从而降低用户使用任务杀手攻击您并半永久性地搞乱您的应用程序的可能性

My code looks like this:

You cannot register a BroadcastReceiver from another BroadcastReceiver and get reliable results. Android will terminate your process, because it doesn't think anything is running. The only way to listen for ACTION_BATTERY_CHANGED will be to register that receiver from an activity or a service.

Isn't this only supposed to be broadcast for each percent decrease?

Where do you see that documented? AFAIK, ACTION_BATTERY_CHANGED will be broadcast whenever the hardware feels like it. Also, bear in mind that other data changes within that Intent, such as temperature.

If you want to implement this app widget, do not register for ACTION_BATTERY_CHANGED the way you are. Instead:

  • Allow the user to choose a polling period via a SharedPreference (e.g., once a minute, once every 15 mintues)
  • Use AlarmManager to give you control on that polling period via a getBroadcast() PendingIntent
  • In that BroadcastReceiver, call registerReceiver() for ACTION_BATTERY_CHANGED but with a null BroadcastReceiver, as this will return to you the last Intent that was broadcast for that action (note: you will still need to use getApplicationContext() for this)
  • Use AppWidgetManager to update your app widget instances with the battery level pulled out of the Intent you retrieved in the preceding step (note: if you are setting them all to be the same, you do not need to iterate over the IDs -- use the updateAppWidget() that takes a ComponentName as a parameter)

This has several advantages:

  1. You do not care how often ACTION_BATTERY_CHANGED is broadcast
  2. The user gets to control how much battery you consume by doing these checks (should be negligible if you keep the polling period to a minute or more)
  3. Your process can be safely terminated in between polls, thereby making it less likely that users will attack you with task killers and semi-permanently mess up your app
酒儿 2024-12-15 02:19:06

好吧,您的 onUpdate 正在将自己的类注册为 Batteryinfo 意图的接收器。然后,第一个信息会立即触发此意图。
你的 onReceive 再次调用你的 onUpdate 。我们称之为循环。因此每秒 100 个日志......

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 ...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文