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
Implementing User Choice of Theme
Programmatically Collapse or Expand Collapsingtoolbarlayout
Check If Correct Google Play Service Available: "Unfortunately Application Has Stopped Working"
Fragmentcontainerview Using Findnavcontroller
Using Resultreceiver in Android
Change Image of Imageview Programmatically in Android
Spinner Does Not Wrap Text -- Is This an Android Bug
Failed to Find Build Tools Revision 23.0.1
How to Debug Android Application Line by Line Using Eclipse
How to Determine If One of My Activities Is in the Foreground
Toolbar Navigation Icon Never Set
Android How to Apply Mask on Imageview
How to Create Preference Activity and Preference Fragment on Android
Android App Crashes When Launched in Debug Mode
How to Add Window -- Token Android.Os.Binderproxy Is Not Valid; Is Your Activity Running
Android Studio Adb Syntax Error: ")" Unexpected
Best Practice for Nested Fragments in Android 4.0, 4.1 (<4.2) Without Using the Support Library