HI i am having right trouble handling a click on a widget! I have got it so I can print a message to logcat when it is clicked on but I cant say change the text of a textview or show a button.
My main goal is to get a button to become visible when clicking on the widget and from here open a settings menu or share options for social media.
Here is my On Update code (DaysTillWidget.class)
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
setAlarm(context, appWidgetId, UPDATE_RATE);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.main);
Intent clickIntent = new Intent(context, DaysTillWidget.class);
clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, appWidgetId, clickIntent, 0);
views.setOnClickPendingIntent(R.id.imageView2, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
}
and here is the onRecieve code in the same Class
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction()==null) {
Bundle extras = intent.getExtras();
if(extras!=null) {
int widgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
// do something for the widget that has appWidgetId = widgetId
System.out.println("is this it?" + widgetId);
RemoteViews RemoteViews = new RemoteViews(context.getPackageName(), R.layout.main);
}
}
else {
super.onReceive(context, intent);
}
}
Any ideas on how I can get to my main goal?! I have spent hours reading peoples posts with similar problems but just cant get anything to work!
Im not sure if my project setup it correct or not but so far I have got everything else working? I have a service Class and a config class.
If I cant get the button to show and hide I would like to relaunch the config activity with the sharedprefernces for that widgetId
If you need to see any more code please let me know
Thanks in advance
Related
In the RemoteViews for an AppWidget I have an AdapterViewFlipper which is supposed to flip when the user clicks a button in the AppWidget. According to the official documentation this should be done by calling the showNext on the RemoteViews. The AppWdiget should then be updated with partiallyUpdateAppWidget which even has the showNext() function as an example in the documentation. I've tried implementing this and I'm most likely making some silly mistake that I can't seem to figure out.
public class WidgetProvider extends AppWidgetProvider {
public static final String NEXT = "next";
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
Intent nextIntent = new Intent(context, WidgetProvider.class);
nextIntent.setAction(NEXT);
views.setOnClickPendingIntent(R.id.next_button,
PendingIntent.getBroadcast(context, appWidgetId, nextIntent,
PendingIntent.FLAG_UPDATE_CURRENT));
views.setRemoteAdapter(R.id.view_flipper, new Intent(context,
WidgetRemoteViewService.class));
appWidgetManager.updateAppWidget(appWidgetId, views);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(NEXT)) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.widget_layout);
remoteViews.showNext(R.id.view_flipper);
AppWidgetManager.getInstance(context).partiallyUpdateAppWidget(
AppWidgetManager.getInstance(context).getAppWidgetIds(
new ComponentName(context, WidgetProvider.class)),
remoteViews);
}
super.onReceive(context, intent);
}
}
When replacing partiallyUpdateAppWidget with updateAppWidget the next button is working until the orientation changes or the phone goes to sleep which forces a redraw of the last stored RemoteViews. This leads me to believe the mistake I'm making has to do with partial update but I can't figure out what I'm doing wrong.
In which API level are you testing?
Maybe the problem with withpartiallyUpdateAppWidget is related to this open issue issuetracker.google.com/issues/37136552
I am trying to do widget, which will update itself on click.
Co, I created following code, which works like a charm - but only for about 20minutes then it stopped working (it does not update on click anymore, but classic widget self-update after specified period in XML works)
It starts working again if I add another instance of widget, then all intents are registered again.
Have anyone else faced the problem? Can you see something wrong with my code?
In my widget Provider:
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
final int N = appWidgetIds.length;
Log.d(tag, "onUpdate");
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_exchange_rate_small);
Intent intent = new Intent(context, ExchangeRateWidgetService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
PendingIntent pendingIntent = PendingIntent.getService(context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Register onClick action for pendingIntent
views.setOnClickPendingIntent(R.id.wdExchangeRate, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
try {
// Perform first update
pendingIntent.send();
} catch (CanceledException e) {
Log.e(tag, "First update has been canceled, this should not normally happend!");
e.printStackTrace();
}
}
How my service is declared:
public class ExchangeRateWidgetService extends IntentService {
protected void onHandleIntent(Intent intent) {
// Doing something ...
}
}
I think I solved it, the problem was in IntentService, service updated widget via remote view, but does not registered setOnClickPendingIntent.
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.
I have a widget and I want it to make a phonecall to a particular number when the user clicks on the widget. How do i do this? Please help.
I was able to get it working with this code:
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Log.d(LOG_TAG, "onUpdate(): ");
for (int appWidgetId : appWidgetIds) {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:"+number));
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, callIntent, 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.caller);
views.setOnClickPendingIntent(R.id.callButton, pendingIntent);
// Tell the AppWidgetManager to perform an update on the current App Widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
public static Intent newPhoneCallIntent(String phoneNumber){
Intent callintent = new Intent(Intent.ACTION_DIAL);
callintent.setData(Uri.parse("tel:"+phoneNumber));
return callintent;
}
startActivity(newPhoneCallIntent("5555555555"));
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);
}