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 =]
Related
I am new to Android development and Java and am trying to update my widget using AlarmManager but I am not able to fully understand why most of the tutorials do not update widgets in the following way. I am using textview to display a number in my widget and increment it once every second and decrement it by 10 when a widget is removed and reset to 0 when all widgets are removed.
public class widget_1_1 extends AppWidgetProvider {
private static int var1 = 0;
public void onReceive(Context context, Intent intent)
{
AppWidgetManager widgetManager = AppWidgetManager.getInstance(context);
ComponentName widgetComponent = new ComponentName(context.getPackageName(), this.getClass().getName());
int[] widgetId = widgetManager.getAppWidgetIds(widgetComponent);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (intent.getAction().equals(AppWidgetManager.ACTION_APPWIDGET_UPDATE))
{
this.onUpdate(context, AppWidgetManager.getInstance(context), widgetId);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime()+1000, 1000, pendingIntent);
}
else if (intent.getAction().equals(AppWidgetManager.ACTION_APPWIDGET_DELETED))
{
// one widget deleted
var1-=10;
}
else if (intent.getAction().equals(AppWidgetManager.ACTION_APPWIDGET_DISABLED))
{
// last widget deleted
alarmManager.cancel(pendingIntent);
var1=0;
}
}
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
var1++;
// Code to update widget by calling appWidgetManager.updateAppWidget here
}
}
Is there something wrong with this method above? All the tutorials I see use a private static final String alarmAction = "com.elison.widget1.ALARM_ACTION" or similar string in the class and use it to get PendingIntent. I do not understand what is its benefit and why not the above simple method?
public void onReceive(Context context, Intent intent)
{
// Some code
Intent enable = new Intent(alarmAction);
intent.setClass(context, WYDAppWidgetProvider_4_1.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, enable, 0);
// Some tutorials use PendingIntent.FLAG_UPDATE_CURRENT instead of 0 in 4th parameter
// more code
}
The only problem with your code is that PendingIntent creation should be inside if statement which checks whether its WIDGET_UPDATE action or not. And other thing is that you don't need to create AlarmManager every time as you are using repeating alarm manager. Also you extracting widgetId array manually every time, it should also be in if statement.
I'm starting with widgets and got a very nice tutorial on the internet, got the example run perfectly, but when i tried to change somethings I got stuck.
The thing is: I just want to change the image from my imageButton when i press it, I've tried somethings but nothing seems to work. I didn't get how the RemoteView and Intent works exactly. So if someone can explain it shortly I would appreciate it =)
Here's the code:
public class HelloWidget extends AppWidgetProvider {
private ImageButton wifi;
public static String ACTION_WIDGET_CONFIGURE = "ConfigureWidget";
public static String ACTION_WIDGET_RECEIVER = "ActionReceiverWidget";
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.main);
Intent configIntent = new Intent(context, ClickOneActivity.class);
configIntent.setAction(ACTION_WIDGET_CONFIGURE);
Intent active = new Intent(context, HelloWidget.class);
active.setAction(ACTION_WIDGET_RECEIVER);
PendingIntent actionPendingIntent = PendingIntent.getBroadcast(context, 0, active, 0);
PendingIntent configPendingIntent = PendingIntent.getActivity(context, 0, configIntent, 0);
remoteViews.setOnClickPendingIntent(R.id.button_wifi, actionPendingIntent);
remoteViews.setOnClickPendingIntent(R.id.button_two, configPendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
}
#Override
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 {
// check, if our Action was called
if (intent.getAction().equals(ACTION_WIDGET_RECEIVER)) {
Toast.makeText(context, "Teste", Toast.LENGTH_LONG).show();
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.main);
remoteViews.setInt(R.id.button_wifi, "toogleOnOff", R.drawable.icon);
}
super.onReceive(context, intent);
}
}
}
There's a lot of the tutorial code i got as you can see =p
Thx since now
Looks like you need to understand a little more about RemoteViews. When you call functions like setOnClickPendingIntent, setInt, etc. on the RemoteViews object it basically just stores these operations and arguments internally. Then when the widget is displayed it just plays those operations back to construct the widget's views. So after giving the RemoteViews to the AppWidgetManager by calling updateAppWidget, you can't change them again unless you rebuild the whole RemoteViews and call updateAppWidget again.
As an answer to your question, you want to use a state list as the background for the button. There's a good example here.
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.
I have a widget that you press and it then it will update the text on the widget. I have set an on click listener to launch another activity to perform the text update, But for some reason it only works temporarily and then it will become unresponsive and not do anything when pressed. Does anyone know why it might be doing that? i have posted my widget code below in case it is helpful.
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) {
thisWidget = new ComponentName(context, MemWidget.class);
Intent intent = new Intent(context, updatewidget.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
// Get the layout for the App Widget and attach an on-click listener to the button
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
views.setOnClickPendingIntent(R.id.ImageButton01, pendingIntent);
// Tell the AppWidgetManager to perform an update on the current App Widget
appWidgetManager.updateAppWidget(thisWidget, views);
}
#Override
public void onReceive(Context context, Intent intent)
{
appWidgetManager = AppWidgetManager.getInstance(context);
remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
thisWidget = new ComponentName(context, MemWidget.class);
// 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);
}
}
Here is code that is called from my activity
thisWidget = new ComponentName(this, MemWidget.class);
appWidgetManager = AppWidgetManager.getInstance(this);
remoteViews = new RemoteViews(this.getPackageName(), R.layout.widget);
//do work
remoteViews.setTextViewText(R.id.ImageButton01,"setting text here");
appWidgetManager.updateAppWidget(thisWidget, remoteViews);
The onUpdate method there doesn't update any of the data in the RemoteViews other than the PendingIntent, so if that's ever called, the widget will revert to the state defined in R.layout.widget.
Do you have the code that calls updateAppWidget after the user interaction? That might help too.
Also, if the update is inline and doesn't require any UI, you don't need to launch an activity to do that update. It's more efficient and won't disrupt the back stack if your PendingIntent is for a broadcast receiver instead, using PendingIntent.getBroadcast. You can use the same BroadcastReceiver that is your app widget provider. You don't need another one.
Update: (I can't reply below because the text is too long)
I'd make a function like this, and call it from your activity from onUpdate(). You'll need to save text somewhere so you can also pass it in from onUpdate(). Otherwise it will revert the text to the default in R.layout.widget.
void updateWidget(Context context, CharSequence text) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
remoteViews.setOnClickPendingIntent(R.id.ImageButton01, pendingIntent);
remoteViews.setTextViewText(R.id.ImageButton01, text);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
ComponentName thisWidget = new ComponentName(context, MemWidget.class);
appWidgetManager.updateAppWidget(thisWidget, remoteViews);
}