Intent extras not removed/replaced - android

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

Related

Android Pending Intent to start service

So I have a service, in the onCreate() I setup 3 pending intents to start the same service, each having different extra data to specify the action. I'm creating a notification, and I want to use one pending intent as the click action, one as the dismiss action, and the third is for an alarm.
Intent iCancel = new Intent(this, BootService.class);
Intent iAlarm = new Intent(this, BootService.class);
Intent iDismiss = new Intent(this, BootService.class);
// each will have actions
iAlarm.putExtra(INTENT_ACTION, INTENT_ALARM_FIRED);
iCancel.putExtra(INTENT_ACTION, INTENT_CANCEL);
iDismiss.putExtra(INTENT_ACTION, INTENT_DISMISS);
PendingIntent piCancel = PendingIntent.getService(
this,
0,
iCancel,
Intent.FILL_IN_DATA);
mPiAlarm = PendingIntent.getService(this, 0, iAlarm, Intent.FILL_IN_DATA);
PendingIntent piDismiss = PendingIntent.getService(this, 0, iDismiss, Intent.FILL_IN_DATA);
mNotifyBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_action_about)
.setContentTitle(getString(R.string.app_name))
.setContentIntent(piCancel)
.setDeleteIntent(piDismiss);
The problem is all pending intents seem that have the same intent extra data, so when onStartCommand is launched no matter whether the notification was clicked or dismissed or neither, constant INTENT_CANCEL is received from intent.getIntExtra(INTENT_ACTION)
I believe it has something to do with the flags used in PendingIntent.getService(), i'm confused about which to use. I've tried using PendingIntent.FLAG_CANCEL_CURRENT, and UPDATE_CURRENT, neither seem to fix the issue but the result is different, I receive constant INTENT_ALARM_FIRED for every action.
How can I get each pending intent to have its own intent extra data?
Solution
I discovered an exact warning about this scenario right in the PendingIntent doc. http://developer.android.com/reference/android/app/PendingIntent.html
just changed my request codes and it works
This has to do with Intents being considered the same. See PendingIntent for more information.
One way to get around this would be to just vary the requestCode for each Intent. (The 2nd parameter in the getService call)

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: 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.

WidgetProvider Intent extras sent with button click not found in onReceive

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.

Android appwidget, can i put buttons on it?

I would like to add twoo buttons on an appwidget, then i would like to set the onclicklistener methods of this.
Is there a way to do it? how?
RemoteViews views = new RemoteViews(context.getApplicationContext(), R.layout.main_view);
Intent intent = new Intent(context, InputBroadcastReceiver.class); // receiver class
intent.putExtra(EXTRA_ID, id); // some extras
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT); views.setOnClickPendingIntent(R.id.my_button, pendingIntent);
Then override the onReceive method in InputBroadcastReceiver and enjoy your inputs ;)
BroadcastReceivers are explaining here.

Categories

Resources