【问题标题】:Android BroadcastReceiver not updating WidgetAndroid BroadcastReceiver不更新小部件
【发布时间】:2016-11-18 10:57:43
【问题描述】:

我尝试了所有在 stackoverflow 上找到的方法,但没有一个有效。

我正在开发一个电池监控应用程序,它包含一些用于显示信息的小部件。我使用一个名为BatteryUpdateReceiver 的通用接收器来收听ACTION_BATTERY_CHANGED 事件。我使用这个接收器来更新一个显示当前电池电量的小部件。但由于某些原因,它不会更新小部件。我尝试了很多方法,但无法弄清楚出了什么问题。我的代码如下。

BatteryUpdateReceiver.java

public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
            Log.i(TAG, "Receiver ACTION_BATTERY_CHANGED fired");

            RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
                    R.layout.widget);

            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context.getApplicationContext());
            ComponentName thisWidget = new ComponentName(context.getApplicationContext(), BatteryWidget.class);
            int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
            for (int i=0; i < allWidgetIds.length; i++) {
                Log.i(TAG, "WID ID: " + allWidgetIds[i]);
                appWidgetManager.updateAppWidget(allWidgetIds[i], remoteViews);
            }
        }
    }

BatteryWidget.java

public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);

        Log.i(TAG, "onUpdate: ");

        int currentLevel = calculateBatteryLevel(context);
        if (batteryChanged(currentLevel)) {
            batteryLevel = currentLevel;
            Log.i(TAG, "onUpdate: Battery level changed");
        }
        updateViews(context);
    }

    private boolean batteryChanged(int currentLevelLeft) {
        return (batteryLevel != currentLevelLeft);
    }

    private int calculateBatteryLevel(Context context) {
        Log.i(TAG, "calculateBatteryLevel: ");

        Intent batteryIntent = context.getApplicationContext().registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

        int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
        int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
        return level * 100 / scale;
    }

    private void updateViews(Context context) {
        Log.i(TAG, "updateViews: ");

        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
        views.setTextViewText(R.id.batteryText, batteryLevel + "%");

        ComponentName componentName = new ComponentName(context, BatteryWidget.class);
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
        appWidgetManager.updateAppWidget(componentName, views);
    }

AndroidManifest.xml

    <receiver android:name=".lib.receivers.BatteryUpdateReceiver" android:enabled="true" />

    <receiver android:name=".widget.BatteryWidget" android:label="@string/app_name" >
         <intent-filter>
              <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
         </intent-filter>
         <meta-data
                    android:name="android.appwidget.provider" android:resource="@xml/batterywidgetinfo" />
   </receiver>

我在设备启动时使用服务注册 BatteryUpdateReceiver。

IntentFilter filterBattery = new IntentFilter();
filterBattery.addAction(Intent.ACTION_BATTERY_CHANGED);
this.mBatteryStatusReceiver = new BatteryUpdateReceiver();
getApplicationContext().registerReceiver(this.mBatteryStatusReceiver, filterBattery);
Log.i(TAG, "Receiver ACTION_BATTERY_CHANGED registered by Service");

我可以确认 BatteryUpdateReceiver 有效,因为它记录了小部件 ID。此外,如果我将接收器放在BatteryWidget 中,那么小部件就会更新。有人可以告诉我我在这里想念什么吗?我知道我可以覆盖BatteryWidget 类中的onReceive() 方法。但是我怎样才能以这种方式存档呢?

谢谢!

【问题讨论】:

    标签: java android broadcastreceiver android-widget


    【解决方案1】:

    你应该从你的接收者发送一个ACTION_APPWIDGET_UPDATE广播,而不是直接调用updateAppWidget()

    类似这样的:

    @Override
    public void onReceive(Context context, Intent intent) {
        AppWidgetManager widgetManager = AppWidgetManager.getInstance(getApplicationContext());
        int[] appWidgetIds = widgetManager.getAppWidgetIds(new ComponentName(context, BatteryWidget.class));
    
        Intent updateIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE, null, getApplicationContext(), BatteryWidget.class);
        updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
    
        sendBroadcast(updateIntent);
    }
    

    【讨论】:

      【解决方案2】:

      在同一问题上花费了无数小时后,我终于找到了解决方案。 @earthw0rmjim 的回答把我推到了一半,但我意识到你不能从 Kotlin 广播接收器调用 sendBroadcast()。您必须调用广播上下文和应用程序上下文才能发送广播。

      对于任何希望在 Kotlin 中实现相同目标的人来说,这是对我有用的代码。在我的例子中,MyWidgetProvider 是我用来处理主屏幕小部件的 AppWidgetProvider 类。

      override fun onReceive(context: Context, intent: Intent) {
          val widgetManager = AppWidgetManager.getInstance(context)
          
          val appWidgetIds = widgetManager.getAppWidgetIds(ComponentName(context,MyWidgetProvider::class.java))
      
          val updateIntent = Intent(
              AppWidgetManager.ACTION_APPWIDGET_UPDATE,
              null,
              context,
              MyWidgetProvider::class.java
          )
          
          updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds)
      
          context.applicationContext.sendBroadcast(updateIntent)
      }
      

      【讨论】:

        猜你喜欢
        • 2012-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-29
        • 1970-01-01
        • 2011-05-03
        • 2011-02-14
        相关资源
        最近更新 更多