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.
Related
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
I've added a widget for my application, basically clicking on the widget enables a service.
But sometimes i experience random enabling of the service even if i didn't press the widget
I followed the android developer guide to make the widget and the code looks like this
public class ToggleWidget extends AppWidgetProvider {
static RemoteViews remoteViews;
boolean status = false;
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
// Perform this loop procedure for each App Widget that belongs to this provider
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
remoteViews = new RemoteViews(context.getPackageName(), R.layout.toggle_widget);
Intent intent = new Intent(context.getApplicationContext(), WakeService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
PendingIntent pendingIntent = PendingIntent.getService(
context.getApplicationContext(), 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.bulb_widget, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
context.startService(intent);
Log.w(getClass().getName(), "Widget Worked");
// Tell the AppWidgetManager to perform an update on the current app widget
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
}
}
This code should run the service intent when i click the ImageButton.
Clicking on it works as it should, but i get those random enablings (the service displays a notification when it's enabled, so i know it's running)
Can you spot something wrong in the code?
Take out
context.startService(intent);
Since the PendingIntent already starts the Service when the widget is clicked, having an explicit context.startService() in onUpdate() will make the Service start regardless of whether or not the widget is clicked.
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 =]
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 which is basically a big button (with some images in the background). The button works fine if there's just one widget on the home screen (or more than one after a phone reboot), but if I try to add another widget, the button suddenly stops reacting (on the second widget).
Been struggling with this for months now. Hopefully you'll be able to assist.
public class StatsWidget extends AppWidgetProvider {
public static String ACTIONWIDGETCLICK = "MyWidgetClick";
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Intent intentt = new Intent(context, StatsService.class);
context.startService(intentt);
final int N = appWidgetIds.length;
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.main);
Intent intent = new Intent(context, StatsWidgetActivity.class);
intent.setAction(ACTIONWIDGETCLICK);
intent.putExtra("widgetId", appWidgetId);
PendingIntent pendingIntent = PendingIntent.getActivity(context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.widget_button, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}
The only error I see in your code is you forgot to add
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
This must be used when starting an Activity from a service/broadcastreciever/etc. Otherwise are you updating the widget from anywhere else in your app? I recently had a problem with the pending intent unresistering itself because I updated the widget from within my app and didn't add the
views.setOnClickPendingIntent(R.id.widget_button, pendingIntent);
to the update code.
Hope this helps