Change Icon on onReceive method - widget Android - 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!

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

Change src image of ImageButton of Android widget programatically

I am developing an Android app with a homescreen widget, which is an imageButton, and i want the image of the button to change after its been pressed. I have tried selector in an xml file, to change the image of the button, but it changes it only when it is pressed, but it goes back when its released.
I want it to change image after it was pressed and when the code inside the WidgetProvider is executed, it changes the image back to the default one.
I tried to do it programatically(in onRecieve() method), I guess it should be something with RemoteViews but whatever i try, it doesnt work.
Could someone help my with this? I saw many people asking about it, but most of the posts were either pretty old or the solutions were not working for me.
Thank you :)
Normally you'd set the image on the surface of the ImageButton using the setImageResource method (ImageButton inherits it from ImageView), but that method isn't available for RemoteViews.
RemoteViews offers a corresponding setImageViewResource method that does what you want (as well as setImageViewBitmap and setImageViewUri depending on how you'd like to provide the image data).
The code to set the image (say, within your BroadcastReceiver's onReceive method) would look something like this:
#Override
public void onReceive(Context context, Intent intent) {
int appWidgetId = intent.getIntExtra("appWidgetId", -1);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.main);
views.setImageViewResource(R.id.imageButton1, R.drawable.awesome_image);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
Note that the code above assumes you've added the id of the widget to be manipulated as an extra to the broadcast intent (wrapped in a PendingIntent that is sent when the user clicks the ImageButton) using the key "appWidgetId". You'll most likely want to do that in the onUpdate method of your AppWidgetProvider, like so:
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int i = 0; i < appWidgetIds.length; i++) {
int appWidgetId = appWidgetIds[i];
Intent intent = new Intent ("YourActionHere");
intent.putExtra("appWidgetId", appWidgetId);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, i, intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.main);
views.setImageViewResource(R.id.imageButton1, R.drawable.initial_image);
views.setOnClickPendingIntent(R.id.imageButton1, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
A simple but not elegant way is:
boolean isButtonSelected = false;
..
button.setOnClickListener(buttonListener);
..
OnClickListener buttonListener = new OnClickListener() {
#Override
public void onClick(View arg0) {
if(isButtonSelected ){
isButtonSelected = false;
button.setBackgroundResource(R.drawable.buttonOff); // or setImageResource(..);
} else{
isButtonSelected = true;
button.setBackgroundResource(R.drawable.buttonOn);
}
}
};

Can't update Button's text in a Widget

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

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

ViewFlipper in app widgets

I'm playing around building a new widget and was looking at the Android app widget documentation, in particular the section on which widget classes were supported. I noticed that ViewFlipper is supported, but I'm struggling to find any examples on how to use one in a home screen widget. In particular, I'm wondering if its possible to manually trigger swapping views. In an activity this looks relatively straightforward, one example being hooking up the onclick listener of a button to call the showNext() of the flipper.
The RemoteViews object has showNext and showPrevious methods but I'm not sure I understand how to hook them up to an event fired from the user interacting with the widget. Can anyone provide examples of when these methods might be called?
It looks like buttons in widgets can only be wired up to intents rather than code to exercise the flipper. If this restriction is true, then is the only use of a view flipper in an app widget for auto flipping of views?
Say you have 2 buttons: LEFT and RIGHT. First you would attach pending intent to each (here it's triggered from Service#onStart:
#Override
public void onStart(Intent intent, int startId) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this.getApplicationContext());
int[] allWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
// add listeners for every widget registered
for (int widgetId : allWidgetIds) {
addClickListeners(appWidgetManager, widgetId, root);
}
stopSelf();
}
protected void addClickListeners(AppWidgetManager appWidgetManager, int widgetId, RemoteViews root) {
root.setOnClickPendingIntent(R.id.left, getNavigationIntent(widgetId, R.id.left));
root.setOnClickPendingIntent(R.id.right, getNavigationIntent(widgetId, R.id.right));
}
protected PendingIntent getNavigationIntent(int widgetId, final int id) {
Intent clickIntent = new Intent(this, WidgetProvider.class);
clickIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
clickIntent.putExtra(TRIGGER, id);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, clickIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
Then, in AppWidgetProvider do
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Bundle extras = intent.getExtras();
Integer id = (Integer) (extras == null ? null : extras.get(TRIGGER));
if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action) && id != null) {
int widgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, 0);
onNavigate(context, widgetId, id);
} else {
super.onReceive(context, intent);
}
}
protected void onNavigate(Context context, Integer widgetId, Integer id) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews root = new RemoteViews(context.getPackageName(), R.layout.app_widget);
if (id == R.id.left) {
root.showPrevious(R.id.scroll);
} else {
root.showNext(R.id.scroll);
}
appWidgetManager.updateAppWidget(widgetId, root);
}
This should do it. Now the problem is - this will only work in API 11+ and I just found the hard way that root.setInt(R.id.scroll, "setDisplayedChild", pos) will not work in API 7.

Categories

Resources