accessing android widget controls - android

Probably a stupid question, but where and how do I access my widget controls?
With normal programs I call setContentView(R.layout.blah) and then use findViewById(R.id.blah)
to access the controls, but how do I do the same for widgets? Do I need to call setContentView() somewhere or..? The widget looks just fine without calling it anywhere.

As it comes out there's now way to access them directly. Instead you have to do this:
RemoteViews remoteViews =
new RemoteViews(ctx.getPackageName(), R.layout.folder_view_mywidget);
ComponentName thisWidget = new ComponentName(ctx, FolderViewProvider.class);
Then you use methods from Remoteviews to set all the fields you want like this:
remoteViews.setTextViewText(R.id.text1_1, "text");
And then finally you call this to execute the changes:
AppWidgetManager.getInstance(ctx).updateAppWidget(thisWidget, remoteViews);

Related

How to partially update views in an app widget without rebuilding all the RemoteViews

I'm implementing an app widget and I'd like to be able to change the property of a single view in the widget layout, without rebuilding all the RemoteViews from scratch, which involves loading XML etc and which is not necessary in some circumstances.. Is there a way to say "update property X on view identified by a specific ID in the current widget layout"? I've seen that there is a partiallyUpdateAppWidget method in the AppWidgetManager class but I can't understand nor if it is meant for this purpose neither how it must be used.. Can you help me or point me to a useful link or example?
Yes, you can use partiallyUpdateAppWidget method in the AppWidgetManager class.
As an example, if you want to update a text view inside a widget:
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
rv = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);
rv.setTextViewText(R.id.ofTextViewInWidgetLayoutXML, "Hello World");
appWidgetManager.partiallyUpdateAppWidget(appWidgetIds, rv);
Ref:
Just update a widget RemoteViews instead of completly creating a new one?

Widget not updating when Activity content changes in Android

I have a widget whose content is very similar to what is seen in the actual app, i.e. images and text just on a smaller scale.
I am using the following code to make the widget update after the activity UI updates - only it is not working and the widget it not updating:
Intent i = new Intent(mContext, ExtensionOfAppWidgetProvider.class);
i.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
mContext.sendBroadcast(i);
I cannot get the onUpdate() of the AppWidgetProvider class to be called without removing the widget and then placing it back on the homescreen.
Any help is appreciated.
Thanks.
Here was the culprit...a couple lines of code were missing from the onReceive() of my AppWidgetProvider class.
AppWidgetManager mgr = AppWidgetManager.getInstance(context);
int[] ids = mgr.getAppWidgetIds(new ComponentName(context, PromoStackWidgetProvider.class));
for(int id : ids) {
mgr.notifyAppWidgetViewDataChanged(id, R.id.stack_view);
}
Make sure that your widget has itself as a registered broadcast reciever in your AndroidManifest.xml

Update a widget from a service

I'm trying to update a widget from a service... the service start a thread that execute this code
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(Worker.this);
RemoteViews remoteViews = new RemoteViews(Worker.this.getPackageName(), R.layout.mywidget);
ComponentName projectWidget = new ComponentName(Worker.this, MyWidget.class);
remoteViews.setTextViewText(R.id.widgetstate, "update");
appWidgetManager.updateAppWidget(projectWidget, remoteViews);
the onUpdate method just print a log, but this log is printed only when I create the widget, not everytime the thread cycles... where I'm wrong?
Thanks in advance
You're not wrong. You just update the widget without calling onUpdate(). It's just a convinience method that gets called in response to the ACTION_APPWIDGET_UPDATE broadcast by the system. You don't have to call it to update a widget, it also just works like you did here. ¹
To invoke it you can send the broadcast or call it by hand though, it's a good idea to keep the widget update functionality in one place from a code structure point of view to find things easily.
¹ Take a look at the AppWidgetProvider source, line 56. The whole AppWidgetProvider is just a BroadcastReceiver that does some work for you already - and it does start the update in the same way.

Just update a widget RemoteViews instead of completly creating a new one?

In my onUpdate method in my AppWidgetProvider class, I ended up executing a non-trivial amount of code so that I can completely recreate a new RemoteView object. The reality is I really only need to be setting the text in one of the TextViews in the RemoteViews each time I update.
Is there any way to just modify the RemoteViews that a particular widget is already using?
First, RemoteView is not a View. It's a set of instructions that build a View hierarchy. It is used to recreate a View in another process (App Widgets do not execute in your app's process). As such it's serializable and mutable.
So, when you initialize a RemoteView just store a reference to it somewhere, e.g. in a field of your custom AppWidgetProvider.
Next time you need it, get it from field and the change something on it. For changing the string in a TextView use setString(..).
remoteView.setString(textViewId, "setText", "some text for TextView")
This is the 2013 update if you are using current API's. In your WidgetProvider class' method that will perform an update:
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
rv = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);
rv.setTextViewText(R.id.ofTextViewInWidgetLayoutXML, "Hello World");
appWidgetManager.partiallyUpdateAppWidget(appWidgetIds[i], rv);
Note that it is no longer remoteView.setString but remoteView.setTextViewText
You can update the remote views and then call
ComponentName componentName= new ComponentName(context, YourClass.class);
AppWidgetManager.getInstance(context).updateAppWidget(componentName, remoteViews);
on, which AFAIK should update the widget

After orientation change buttons on a widget are not responding [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
After orientation change buttons on a widget are not responding
I'm facing a problem with an appwidget that has one ImageView inside the xml layout for which I register a pendingintent that is handled in OnReceive method .
Everything works okay until I change phone orientation. At this point the widget doesn't work anymore, I click on the image but nothings happens.
This problem is exactly as the one here :
After orientation change buttons on a widget are not responding
What's is the problem and how can be resolved ?
Thanks.
I eventually managed to recreate the OP's service-free solution. Here's the secret for the record: Any time you update the remote views, you must update everything that you ever update. My app was updating some visual elements, but not setting the button handler again. This caused the handler to stop working--not straight away--only after a rotation change, hence the confusion.
If this is done right, you don't need to intercept configuration change broadcasts, the last remote views you set will be used again after rotation. No call is needed to your AppWidgetProvider.
I had a similar issue, but my app is working well now with the solution suggested by Alex
"...solved without the help of a service, just setting again the
setOnClickPendingIntent in the OnReceive method"
I tracked the onReceive method and it is called everytime I change the orientation of my device, so I called again the configuration of my widget on the onReceive method.
Anyway Im not sure this is the best solution to solve that problem, if anyone knows a better solution please share.
Thanks.
Whenever you update the look of your widget (using either an Activity or your Broadcast Receiver [App widget provider]), you must also reassign all the PendingIntents for the click handlers, and then call updateAppWidget() as normal.
Example with setTextViewText():
// This will update the Widget, but cause it to
// stop working after an orientation change.
updateWidget()
{
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
remoteViews.setTextViewText(R.id.widget_text_view, "Updated widget");
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
// This is the correct way to update the Widget,
// so that it works after orientation change.
updateWidget()
{
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
remoteViews.setTextViewText(R.id.widget_text_view, "Updated widget");
Intent intent = new Intent(context, MyWidgetActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, ...);
remoteViews.setOnClickPendingIntent(R.id.widget_click_button, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
See here for a possible explanation, or further things to try:
http://permalink.gmane.org/gmane.comp.handhelds.android.devel/98008
or
http://groups.google.com/group/android-developers/browse_thread/thread/578a4429c369c27c/273a53a96ddd10c5?lnk=gst&q=Widget+does+not+respond+when+phone+orientation+changes#273a53a96ddd10c5
But it's not yet clear what the true solution is.

Categories

Resources