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

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

Related

setTextViewText not working in IntentService

The code here in onHandleIntent:
RemoteViews views = new RemoteViews(getPackageName(), R.layout.mylayout);
views.setTextViewText(R.id.txtView1, "some string");
...
Bundle bundle = intent.getExtras();
int id = bundle.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(id, views);
does not update the widget's TextView named txtView1. I've searched and searched, but it appears that everything I've done seems to match what I found.
You need Handler to update UI from worker thread.
You can take help from this tutorial
http://crodrigues.com/updating-the-ui-from-a-background-thread-on-android/
or alternatively you can use Asynctask if you don't want to get into thread and handler stuff.
Asynctask manages this stuff by itself and you can update UI in onPostExecute() method and so on..
You can read details about asynctask in developer android site of google.
You have to update your textview in app widget development.
RemoteViews views = new RemoteViews(getPackageName(), R.layout.mylayout);
views.setTextViewText(R.id.txtView1, "some string");
thisWidget = new ComponentName(context, WatchWidget.class);
appWidgetManager.updateAppWidget(thisWidget, remoteViews);
Sigh, thank you all for your answers, unfortunately it was my mistake. In my onUpdate from my custom AppWidgetProvider, I was passing the wrong Id. I've switched it now to the proper Id, and each widget instance updates properly.

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?

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.

accessing android widget controls

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);

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