CodeWarrior
CodeWarrior

Reputation: 5176

onUpdate() not getting called for a widget?

I wanna make a CountDown timer sort of Widget. I want it to update every second. Below is my code. onUpdate() isn't getting called at all except once in the begining. Kindly point me to the issue. Thanks in advance.

JAVA Code

public class MainActivity extends AppWidgetProvider {

    private boolean isTimeComplete = false;
    private int days, hours, minutes, seconds;
    private PendingIntent pendingIntent;

    @Override
    public void onEnabled(Context context) {
        super.onEnabled(context);

        AlarmManager alarmManager = (AlarmManager) context
                .getSystemService(Context.ALARM_SERVICE);

        Intent alarm = new Intent(context, MainActivity.class);
        pendingIntent = PendingIntent.getService(context, 0, alarm,
                    PendingIntent.FLAG_CANCEL_CURRENT);
        alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis(),
                1000, pendingIntent);
        ComponentName thisWidget = new ComponentName(context,
                MainActivity.class);
        AppWidgetManager manager = AppWidgetManager.getInstance(context);
        manager.updateAppWidget(thisWidget,
                new RemoteViews(context.getPackageName(),
                        R.layout.activity_main));
        int appWidgetIds[] = manager.getAppWidgetIds(thisWidget);
        manager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.text_value);

    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) {

        RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
                R.layout.activity_main);
        ComponentName timerWidget = new ComponentName(context,
                MainActivity.class);

        SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss",
                Locale.US);
        Date d2 = null;
        try {
            d2 = format.parse("2014/10/04 10:00:00");
        } catch (ParseException e) {
            e.printStackTrace();
        }

        Calendar cal = Calendar.getInstance();

        long diff = d2.getTime() - cal.getTime().getTime();
        seconds = (int) (diff / 1000) % 60;
        minutes = (int) ((diff / (1000 * 60)) % 60);
        hours = (int) ((diff / (1000 * 60 * 60)) % 24);
        days = (int) (diff / (1000 * 60 * 60 * 24));
        remoteViews.setTextViewText(R.id.text_remaining,
                context.getString(R.string.time_remaining_text));
        remoteViews.setTextViewText(
        R.id.text_value,
        String.format(context.getString(R.string.text_days),
                days)
        + " "
        + String.format(
        context.getString(R.string.text_hours),
                hours)
        + " "
        + String.format(context.getString(R.string.text_minutes),
                minutes)
        + " "
        + String.format(context.getString(R.string.text_seconds),
                seconds));
        appWidgetManager.updateAppWidget(timerWidget, remoteViews);
    }
}

Provider XML

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:initialLayout="@layout/activity_main"
    android:minHeight="144dp"
    android:minWidth="146dp"
    android:updatePeriodMillis="1000" />

Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.poc_timerwidget"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="19" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <receiver
            android:name=".MainActivity"
            android:label="Timer Widget" >
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>

            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/timer_widget_provider" />
        </receiver>
    </application>

</manifest>

Upvotes: 3

Views: 2947

Answers (1)

Manish Mulimani
Manish Mulimani

Reputation: 17615

Issue:

  1. AppWidgetProvider is-a BroadcastReceiver. You are retrieving a PendingIntent which starts a service, instead of retrieving a PendingIntent which sends a broadcast.
  2. The receiver in manifest file has an intent-filter with action ACTION_APPWIDGET_UPDATE. However action AppWidgetManager.ACTION_APPWIDGET_UPDATEis not set on the pending intent passed to the alarm manager. You also need to set the extras AppWidgetManager.EXTRA_APPWIDGET_IDS on the pending intent.

Set repeat alarm to update widget:

Intent alarm = new Intent(context, MainActivity.class);
alarm.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); // Set appwidget update action
alarm.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds); // Set appwidget ids to be updated
pendingIntent = PendingIntent.getBroadcast(context, 0, alarm,
    PendingIntent.FLAG_CANCEL_CURRENT); // get the broadcast pending intent
alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis(),
    1000, pendingIntent); // set repeat alarm 

Remember to set updatePeriodMillis to 0. From docs :

Set the alarm type to either ELAPSED_REALTIME or RTC, which will only deliver the alarm when the device is awake. Then set updatePeriodMillis to zero ("0").

Upvotes: 8

Related Questions