3

I want to create three different widgets with different sizes. I didn't find any tutorial, except this question how to add multiple widgets in one app? and I went this way.

Here is question, because later you will see long wall of the code.

When APPWIDGET_UPDATE is fired, in some way my widget gets update three times. I debugged that and found that overriden method updateRemoteView() launches three times from the three subclasses. How to launch it just from one class?

I've added three different receivers in to the Manifest:

    <receiver
        android:name=".DaysWidgetSmall"
        android:label="@string/small_widget_name" >
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>

        <meta-data
            android:name="android.appwidget.provider"
            android:resource="@xml/small_widget_provider" />
    </receiver>
    <receiver
        android:name=".DaysWidgetMedium"
        android:label="@string/medium_widget_name" >
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>

        <meta-data
            android:name="android.appwidget.provider"
            android:resource="@xml/medium_widget_provider" />
    </receiver>
    <receiver
        android:name=".DaysWidgetLarge"
        android:label="@string/large_widget_name" >
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>

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

Next I've created one base class and three subclasses:

Base One (parts of it):

@Override
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
    super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);

    Calendar calendar = Calendar.getInstance();
    calendar.add(Calendar.MILLISECOND, 2000);

    Intent alarmIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
    PendingIntent pendingIntent =
            PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);

    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    alarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), 2000, pendingIntent);
}

@Override
public void onReceive(Context context, Intent intent) {
    super.onReceive(context, intent);

    Bundle extras = intent.getExtras();
    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);

    if (intent.getAction().equals(AppWidgetManager.ACTION_APPWIDGET_UPDATE)) {

        if (extras != null) {
            int[] widgetIds =
                    appWidgetManager.getAppWidgetIds(
                            new ComponentName(
                                    context, DaysWidgetSmall.class
                            ));

            for (int appWidgetId : widgetIds) {
                RemoteViews views = new RemoteViews(context.getPackageName(), getLayout());
                SharedPreferences sharedPreferences =
                        context.getSharedPreferences(PREFS_FILE, Context.MODE_PRIVATE);
                updateRemoteView(views, sharedPreferences, appWidgetId);
                appWidgetManager.updateAppWidget(appWidgetId, views);
            }

            widgetIds =
                    appWidgetManager.getAppWidgetIds(
                            new ComponentName(
                                    context, DaysWidgetMedium.class
                            ));

            for (int appWidgetId : widgetIds) {
                RemoteViews views = new RemoteViews(context.getPackageName(), getLayout());
                SharedPreferences sharedPreferences =
                        context.getSharedPreferences(PREFS_FILE, Context.MODE_PRIVATE);
                updateRemoteView(views, sharedPreferences, appWidgetId);
                appWidgetManager.updateAppWidget(appWidgetId, views);
            }

            widgetIds =
                    appWidgetManager.getAppWidgetIds(
                            new ComponentName(
                                    context, DaysWidgetLarge.class
                            ));

            for (int appWidgetId : widgetIds) {
                RemoteViews views = new RemoteViews(context.getPackageName(), getLayout());
                SharedPreferences sharedPreferences =
                        context.getSharedPreferences(PREFS_FILE, Context.MODE_PRIVATE);
                updateRemoteView(views, sharedPreferences, appWidgetId);
                appWidgetManager.updateAppWidget(appWidgetId, views);
            }
        }
    }
}

public abstract int getLayout();

public abstract void updateRemoteView(RemoteViews views, SharedPreferences prefs, int id);

And here is short implementations of the one of the three classes (currently they are different by returning layouts, but later I want to expand this):

public class DaysWidgetSmall extends DaysWidget {

    @Override
    public int getLayout() {
        return R.layout.small_widget;
    }

    @Override
    public void updateRemoteView(RemoteViews views, SharedPreferences prefs, int id) {
        int current = prefs.getInt(PREFS_COUNT_NAME + id, 0);
        prefs.edit().putInt(PREFS_COUNT_NAME + id, ++current).apply();
        views.setTextViewText(R.id.update, current + "");
    }
}
Community
  • 1
  • 1
Anton Shkurenko
  • 4,301
  • 5
  • 29
  • 64

0 Answers0