android - set both class and action for intent - android

I have an Intent that I initiate like this:
notificationIntent = new Intent(context, HomeActivity.class);
This intent is attached to an ongoing notification.
Now, in addition to the class opened when clicking the intent, I want to add an action string to the intent, so that when the notification clicked my custom BroadcastReceiver that listens to the same action string will trigger.
notificationIntent.setAction(context.getString(R.string.notification_clicked_action_string));
Problem is, for some reason, the BroadcastReceiver is not called, and I have other BroadcastReceiver that I registered problematically like this and they work fine.
So, it is a problem to have both a class and an action in an intent?

So, it is a problem to have both a class and an action in an intent?
No, that is perfectly fine.
However, unless you have a very strange naming system, HomeActivity is an activity. That means that new Intent(context, HomeActivity.class) identifies that activity, and you are hopefully using that with PendingIntent.getActivity(). You cannot have a BroadcastReceiver respond to startActivity(), which is what will be called when the PendingIntent is invoked.

Related

Cancel a notification inside a Bundle created using setGroup

I have multiple notifications stacked in a bundle created using the:
setGroup("groupname");
and the
setGroupSummary(true);
methods.
Each notification has an action. The intent inside the action pendingIntent contains the notification id which can be used to cancel the notification.
When the notifications are NOT bundled into a group and displayed inside a summary notification, calling NotificationManager.cancel(id) cancels the notification promptly.
However, If the notifications are grouped and ARE summarized, the NotificationManager.cancel(id) does nothing.
Can anyone tell me how to solve this.
The pending intent for action is as follows:
Intent notificationSettingsIntent = new Intent(context.getApplicationContext(), NotificationSettingsActivity.class);
notificationSettingsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
notificationSettingsIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
notificationSettingsIntent.putExtra("fromNotification",true);
notificationSettingsIntent.putExtra("notif_id",counterOfValidNotifications+6666);
//Log.d("FragmentCreate","Setting notif_id inside action button "+(counterOfValidNotifications+6666)+" for restid "+c.getInt(restidindex));
PendingIntent notificationSettingsActivityPendingIntent = PendingIntent.getActivity(context,(int)(System.currentTimeMillis()%10000),notificationSettingsIntent,PendingIntent.FLAG_ONE_SHOT);
notificationBuilder.addAction(R.drawable.ic_notifications_off_black_24dp,"Notification Options",notificationSettingsActivityPendingIntent);
The notif_id inside this intent is received inside the activity specified and here i basically call cancel(id).
(int)(System.currentTimeMillis()%10000)
This is not enough. If all your notifications are created within the millisecond they'll have just one PendingIntent. You set the flags as oneshot, so after the first one they won't be even delivered.

Notification with button that upon click take an action without opening activity

I am trying to create a notification where I add button to it that would basically do some action. I know I can do the following
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(con)
.setSmallIcon(image)
.setContentTitle("title")
.addAction(icon, title, intent)
My questions are:
1) Is adding button supported in API 5.0+ ONLY or also in 4.x? I read different answers about it
2) The action seems to be associated with opening an activity. Is there away I can have it so when you click on a button it takes an action without having to open the activity (Either through broadcast receiver or some other way)? As far as I know Intent opens activities.
Thank you so much
It will work in Android 4.1 and later. See official doc.
If you want to do action with out any UI update(i.e., showing any activity), I suggest send a pending intent(which will trigger a broadcast receiver) as a parameter for notification action
i) Create a BroadcastReceiver named MyBroadcastReceiver
ii) Add your action in BroadcastReceiver's onReceive method
iii) Create a PendingIntent
Intent mIntent = new Intent(this,MyBroadcastReceiver.class);
PendingIntent mPendingIntent = PendingIntent.getBroadcast(this, 0, mIntent , 0);
iv) Add it to Notification
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(con)
.setSmallIcon(image)
.setContentTitle("title")
.addAction(icon, title, mPendingIntent)
1) Is adding button supported in API 5.0+ ONLY or also in 4.x?
It will work in Android 4.1 and later. See official doc.
2)...As far as I know Intent opens activities.
Yes, you can use BroadcastReceiver or Service for executing logic that doesn't involve UI. First of all, you can build intent to launch activity, broadcast receiver, or service. Secondly, the third argument of NoticiationCompat.Builder#addAction is PendingIntent, not an Intent. You can use PendingIntent.getService to create an PendingIntent for service, for instance.
http://developer.android.com/reference/android/app/PendingIntent.html#getService(android.content.Context, int, android.content.Intent, int)

Unable to retrieve new intent extras

I'd like to ask you for help as after trying to figure this issue out for a couple of hours still can't get it works.
I have a notification manager which process incoming GCM messages and creates notifications, however an intent, that is passed to pending intent, always got old extras (intent recycle) within activity.
intent.putExtra("user_id", id);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
builder.setContentIntent(PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
Lets say that I will receive two notifications from two different users and intent starts the same activity which displays that user ID. After click on first notification, activity is launched as usually and intent's extras contains user ID of first user. However, if I will remain within this activity, and click on another push notification, an activity is recreated (onDestroy is called) but, intent's extras contains user id of first user, not the second one.
Here is my question. How can I retrieve new intent extras? I've already tried to implement onNewIntent callback method, but it never get called, also tried to change flags but unsuccessfully and what's kinda weird to me is, that even after onDestroy callback is called, intent extras in next instance of that activity have old data...
Thanks in advance
You need to pass unique Id in place of just 0 when fetching Activity from PendingIntent:
int iUniqueId = (int) (System.currentTimeMillis() & 0xfffffff);
builder.setContentIntent(PendingIntent.getActivity(context, iUniqueId, intent, PendingIntent.FLAG_UPDATE_CURRENT));
I think you fire your notifications either with the same id or with a inappropriate intent flag. As it is mentioned here, when creating the pending intent you can set its flag. If you don't like the previous pending intent to be updated or overridden, you should set its flag to FLAG_ONE_SHOT. It indicates that although you have more than one pending intents sticking around in the system, each can be executed only once!
Conclusion: Your code should be sth like this:
PendingIntent pIntent = PendingIntent.getActivity(context, id,intent,PendingIntent.FLAG_ONE_SHOT);
In this code the "id" is unique per pending intent and "intent" is the actual intent for the target activity.
Cheers

Stopping a service passed through Notification Intent

In my app I have a notification in the task bar and when clicked it starts a new Activity view of my program. However when I try and use the stop button to stop my service from within this view, nothing happens. I am assuming when I press the notification button that it does not keep my ACTIVITY linked with the service.
When my app is first opened, the service is started by using the Intent below:
Intent svc = new Intent(this, StreamService.class);
startService(svc);
Then in the service:
//Intent passed when notification is selected.
Intent notificationIntent = new Intent(this, HomeActivity.class);
Any idea how to link back to my running service? Or perhaps bring the original activity/view back to the front when the notification is selected?
The Intent that you can attach to the notification should have a service intent, with a specific action. In your service's onStart method, you can check it's a close action, and then you can call stopSelf().
If the Activity you are opening from the notification is part of the same application as the service, then it is be able to stop the service. Try to use:
Intent svc = new Intent(this, StreamService.class);
stopService(svc);

Correct way of handling (pending) intents in AppWidgets

I have a question regarding AppWidget intent handling. I have a widget which is clickable, and on click I want to send an intent to the AppWidgetProvider itself for further processing.
The problem: I receive the intents initially in onReceive(), but after a while (not sure what causes it), onReceive() is no longer called.
I have the following code, all in MyWidgetProvider extends AppWidgetProvider.
a) register for receiving broadcasts:
in onEnabled(...):
context.getApplicationContext().registerReceiver(this, new IntentFilter(MY_ACTION));
b) set intent to be fired on click:
in onUpdate(...)
Intent intent= new Intent(MY_ACTION);
PendingIntent pendingIntent= PendingIntent.getBroadcast(context, 0/*notusedanyway*/, intent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.widget_root, pendingIntent);
c) react to event and do something:
in onReceive(...)
if (MY_ACTION.equals(intent.getAction())
doSomething();
When I deploy + add a widget, it works fine. However, after a while - not sure what exactly causes the problem, but a phone call, for example, seems to affect it - I no longer get any notifications in onReceive().
I am completely stumped why this is the case. Can someone point out to me the correct way of doing this?
Thanks!
Tom
You should use a BroadcastReceiver registered in your AndroidManifest.xml file. When you register it in onEnable it is tied to the process. Whenever Android kills your process (for example, when a phone call is received) then your receiver no longer exists and (as you observed) no longer works.

Categories

Resources