Multiple Instances of Widget Only Updating Last Widget

Multiple Instances Of Widget Only Updating Last widget

I had a similar problem. Just add this to your config activity, where you set your PendingIntent:

Uri data = Uri.withAppendedPath(
Uri.parse(URI_SCHEME + "://widget/id/")
,String.valueOf(appWidgetId));
intent.setData(data);

The variable URI_SCHEME is a String, and can be whatever you'd like.. ie - "ABCD" This causes each widget to have a unique PendingIntent.

Multiple Android Widget instances only updating last widget

The problem isn't your configActivity, the problem is in your widgetProvider. I had the same problem as you did but solved using the link you specified. You need to set the "hacked" intent on your configIntent in buildRemoteView.

Updating multiple instances of App Widget in Android

Based on what you've posted it seems that this:

// request for widget update
pushWidgetUpdate(context, remoteViews, appWidSingle);

should probably look like this instead:

// request for widget update
pushWidgetUpdate(context, remoteViews, appWidgetIds[appWidSingle]);

Likewise:

// register for button event
remoteViews.setOnClickPendingIntent(R.id.sync_button,
buildButtonPendingIntent(context, appWidSingle));

should be:

// register for button event
remoteViews.setOnClickPendingIntent(R.id.sync_button,
buildButtonPendingIntent(context, appWidgetIds[appWidSingle]));

Multiple widget instances - need to update each instance separately

Use below sample step by step.

Step 1

Create Service UpdateWidgetService.java

public class UpdateWidgetService extends Service {
public UpdateWidgetService() {
}
public static final String SKIP = "skip";
public static final String OPENAPP = "openapp";

@Override
public int onStartCommand(Intent pIntent, int flags, int startId) {

String command = pIntent.getAction();

int appWidgetId = pIntent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
RemoteViews remoteView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.widget);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getApplicationContext());

if(command.equals(SKIP)){
/**Do the SKIP click work here*/
return START_NOT_STICKY;
}else if(command.equals(OPENAPP)){
/**Do the OPENAPP click work here*/
Intent mAct=new Intent(this, OPENAPP.class);
mAct.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(mAct);
return START_NOT_STICKY;
}

remoteView.setTextViewText(R.id.widet_ibtn_skip, "MyTextHere");
remoteView.setTextViewText(R.id.widget_tv_title, "Title");

remoteView.setOnClickPendingIntent(R.id.widet_ibtn_skip,WallWidgetProvider.makeControlPendingIntent(getApplicationContext(),SKIP,appWidgetId));
remoteView.setOnClickPendingIntent(R.id.widget_tv_title,WallWidgetProvider.makeControlPendingIntent(getApplicationContext(),OPENAPP,appWidgetId));

appWidgetManager.updateAppWidget(appWidgetId, remoteView);

return super.onStartCommand(pIntent, flags, startId);
}

@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}

Step 2
Create WidgetProvider as WallWidgetProvider.java

public class WallWidgetProvider extends AppWidgetProvider{

public static final int UPDATE_RATE = 1000;

@Override
public void onDeleted(Context context, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
setCounterAlarm(context, appWidgetId, -1);
}
super.onDeleted(context, appWidgetIds);
}

@Override
public void onDisabled(Context context) {
context.stopService(new Intent(context,UpdateWidgetService.class));
super.onDisabled(context);
}

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
PrefrenceSettings ps=new PrefrenceSettings(context);

for (int appWidgetId : appWidgetIds) {
setCounterAlarm(context, appWidgetId, UPDATE_RATE);
}

super.onUpdate(context, appWidgetManager, appWidgetIds);
}

public static void setCounterAlarm(Context context, int appWidgetId, int updateRate) {
PendingIntent newPending = makeControlPendingIntent(context,UpdateWidgetService.UPDATE,appWidgetId);
AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (updateRate >= 0) {
alarms.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), updateRate, newPending);
} else {
// on a negative updateRate stop the refreshing
alarms.cancel(newPending);
}
}

public static PendingIntent makeControlPendingIntent(Context context, String command, int appWidgetId) {
Intent active = new Intent(context,UpdateWidgetService.class);
active.setAction(command);
active.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
//this Uri data is to make the PendingIntent unique, so it wont be updated by FLAG_UPDATE_CURRENT
//so if there are multiple widget instances they wont override each other
Uri data = Uri.withAppendedPath(Uri.parse("widget://widget/id/#"+command+appWidgetId), String.valueOf(appWidgetId));
active.setData(data);
return(PendingIntent.getService(context, 0, active, PendingIntent.FLAG_UPDATE_CURRENT));
}

}

Hope you should know how to use these two class in your project, These classes generate unique identification of each Widget.

Why do we have to update multiple widgets from one widget?

Every widget has its own Broadcast reviever

No, it does not.

First, an AppWidgetProvider class handles all app widgets provided by that provider. If the user creates several instances of that app widget (e.g., weather reports for several cities), all of them are updated by that single AppWidgetProvider class.

Second, an individual instance of AppWidgetProvider is used for a single onUpdate() call. This is because AppWidgetProvider is a subclass of BroadcastReceiver, onUpdate() is triggered by onReceive(), and a manifest-registered BroadcastReceiver gets a unique instance per onReceive() call.

multiple instances of widget with separated working clickable ImageView

The method updateAppWidget(ComponentName provider, RemoteViews views) sets the RemoteViews to use for all AppWidget instances for the supplied AppWidget provider.

You want to use this method: updateAppWidget(int appWidgetId, RemoteViews views) which set the RemoteViews to use for the specified appWidgetId.

To do this you will need to keep track of the widget's id

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
final int N = appWidgetIds.length;

for (int i = 0; i < N; i++) {
// the individual id for the widget
int appWidgetId = appWidgetIds[i];

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

// pass appWidgetId to the click handler
remoteViews.setOnClickPendingIntent(R.id.widgetImageView, buildButtonPendingIntent(context, appWidgetIds[i]));

// pass appWidgetId to the update method
pushWidgetUpdate(context, remoteViews, appWidgetIds[i]);

}
}

Then update the two methods to use the appWidgetId

public static void pushWidgetUpdate(Context context, RemoteViews remoteViews, int appWidgetId) {
AppWidgetManager manager = AppWidgetManager.getInstance(context);
manager.updateAppWidget(appWidgetId, remoteViews);

}

public static PendingIntent buildButtonPendingIntent(Context context, int appWidgetId) {
Intent intent = new Intent();
// put the appWidgetId as an extra to the update intent
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
intent.setAction("WidgetUtils.WIDGET_UPDATE_ACTION");

return PendingIntent.getBroadcast(context, appWidgetId, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}

Finally, update the receiver to take the appWidgetId extra and use it for the update call

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

if(intent.getAction().equals("WidgetUtils.WIDGET_UPDATE_ACTION")){
int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
updateWidgetPictureAndButtonListener(context, int appWidgetId);
}

}

private void updateWidgetPictureAndButtonListener(Context context, int appWidgetId) {

RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_main);
remoteViews.setImageViewResource(R.id.widgetImageView, getImageToSet());

remoteViews.setOnClickPendingIntent(R.id.widgetImageView, MyWidgetProvider.buildButtonPendingIntent(context));
MyWidgetProvider.pushWidgetUpdate(context, remoteViews, appWidgetId);

}


Related Topics



Leave a reply



Submit