Vajira Lasantha Vajira Lasantha - 1 month ago 6
Android Question

Android BroadcastReceiver not updating Widget [FIXED]

UPDATE: Fixed using @user13 answer.

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

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

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(),

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

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

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(, batteryLevel + "%");

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


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

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

I register BatteryUpdateReceiver using a service when device boot up.

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

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



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

Something like this:

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