WidgetProvider Intent extras sent with button click not found in onReceive - android

I am trying to detect when widget button is clicked but none of the Intent extras are showing up in the onReceive method.
onReceive gets called with every click but none of my Intent extras show up.
My code is below: I only hook up the toggle button in on update so not sure if this is correct. None of the extras show up and categories are null even though I set this.
onUpdate(Context context etc):
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.my_widget);
Intent buttonIntent = new Intent(context, MyWidgetProviderClass.class);
buttonIntent.setAction(ACTION_WIDGET_RECEIVER);
buttonIntent.putExtra("BUTTON_CLICKED", "buttonClick");
buttonIntent.putExtra("BUTTON",899);
PendingIntent muPendingIntent = PendingIntent.getBroadcast(context, 0,
buttonIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
buttonIntent.addCategory("buttonclick");
remoteViews.setOnClickPendingIntent(R.id.ToggleImageButton, myPendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
onReceive():
intent.getIntExtra("BUTTON",-1); ---> 1
intent.getCategories() --- > null

Try FLAG_UPDATE_CURRENT instead of FLAG_CANCEL_CURRENT.
Also, your code may have a typo: you have muPendingIntent instead of myPendingIntent.
Also also, please do not use buttonclick as a category. Please namespace it (e.g., com.something.whatever.buttonclick), or remove it, as I am not sure why you would need it.
Here is a sample project demonstrating an app widget that, on a click, triggers an update on itself, with an extra (used to supply the app widget IDs).

Android Apparently Does not like re-use of the name ACTION_WIDGET_RECEIVER and removes those parameters. Created another ACTION just for toggle button, registered in the manifest and now the parameters show up.

I found that if the Intent that was used to create the Pending intent has any extras already in it then the new intent's extras are ignored. For example, if you follow the sample in the Android docs for building a Widget like so
Intent toastIntent = new Intent(context, StackWidgetProvider.class);
toastIntent.setAction(StackWidgetProvider.TOAST_ACTION);
toastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, toastIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
rv.setPendingIntentTemplate(R.id.stack_view, toastPendingIntent);
Then the line
toastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
Will prevent your new intent's extras from sticking. I removed that line and my new intent worked.

Related

Implement setOnClickPendingIntent from notification

I build custom notification that contain button and i want to listin when user press on it.
The button should not open any activity but only logic staff like change song.
the Code:
RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.notification);
contentView.setTextViewText(R.id.toptext, nowPlayingTitle);
//this not work
Intent intent = new Intent(this, receiver.class);
intent.putExtra("UNIQ", "1");
PendingIntent pendingIntent = PendingIntent.getBroadcast(
this.getApplicationContext(), 234324243, intent, PendingIntent.FLAG_CANCEL_CURRENT)
contentView.setOnClickPendingIntent(R.id.imageButtonPlay,
pendingIntent);
notification.contentView = contentView;
// this is to return to my activity if click somwhere else in notification
Intent notificationIntent = new Intent(this, MYACTIVITY.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.contentIntent = contentIntent;
mNotificationManager.notify(NOTIFICATION_ID, notification);
I don't get the hang of the setOnClickPendingIntent what need to be in the second param?
How can i just call a function after user press on the button?
im probably missing something cause i dont understand the receiver side and what happend after user press
You are missing the fact that the button you created actually doesn't belong to your application. It is created in another context, in another process. There is no way it can call your function.
Instead, when the user taps the button, that pending intent is fired. You can catch it by your receiver (in your activity), check some parameters and do the action.
Or you can implement a service and handle this intent in background. I'd prefer this way.
thanks for quick answer. I try using receiver but it never fired.
The code is in the main question and i created for the reciever class the following code:
public class receiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Bundle bundle = intent.getExtras();
}
}
but click on the notification never fire the receiver ( Test on debug mode )

android widget id only for current widget

Can I get my current widgetId inside onUpdate() method of AppWidgetProvider?
I found many posts about sending appWidgetId in field of Intent, but I can't understand where I have to get it before sending.
I didn't find the methods for getting only current widget Id without configuration activities.
try in onUpdate
int a = appWidgetIds.length;
If this returns 1, then:
int yourAppWidgetId = appWidgetIds[0];
should return your appWidgetId.
EDIT
without seeing any code it´s difficult to give You the right answer, but I will give You an example. If you created your RemoteViews for your widgets, you have to create an intent for every RemoteView. At this intent, You could set an ID, for example:
RemoteViews remoteViews = new RemoteViews(getApplicationContext()
.getPackageName(),
layout.your_widget_layout);
Intent intent1 = new Intent(getApplicationContext(),
YourAppWidgetProvider.class);
intent1.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent1.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,widgetIds);
intent1.putExtra("ID", "one");
Then create a PendingIntent, which You can set to remoteViews:
PendingIntent pendingIntent = PendingIntent.getBroadcast(
getApplicationContext(), 1, intent1,
PendingIntent.FLAG_ONE_SHOT);
remoteViews.setOnClickPendingIntent(R.id.your_widget_button_id_in_xml,
pendingIntent);
If user pressed the widget, you can get id inside onReceive() with
String a = intent.getStringExtra("ID");
But this is only an incomplete example, there is a lot more to do. I think it is a good way, if you read this tutorial:
http://www.android10.org/index.php/articlesgeneralprogramming/315-app-widgets-tutorial
There is a good example with an updateService.

Android: Start Service with Context.startService vs PendingIntent.getService

Context.startService
Intent intent = new Intent(context, MyService.class);
context.startService(intent);
PendingIntent.getService
Intent intent = new Intent(context, MyService.class);
PendingIntent pi = PendingIntent.getService(context, 0, intent, 0);
pi.send();
Questions
When would you start a service with Context.startService vs a PendingIntent?
Why would you use one over the other?
There really is no difference.
Specifically the Context method is used to directly start it where as a PendingIntent is typically used with a notification to fire this intent when it is tapped, which is delayed until the user taps it (typically). However; you wouldn't typically send the PendingIntent directly because that is not what it is for.
A PendingIntent is an Intent that is pending, pending, meaning that its NOT supposed to happen now, but in the near future. Whereas with an Intent, it is sent at the very moment.
If a PendingIntent is not pending when it is used, then it is no longer a PendingIntent and it is infact an Intent. Defeating the purpose entirely.
PendinIntents are very much used for widgets. As the layout of a running widget doesn't "belong" to your code, but it is instead under control of the system, you can't assign directly click listeners to the interface elements. Instead you assign a PendingIntent to those elements (like buttons) so when the user touches them, the PendingIntent is "executed", something like:
// get the widget layout
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.id.widget_layout);
// prepare to listen the clicks on the refresh button
Intent active = new Intent(context, WidgetCode.UpdateService.class);
PendingIntent refreshPendingIntent = PendingIntent.getService(context, 0, active, 0);
remoteViews.setOnClickPendingIntent(R.id.buttonWidgetRefresh, refreshPendingIntent);
// send the changes to the widget
AppWidgetManager.getInstance(context).updateAppWidget(appwidgetid, remoteViews);
In this case a button in the widget starts a service. Usually you put extra info in the intent, with putExtras(), so the service will get any needed information to do its job.

Intent extras not removed/replaced

I am setting an alarm on a button click.
The alarm is triggered with an intent.
This intent get an extra "int" to pass to the Broadcast Receiver.
The problem is that the intent's extra gets set once on the first
click of the button and never changes on the other clicks:
Intent intent = new Intent(A.this, B.class);
intent.putExtra(WAKEUP_DURATION, wakeUpDuration);
PendingIntent sender = PendingIntent.getBroadcast(A.this, 0, intent, 0);
I tried removing it in the Broadcast Receiver, but no luck:
intent.removeExtra(A.WAKEUP_DURATION);
Use FLAG_UPDATE_CURRENT when creating your PendingIntent to update the extras from a new Intent.
Thanks! That did the trick.
For those of you who would like to know the exact answer.
The "FLAG_UPDATE_CURRENT" goes as the fourth argument in the method 'getBroadcast'.
It should look like this:
PendingIntent sender = PendingIntent.getBroadcast(A.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

android widget question

can anybody give example how to implement click event in appwidget in android ?
Thanks
You can use RemoteViews.setOnClickPendingIntent(R.id.view_id, intent) method for handle click event of app-widget. For more information you can refer below link
Click here
Use RemoteViews.setOnClickPendingIntent(R.id.view_id, intent) method.
The intent parameter should be a well formed Intent object which would match on of the filters at your manifest file.
Intent intent = new Intent(context, Activity.class);
Uri widgetId = Uri.parse("" + appWidgetId); // this line means
intent.setData(widgetId); // you can send a widget id
PendingIntent pintent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.clickButtoninWidget, pintent);
return views;

Categories

Resources