Can't update Button's text in a Widget - android

How do I access items of a homescreen Widget, so I can make changes to them like setting a Button's text? In my AppWidgetProvider's onReceive() method I'm trying to set the text of a Button, which is in my homescreen widget:
#Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(MainActivity.ACTION_CHANGE_BUTTONSTATE))
{
String state = intent.getExtras().getString("state");
Log.d("HomescreenWidget", "received broadcast for button state");
RemoteViews views = new RemoteViews(context.getPackageName(),
R.id.widgetButton);
views.setTextViewText(R.id.widgetButton, state);
ComponentName cn = new ComponentName(context,
HomescreenWidget.class);
AppWidgetManager.getInstance(context).updateAppWidget(cn, views);
}
super.onReceive(context, intent);
}
My Widget's layout.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/RelativeLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/widget_margin" >
<Button
android:id="#+id/playButton_Widget"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:minWidth="80dp"
android:text="#string/playButton" />
</RelativeLayout>
I'm receiving the Broadcast, but then my Widget shows following text: "Problem loading widget".
EDIT
I found following message at the catlog:
W/AppWidgetHostView(135): updateAppWidget couldn't find any view, using error view
W/AppWidgetHostView(135): android.widget.RemoteViews$ActionException: can't find view: 0x7f0a0004
0x7f0a0004 is my Widget's Button. What could be the reason, that it can't be found?

To Access your view via appwidget provider you can use this remote views
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
views.setTextViewText(R.id.widgetname, newName);
or via service :
public class UpdateWidgetService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onStart(Intent intent, int startId) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this
.getApplicationContext());
int[] allWidgetIds = intent
.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
for (int widgetId : allWidgetIds) {
RemoteViews remoteViews = new RemoteViews(this
.getApplicationContext().getPackageName(),
R.layout.widget_layout);
remoteViews.setTextViewText(R.id.update,
"Random: " + String.valueOf(number));
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}
stopSelf();
super.onStart(intent, startId);
}
}
and don't forget to add the service to the manifest
<service android:name=".UpdateWidgetService"></service>
and then in the onUpdate (in your App Widget Provider class)
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
ComponentName thisWidget = new ComponentName(context,
MyWidgetProvider.class);
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
Intent intent = new Intent(context.getApplicationContext(),
UpdateWidgetService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);
context.startService(intent);
}
I hope this can help :)

I've just found the solution. The whole time I was passing the wrong ID for the Button. widgetButton did not exist in the Widget's layout. It was a button from my main Activity

import android.widget.RemoteViews;
//grab the layout, then set the text of the Button called R.id.Counter:
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.my_layout);
remoteViews.setTextViewText(R.id.Counter, "Set button text here");

Related

Widget refresh from inside application

Good Day! I want to add text from inside application to widget, i have a main activity and it has list view and lots of text contents and it has a button to add the text to widget via shared preference, it's works fine when i close the widget and recreate it only, otherwise it's not automatically refresh.if anyone know; how to solve this please help me. here i attached the widget code below.
public class WidgetMaster extends AppWidgetProvider {
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
Intent intentHome = new Intent(context, MainActivity.class);
PendingIntent pendingIntentHome = PendingIntent.getActivity(context, 0, intentHome, 0);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_master);
views.setOnClickPendingIntent(R.id.wid_home, pendingIntentHome);
final SharedPreferences sharedPreferencestoWi = context.getSharedPreferences(String.valueOf(R.string.addTextToWidgetPref), MODE_PRIVATE);
String forWidget = sharedPreferencestoWi.getString("textToWidget", "");
String dum = "add from reading";
if(forWidget.equals("")){
views.setTextViewText(R.id.dum_appwidget_text, dum);
appWidgetManager.updateAppWidget(appWidgetId, views);
} else {
views.setTextViewText(R.id.appwidget_text, forWidget);
views.setViewVisibility(R.id.appwidget_text, 0);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
#Override
public void onEnabled(Context context) {
// Enter relevant functionality for when the first widget is created
}
#Override
public void onDisabled(Context context) {
// Enter relevant functionality for when the last widget is disabled
}
}
How do you update the widget from mainActivity?
In the widget configuration file you can specify a fixed update interval. The smallest update interval is 1800000 milliseconds (30 minutes).
But its better to update widget programmatically, to do this You should send a broadCast to update widget and use a
method like alarmManager or Handler for a repeating task for example you can use the following broadCast to update widget form mainActivity:
Intent intent = new Intent(this, WidgetMaster.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
int[] ids = AppWidgetManager.getInstance(getApplication())
.getAppWidgetIds(new ComponentName(getApplication(),WidgetMaster.class));
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
sendBroadcast(intent);

Do not create widget

Hello this is simple question
i create widget and test this is my simple code :
#Override
public void onReceive(Context context, Intent intent) {
ComponentName thisAppWidget = new ComponentName(context, MyWidget.class);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int ids[] = appWidgetManager.getAppWidgetIds(thisAppWidget);
Log.d(" widget ids : " + Arrays.toString(ids) );
setResultCode(0);
}
But i have got red square on home screen .. ?
My widget provider configuration :
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="80dp"
android:minHeight="80dp"
android:previewImage="#drawable/example_appwidget_preview"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen|keyguard"
>
</appwidget-provider>
But i have got red square on home screen .. ?
This could be the preview image you have set in widget provider xml.
When the widget is added in home screen, the onUpdate() method will be called, where you can set the remote layout for the widget like this.
public class CustomAppWidgetProvider extends AppWidgetProvider{
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
for (int i = 0; i < N; i++) {
int appWidgetId = appWidgetIds[i];
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget_layout);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
}
You can also set a pending intent to an activity/service to be invoked when the whole widget or an child item in the widget is clicked
Intent intent = new Intent(context, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context,0,intent,0);
remoteViews.setOnClickPendingIntent(R.id.imageView1,pendingIntent);
So, here in the widget layout there is a textview , and when the user click on the textview the MainActivity will be launched.
You have to set an layout file to your appwidget-provider:
android:initialLayout="#layout/widget_view"
In this layout file you have to put Buttons, Images, TextViews etc. whatever you need.

Android sets different layout to AppWidget

I have a very weird problem with my AppWidget in Android 4.1.1. I'm currently developing a music player application and its widget. Widget must be updated when song changes, player starts and stops. It has a ListView which must be in sync with playlist in application.
Prior to Jelly Bean everything was working fine. After my test device is upgraded from 4.0.3 to 4.1.1, whenever widget is programmatically forced to update, layout of Android's Messaging widget is set to my widget for a few seconds! I also checked this case in emulator with 4.1, which works fine.
I use that piece of code to force my widget to update:
AppWidgetManager man = AppWidgetManager.getInstance(applicationContext);
int[] ids = man.getAppWidgetIds(
new ComponentName(applicationContext, MuzikLargeWidgetProvider.class));
Intent updateIntent = new Intent();
updateIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
applicationContext.sendBroadcast(updateIntent);
And here is my onUpdate method
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
this.context = context;
this.appWidgetManager = appWidgetManager;
ComponentName thisWidget = new ComponentName(context,
MuzikLargeWidgetProvider.class);
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
for (int appWidgetId : allWidgetIds) {
Intent svcIntent = new Intent(context, UpdateService.class);
svcIntent.putExtra(WidgetActions.DATA_WIDGET_ID, appWidgetId);
context.startService(svcIntent);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
I'm using a service (UpdateService), which is a static inner class, to update my widget:
public static class UpdateService extends IntentService {
public UpdateService() {
super("UpdateService");
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
public RemoteViews buildUpdate(Context context, int widgetId) {
final RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.muzikwidget_large);
return views;
}
#Override
protected void onHandleIntent(Intent intent) {
// Build the widget update
RemoteViews updateViews = buildUpdate(this, intent.getIntExtra(WidgetActions.DATA_WIDGET_ID, 0));
// Push update for this widget to the home screen
ComponentName thisWidget = new ComponentName(this, MuzikLargeWidgetProvider.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(thisWidget, updateViews);
}
}
buildUpdate method does a few more things (setting intents for widget's buttons, setting textviews, etc.) but they are not related with my problem. I'm having this problem on a Asus TF 300 TG tablet (not rooted).
Any help is appreciated.
The problem is resolved. I modified the code piece which I use to force widget to update. This is working:
AppWidgetManager man = AppWidgetManager.getInstance(applicationContext);
int[] ids = man.getAppWidgetIds(
new ComponentName(applicationContext, MuzikLargeWidgetProvider.class));
for (int appWidgetId : ids) {
Intent svcIntent = new Intent(applicationContext, UpdateService.class);
svcIntent.putExtra(WidgetActions.DATA_WIDGET_ID, appWidgetId);
applicationContext.startService(svcIntent);
}
Widget's onUpdate method is not called and UpdateService is invoked directly. It seems like sendBroadcast should be avoided sometimes.
EDIT
If you need to use broadcast to update your widget, this seems to be a proper way to accomplish that:
AppWidgetManager man = AppWidgetManager.getInstance(applicationContext);
int[] ids = man.getAppWidgetIds(
new ComponentName(applicationContext, MuzikLargeWidgetProvider.class));
Intent updateIntent = new Intent(applicationContext, MuzikLargeWidgetProvider.class);
updateIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
applicationContext.sendBroadcast(updateIntent);

Change Icon on onReceive method - widget Android

I developed a widget for Android with the intention of clicking a text widget's icon is changed. To do this I set the action and I have tried the method OnReceive action. This is the code:
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_WIDGET_NOTIF)) {
Bundle extras = intent.getExtras();
int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
RemoteViews controles = new RemoteViews(context.getPackageName(),
R.layout.widgetcuatroxuno);
controles.setImageViewResource(R.id.btt,
R.drawable.ic_launcher_new);
AppWidgetManager.getInstance(context).updateAppWidget(appWidgetId, controles);
} else {
super.onReceive(context, intent);
}
}
I know I need AppWidgetManager to update the widget controls, but it failed. How I can fulfill my purpose? Sorry for my English. Thank you very much for everything.
RemoteViews control = new RemoteViews(context.getPackageName(),
R.layout.widget);
control.setTextViewText(R.id.textview1, "ExampleText");
ComponentName cn = new ComponentName(context,
ButtonWidget.class);
AppWidgetManager.getInstance(context).updateAppWidget(cn,
control);
This one works in OnReceive(), thanks a lot!

Widget ImageButton listener not allways called

I have a simple Widget (Android 2.1) containing just a LinearLayout, itself containing an ImageButton.
The ImageButton has a on-click listener.
The problem is: If I put several of this same widget on my home screen, some are working (listener called when button pressed), and some are not! I cannot see any pattern in which are working and which are not.
Here is the widget layout:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#null">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/ImageButton01"
android:src="#drawable/widget_running"
android:background="#null">
</ImageButton>
And here is the widget provider code:
public class GPAppWidgetProvider extends AppWidgetProvider {
private String mTag = getClass().getSimpleName();
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
Log.e(mTag, "onUpdate ");
// Perform this loop procedure for each App Widget that belongs to this
// provider
for (int i = 0; i < N; i++) {
Log.e(mTag, "widget onUpdate one loop");
int appWidgetId = appWidgetIds[i];
// Create an Intent
Intent intent = new Intent(context, GPService.class).setAction(ACTION_WIDGET_TOGGLE_PAUSE);
intent.putExtra("widgetId", appWidgetId);
PendingIntent pauseIntent = PendingIntent.getService(context, 0, intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.gp_appwidget);
views.setOnClickPendingIntent(R.id.ImageButton01, pauseIntent);
// widget update
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}
I had the same problem.
Don't forget to set a different "requestCode" when you call "getService" :
public static PendingIntent getService (Context context, int requestCode, Intent intent, int flags)
And make sure your "appWidgetId" is different for each widget.

Categories

Resources