简体   繁体   中英

Android BroadcastReceiver not updating Widget

Fist of all I tried all the methods which I found on stackoverflow and non of them worked.

I'm developing a battery monitoring app and it contains some widgets to display information. I use a common receiver called BatteryUpdateReceiver to listen to ACTION_BATTERY_CHANGED event. I use this receiver to update a widget which shows current battery level. But for some reasons it does not update the widget. I tried many ways but could not figure out whats's wrong. My code is given below.

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>

I register BatteryUpdateReceiver using a service when device boot up.

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

I can confirm that BatteryUpdateReceiver works because it logs widget id. Also if I will put a receiver inside BatteryWidget , then the widget gets updated. Can someone tell me what am I missing here? I know I can override onReceive() method in BatteryWidget class. But how can I archive it this way?

Thanks!

You should send an ACTION_APPWIDGET_UPDATE broadcast from your receiver, rather than calling updateAppWidget() directly.

Something like this:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM