I have a couple of widgets which are basically quick links to functionality within my app,
These widgets are basically ListView/GridViews which are being backed by data that changes during the main App's execution.
Since the data is only changed during app execution the update frequency is set as so:
android:updatePeriodMillis="0"
and on the data changed I fire the following:
public void updateWidget(#SuppressWarnings("rawtypes") Class provider) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
int[] gridids = appWidgetManager.getAppWidgetIds(new ComponentName(this.getPackageName(), provider.getName()));
Intent intent = new Intent(this, provider);
intent.setAction("android.appwidget.action.APPWIDGET_UPDATE");
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,gridids);
sendBroadcast(intent);
}
I'm able to catch this in the onReceive() of the Provider and from their call the update mechanism:
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
Log.e(this.getClass().getSimpleName(), "onReceive()");
int[] ids = intent.getExtras().getIntArray("appWidgetIds");
for(int id : ids) onUpdateWithService(context, id);
}
protected void onUpdateWithService(Context context, int widgetId) {
super.onUpdateWithService(context, widgetId);
RemoteViews views = new RemoteViews(context.getPackageName(), getResourceLayout(context, widgetId));
Intent intent = new Intent(context, GridViewWidgetServiceAdapter.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
views.setRemoteAdapter(R.id.listView, intent);
views.setPendingIntentTemplate(R.id.listView, PendingIntent.getActivity(context, -1, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT));
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
appWidgetManager.updateAppWidget(widgetId, views);
}
The problem I'm having is that although the code fires and updateAppWidget() is called, the UI of the widget doesn't change.
Am I missing a trick involved in Widget updates?
This answer seems to fix the problem.
Not sure why it fixes the problem, but it does...
Adding the following line to the intent works fine
Intent intent = new Intent(context, GridViewWidgetServiceAdapter.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
intent.putExtra("Random", Math.random() * 1000); // Add a random integer to stop the Intent being ignored.
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
Related
I'm creating an android widget that by clicking, every instance of the widget will go to a different url.
I'm having a problem sending the url from the 'onUpdate' to the 'onReceive' method.
The onUpdate code:
List<String> urls = Arrays.asList("google.com", "yahoo.com", "bing.com", "msn.com");
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
int cnt = 0;
// Get all ids
ComponentName thisWidget = new ComponentName(context,MyWidgetProvider.class);
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
for (int widgetId : allWidgetIds) {
// create some random data
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget_layout);
Log.w("WidgetExample", urls.get(cnt));
// Set the text
remoteViews.setTextViewText(R.id.urlData, urls.get(cnt));
// Register an onClickListener
Intent intent = new Intent(context, MyWidgetProvider.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
intent.putExtra("url",urls.get(cnt));
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.open, pendingIntent);
appWidgetManager.updateAppWidget(widgetId, remoteViews);
cnt++;
}
}
The onReceive code:
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
String TAG = "onReceive";
Bundle extras = intent.getExtras();
if(extras!=null) {
String url = extras.getString("url");
Log.d(TAG, "url is : "+url);
}else {
Log.d(TAG, "no url");
}
}
The problem is that i allwas get the same url (the last one in the list - 'msn.com').
Thank's allot
Avi
I think that this append because you override everytime the intent storage in PendingIntent because the requestCode doesn't change.
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,**0**, intent, PendingIntent.FLAG_UPDATE_CURRENT);
If you want set more PendingIntent you must change the requestCode (0 in your case)
Try
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, cnt, intent, PendingIntent.FLAG_UPDATE_CURRENT);
In this way all PendingIntents are different...
You're using PendingIntent.FLAG_UPDATE_CURRENT which, as the documentation states, "[...]if the described PendingIntent already exists, then keep it but replace its extra data with what is in this new Intent[...]"
So since you're trying to create multiple instances of the same class (PendingIntent) that flag is causing the unwanted behaviour. It is updating the previously instantiated object (the first time you called PendingIntent.getBroadcast(...) method) and changes the field(s) of that object and returns it. So that all your calls end up with the last extra (last URL you supplied) .
I have implemented a widget with an ImageButton and a TextView. That ImageButton launch an activity when its clicked. This activity updates the widget text with what the user writes on the activity EditText. Now the problem is that I only know how to get the ids like this:
for (int widgetId : allWidgetIds) {
// Create some random data
int number = (new Random().nextInt(100));
RemoteViews remoteViews = new RemoteViews(getApplicationContext()
.getPackageName(), R.layout.widget_layout);
Log.w("WidgetExample", String.valueOf(number));
//Here I should set text from edit text, but I'm using a random for testing.
remoteViews.setTextViewText(R.id.textView1,
"Random: " + String.valueOf(number));
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}
This code will obviously change the data of all the ids, since its inside a for. Is there anyway that I can past the clicked widgetId with my intent, so I can eliminate that for? This is my widgetProvider:
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// Get all ids
ComponentName thisWidget = new ComponentName(context, Widget.class);
allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
for (int widgetId : allWidgetIds) {
Intent i = new Intent(context, WidgetSetup.class);
i.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);
i.setFlags(i.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
// Create some random data
int number = (new Random().nextInt(100));
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.widget_layout);
// Set the text
remoteViews.setTextViewText(R.id.textView1, String.valueOf(number));
Intent active = new Intent(context, Widget.class);
active.setAction(ACTION_WIDGET_REFRESH);
PendingIntent actionPendingIntent = PendingIntent.getBroadcast(context, 0, active, 0);
remoteViews.setOnClickPendingIntent(R.id.imageButton1, actionPendingIntent);
active = new Intent(context, Widget.class);
active.setAction(ACTION_WIDGET_SETTINGS);
actionPendingIntent = PendingIntent.getBroadcast(context, 0, active, 0);
remoteViews.setOnClickPendingIntent(R.id.imageButton2, actionPendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
}
}
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_WIDGET_REFRESH)) {
//Log.i("onReceive", ACTION_WIDGET_REFRESH);
Intent i = new Intent(context, MainActivity.class);
i.setFlags(i.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
} else if (intent.getAction().equals(ACTION_WIDGET_SETTINGS)) {
//Log.i("onReceive", AppWidgetManager.EXTRA_APPWIDGET_ID);
Intent i = new Intent(context, WidgetSetup.class);
i.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);
//Here I tried to pass the widgetID with no luck.
//i.putExtra(pass widget id?);
i.setFlags(i.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
} else {
super.onReceive(context, intent);
}
}
Thanks
For a running example have a look at my code for MiniCallWidget lines 97 and 169.
Add an Extra to the intent you launch onClick and create in the for loop that specifies the ID of the current widget being setup.
Then retrieve the ID from the extras in the receiving Activity, and pass it back when you're done. Then use the returned ID to make changes only to one widget.
You can do this by having an if-else that also checks for a flag that tells whether or not you're updating only one widget.
I have a widget that has a refresh button and a textview. Refresh updates the content and when user clicks on textview it starts a new activity.
Problem is it works fine for a few hours and then onclick and refresh button doesn't do anything. Nothing is captured in logcat. Also If user deletes widget and put a new one it starts working for a few hours and then the same story :(...what am I doing wrong!
Broadcast receiver.
onUpdate
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
long interval = getrefresInterval();
final Intent intent = new Intent(context, UpdateService.class);
final PendingIntent pending = PendingIntent.getService(context, 0, intent, 0);
final AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pending);
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(),interval, pending);
// Build the intent to call the service
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget);
// To react to a click we have to use a pending intent as the
// onClickListener is excecuted by the homescreen application
Intent ClickIntent = new Intent(context.getApplicationContext(),widgetHadith.class);
Intent UpdateIntent = new Intent(context.getApplicationContext(),UpdateService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context.getApplicationContext(), 0, ClickIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent pendingIntentUpdate = PendingIntent.getService(context.getApplicationContext(), 0, UpdateIntent,
PendingIntent.FLAG_UPDATE_CURRENT); //use this to update text on widget. if use this put UpdateService.class to intent
remoteViews.setOnClickPendingIntent(R.id.widget_textview, pendingIntent);
remoteViews.setOnClickPendingIntent(R.id.widget_refresh, pendingIntentUpdate);
// Finally update all widgets with the information about the click listener
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
// Update the widgets via the service
context.startService(intent);
}
onReceive
public void onReceive(Context context, Intent intent) {
// v1.5 fix that doesn't call onDelete Action
final String action = intent.getAction();
if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {
final int appWidgetId = intent.getExtras().getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
this.onDeleted(context, new int[] { appWidgetId });
}
} else {
super.onReceive(context, intent);
}
}
onDelete
public void onDeleted(Context context, int[] appWidgetIds) {
// Toast.makeText(context, "onDelete", Toast.LENGTH_SHORT).show();
super.onDeleted(context, appWidgetIds);
}
Service onstart where I am updating
#Override
public void onStart(Intent intent, int startId) {
RemoteViews updateViews = new RemoteViews(this.getPackageName(),R.layout.widget);
processDatabase();
Spanned text = LoadHadith();
String hadith = text.toString();
Log.d("BR", "service---> ");
// set the text of component TextView with id 'message'
updateViews.setTextViewText(R.id.widget_textview, text);
//Push update for this widget to the home screen
ComponentName thisWidget = new ComponentName(this, HelloWidget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(thisWidget, updateViews);
}
The problem is that you can't do a partiall update for a widget, you must set all the widget features, such as the set of PendingIntent's every time you push a new remoteView.
(Partiall updates are only available for API14 and up...).
The reason your widgets are loosing their pendingIntents is that the android system saves the remoteView, and rebuilds your widget with it, in case it resets the widget (shortage of memmory, TaskManager/taskKiller in use, etc...), so you must set all the update code for the widget in the remoteView in your updateService.
Otherwise, it's just won't set the pendingIntents again.
So just add the code setting the pendingIntents to the service and your problem will be solved =]
This is what I want from my AppWidget:
configuration activity comes up, when widget is added to the screen // good so far
after configuration is saved, a service is started that updates the widget // good so far
schedule an alarm periodically to run the service that updates the widget. // having troubles here
This is seriously giving me grey hair already, and I don't know what to do anymore. How do you set the update rate for an AppWidget from a service? I can update the widget from the service, but when I try to set the alarm, it does not get to the onReceive() method on the AppWidget.
Here is the code for the service update:
Intent updateWidget = new Intent();
updateWidget.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
updateWidget.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[]{appWidgetId});
Uri data = Uri.withAppendedPath(Uri.parse(WeatWidgetProvider.URI_SCHEME +
"://widget/id/"), String.valueOf(appWidgetId));
updateWidget.setData(data);
PendingIntent updatePend = PendingIntent.getBroadcast(this, 0, updateWidget, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarm = (AlarmManager)getSystemService(ALARM_SERVICE);
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime()+ updateRate, updateRate, updatePend);
And in the onreceive() of WidgetProviderClass:
public void onReceive(Context context, Intent intent){
super.onReceive(context, intent);
Log.d("OnReceive", "OnReceive called");
String action = intent.getAction();
Log.d("Action", "OnReceive:Action: " + action);
if(AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)){
int appwidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
if(appwidgetId != AppWidgetManager.INVALID_APPWIDGET_ID){
this.onDeleted(context, new int[] {appwidgetId});
}
} else if(AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)){
if(!URI_SCHEME.equals(intent.getScheme())){
final int[] appWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
for(int appWidgetId:appWidgetIds){
SharedPreferences prefs = context.getSharedPreferences(WeatForecastConfigure.WEATHER_PREF_NAME, Context.MODE_PRIVATE);
update = prefs.getInt(WeatForecastConfigure.REFRESH_UPDATE, -1);
System.out.println(update);
if(update != -1){
Intent widgetUpdate = new Intent();
widgetUpdate.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
widgetUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] { appWidgetId });
// make this pending intent unique by adding a scheme to it
widgetUpdate.setData(Uri.withAppendedPath(Uri.parse(WeatWidgetProvider.URI_SCHEME +
"://widget/id/"), String.valueOf(appWidgetId)));
PendingIntent newPending = PendingIntent.getBroadcast(context.getApplicationContext(), 0, widgetUpdate, PendingIntent.FLAG_UPDATE_CURRENT);
// schedule the updating
AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarms.setRepeating(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime(), WeatForecastConfigure.convertToMillis(update), newPending);
}
}
}
super.onReceive(context, intent);
}else{
super.onReceive(context, intent);
}
}
For onUpdate() commented lines are deliberate.
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){
Log.d("OnUpdate", "OnUpdate called");
for (int appWidgetId : appWidgetIds) {
// context.startService(new Intent(context,WeatService.class));
}
//super.onUpdate(context, appWidgetManager, appWidgetIds);
}
Please help. I have no idea how to set the alarm to update. Whether I do it from the configuration class or from a service, it does not work. Thanks.
I think you need to use a standard URI scheme in your intent like this:
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
I wrote all this, and realized it will probably just confused you more, oh well.
Here is the skeleton of how I update my widgets, it is loosely based on this code http://code.google.com/p/android-sky/source/browse/#svn%2Ftrunk%2FSky (particularly the UpdateService class.
The main difference is my code
Starts the service to perform the update
Sets the Alarm (a broadcast pending intent) to alert the widget about the next update
Updates the widget and stops the service
Receives update broadcast (in the providers onReceive) and starts the service again
You seem to be trying to tell the AppWidgetProvider to kickoff through the onUpdate, I'm not sure if this is even possible?
Here is how I do it in semi pseudo code:
UpdateService class:
//based on (an old) example http://code.google.com/p/android-sky/source/browse/#svn%2Ftrunk%2FSky however other methods I have tried have not been as reliable as this
public void run() {
//set the alarm for the next update
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
long millis = System.currentTimeMillis();
//one alarm to update them all, if you wanted to you could
//add an extra appWidgetId then you might need to encode the intent
//however so it is a unique PendingIntent
Intent updateIntent = new Intent(ACTION_UPDATE_ALL); //ACTION_UPDATE_ALL should be a constant somewhere that can be used to resolve this action com.packagename.ACTION_UPDATE_ALL
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, updateIntent, 0);
// Schedule alarm, and force the device awake for this update
alarmManager.set(AlarmManager.RTC, millis + updateFrequency * DateUtils.MINUTE_IN_MILLIS, pendingIntent);
Log.d(TAG, "Next update should be at: " + DateFormat.format("h:mm:ss", millis + updateFrequency * DateUtils.MINUTE_IN_MILLIS));
while (hasMoreUpdates()) {
int appWidgetId = getNextUpdate();
if (!(appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID)) {
Uri appWidgetUri = ContentUris.withAppendedId(Agenda.getContentUri(context), appWidgetId);
AppWidgetProviderInfo info = manager.getAppWidgetInfo(appWidgetId);
String providerName = info.provider.getClassName();
//if the provider matches one of my widget classes, call the update method
if (providerName.equals(Widget_4_1.class.getName())) {
remoteViews = Widget_4_1.buildUpdate(context, appWidgetUri, dateRows);
}
//perform more actions such as sending remoteViews to the AppWidgetManager
}
}
}
Widget_4_1 class:
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// If no specific widgets requested, collect list of all
if (appWidgetIds == null) {
appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(
context, AbstractWidget.class));
}
UpdateService.requestUpdate(appWidgetIds);
Intent i = new Intent();
i.setComponent(new ComponentName(context, UpdateService.class));
context.startService(i);
}
//called from service
public static RemoteViews buildUpdate(Context context, Uri appWidgetUri) {
int appWidgetId = (int) ContentUris.parseId(appWidgetUri);
RemoveViews remoteViews = someMethodToBuildView(appWidgetId );
//return view to service
return remoteViews;
}
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
//when the alarm triggers, just update all your widgets, why handle them separately?
if (action.equals(ACTION_UPDATE_ALL)) {
AppWidgetManager manager = AppWidgetManager.getInstance(context);
int[] appWidgetIds = manager.getAppWidgetIds(new ComponentName(context, getClass()));
if(appWidgetIds.length>0){
UpdateService.requestUpdate(appWidgetIds);
Intent updateIntent = new Intent(context, UpdateService.class);
updateIntent.setAction(action);
context.startService(updateIntent);
}
}
//else you could catch a specific action for updating a single widget and
//tell your update service to do it manually
}
AndroidManifest.xml:
<application>
...
<receiver android:name="com.mypackage.Widget_4_1"
android:label="#string/agenda_widget_name_4_1">
<intent-filter>
<!-- IMPORTANT, needs to match the ACTION_UPDATE_ALL string (e.g. a constant somewhere) -->
<action android:name="com.packagename.UPDATE_ALL" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/widget_4_1" />
</receiver>
...
</application>
Hope I haven't confused you.
As this code is copy/pasted from various parts of my project excuse typo's etc, I will fix them as they are pointed out.
Would like a button in my widget to fire the APPWIDGET_UPDATE intent on the widget class to force an update, but I dont see APPWIDGET_UPDATE as a static field in Intent.
Is this possible, and how would one do this?
Intent intent = new Intent(context, BaseWidgetProvider.class);
intent.setAction({APPWIDGET_UPDATE INTENT HERE})
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.MyWidgetButton, pendingIntent);
Yes, it's possible. You'll find the action in AppWidgetManager:
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE)
Edit: You will need to provide the ids of the widgets you want to update. Below is a complete sample.
AppWidgetManager widgetManager = AppWidgetManager.getInstance(context);
ComponentName widgetComponent = new ComponentName(context, YourWidget.class);
int[] widgetIds = widgetManager.getAppWidgetIds(widgetComponent);
Intent update = new Intent();
update.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, widgetIds);
update.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
context.sendBroadcast(update);
I know this is a very old question, but I think this might be interesting, because Android updated the AppWidgets refresh policies. I think this change could prevent the exising answer to work as expected.
This is my solution, using RemoteViews and a collection.
public static final String ACTION_WIDGET_UPDATE = "com.yourpackage.widget.ACTION_UPDATE";
#TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_WIDGET_UPDATE)) {
int widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 0);
AppWidgetManager.getInstance(context)
.notifyAppWidgetViewDataChanged(widgetId, R.id.widgetColectionRoot);
}
super.onReceive(context, intent);
}
#TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
for (int widgetId : appWidgetIds) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
RemoteViews collectionRemoteView = getRemoteViews(widgetId, context);
appWidgetManager.updateAppWidget(widgetId, collectionRemoteView);
}
}
}
#TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
#SuppressWarnings("deprecation")
private RemoteViews getRemoteViews(int widgetId, Context context) {
// Sets up the intent that points to the RemoteViewService
// that will
// provide the views for this collection.
Intent widgetUpdateServiceIntent = new Intent(context,
RemoteViewsService.class);
widgetUpdateServiceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
// When intents are compared, the extras are ignored, so we need
// to embed the extras
// into the data so that the extras will not be ignored.
widgetUpdateServiceIntent.setData(
Uri.parse(widgetUpdateServiceIntent.toUri(Intent.URI_INTENT_SCHEME)));
RemoteViews collectionRemoteView = new RemoteViews(context.getPackageName(),
R.layout.widget_collection);
collectionRemoteView.setRemoteAdapter(widgetId,
R.id.widgetColectionRoot, widgetUpdateServiceIntent);
collectionRemoteView.setEmptyView(R.id.widgetColectionRoot, R.id.widgetEmpty);
// This section makes it possible for items to have
// individualized behavior.
// It does this by setting up a pending intent template.
// Individuals items of a collection
// cannot set up their own pending intents. Instead, the
// collection as a whole sets
// up a pending intent template, and the individual items set a
// fillInIntent
// to create unique behavior on an item-by-item basis.
Intent selectItemIntent = new Intent(context,
BrochuresWidgetProvider.class);
Intent refreshIntent = new Intent(selectItemIntent);
refreshIntent.setAction(ACTION_WIDGET_UPDATE);
PendingIntent refreshPendingIntent = PendingIntent.getBroadcast(
context, 0, refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT);
collectionRemoteView.setOnClickPendingIntent(R.id.widgetReload,
refreshPendingIntent);
return collectionRemoteView;
}
Of course, you also need to register that intent-filter on your manifest, inside your widget provider declaration.