I have the method
private Notification getNotification() {
Activity currentActivity = MyApplication.getApplication().getCurrentActivity();
Intent i = new Intent(currentActivity, SpeechActivationService.class);
i.putExtra(ACTIVATION_STOP_INTENT_KEY, true);
PendingIntent resultPendingIntent = PendingIntent.getActivity(currentActivity, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action action = new NotificationCompat.Action(R.drawable.ic_mic_off, "Deactivate", resultPendingIntent);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_mic)
.setTicker("TickerSample")
.setWhen(System.currentTimeMillis())
.setContentTitle("My App Voice Control")
.setContentText("Voice Control is Activated")
.addAction(action)
.build();
return notification;
}
It is supposed to make a notification which stays active for as long as the service is active. The notification has a DEACTIVATE Button, which can send an Intent, wrapped in a Pending Intent (whatever the difference is?!). It seems Intents are the only form of Action a notification can take for handling Button clicks, so I can't just do
stopService(new Intent(this, SpeechActivationService.class));
on that DEACTIVATE. But with my code onStartCommand() in SpeechActivationService never gets called when I click on DEACTIVATE. And Services don't inherit an onNewIntent() method. So what method gets called when I send this intent by pressing DEACTIVATE?
So what method gets called when I send this intent by pressing DEACTIVATE?
Nothing will. You are attempting to use a getActivity() PendingIntent with an Intent that points to a service. This will not work, and you should be getting messages in LogCat to that effect.
If you change getActivity() to getService(), then onStartCommand() of your service should be called.
Pending intents is ment to be used for controlling stuff outide of your app (system features use those). For stopping service create BroadcastReceiver, which will receive pending intent (PendingIntent.getBroadcast()), which, in turn, will stop your Service
Related
I am working on an functionality where I get notification for POI (Point of Interest )while the user is navigating through Google Navigation app (used background service to get location update ).
scenario
1) User clicks navigate button from my app
2) He is taken to Google Navigation with data to navigate
3) Now user receives Notification for POI , then he clicks on it and he is taken to my app (my app brought to foreground , still Google Navigation i in background)
4) Now user is seeing my app , now he clicks the same notification , In this case I must put my app to background , so that use now sees Google Navigation
what i tried
Bringing my app to foreground is achieved , but putting my app to background on Notification click is not achieved .
moveTaskToBack(true) this is what I came across, but how can I implement this in Notification click
code
Intent intent = new Intent();
intent.setComponent(new ComponentName(getPackageName(), B_Activity.class.getName()));
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("toFront", toFront);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
moveTaskToBack(boolean bool) is a method Of Activity class . So you can only call it with activity reference. I don't thing that there is way to do it with intent . What you can do send a broadcast in notification intent, and then validate the intent in activity if its in foreground -> call movetaskBack().
If your B_Activity has no Ui . Then just set null component in Pending Intent.
Use Local Broadcast to notify your currently running activity to call moveTaskToBack().
Intent intent = new Intent();
intent.setAction("com.settaskback");//Your custom action goes here
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
Then send broadcast on notification click. The activity which will receive this broadcast will put task to background (only if its in forground)
final Intent broadcastIntent = new Intent("com.settaskback");
PendingIntent intent = PendingIntent.getBroadcast(getApplicationContext(), 0, broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder.setContentIntent(intent);
notification = notificationBuilder.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, notification);
You need to register a Local broadcast receiver for this action in Activity.
#Override
public void onReceive(Context context, Intent intent) {
if(somecondition){
moveTaskToBack(true);
}
}
Using Xamarin.Android.
I have a BroadcastReceiver:
public class MyBroadcastReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
try
{
string someExtra = intent.Extras.GetString("someExtra", string.Empty);
}
catch (Exception)
{
}
}
}
I use a Google Cloud Messaging Service and create a notification when receive some message. Using a notification builder's SetContentIntent I export some extras to the activity that will operate this notification if user opens it. And it works. But when I initialize my notification builder with SetDeleteIntent inside the GCM Service, the notification does not trigger OnReceive in the BroadcastReceiver if user swipe to dismiss the notification.
When I do all the same inside my activity (not inside the GCM service) OnReceive is triggered on every notification's swipe-to-dismiss event. But it does not work inside the service.
I have even implemented the same CreateNotification method in my activity as in the service. When I call it (to create the notification) from my activity - all works perfect. When I call it from the service using a static pointer to the current instance of the activity - MyActivity.CurrentInstance.CreateNotification(...) - my notification does not react on swipe-to-dismiss event. I even tried to put the CreateNotification's code in RunOnUiThread - no result.
Therefore, notification's swipe-to-dismiss event is triggered only in case if that notification has been created in my activity. But I create notifications when receive messages from GCM. It actually creates notifications even when application is not running.
public void CreateNotification(........) {
//RunOnUiThread(() => {
var notificationBuilder = new Notification.Builder(this);
notificationBuilder.SetContentTitle(title);
notificationBuilder.SetContentText(description);
notificationBuilder.SetSmallIcon(Resource.Drawable.Icon);
var notificationIntent = new Intent(this, typeof(MainActivity));
notificationIntent.PutExtra(.......)
var contentIntent = PendingIntent.GetActivity(Application.Context, 0, notificationIntent, PendingIntentFlags.CancelCurrent);
notificationBuilder.SetContentIntent(contentIntent);
// Actually my headache
const String NOTIFICATION_DELETED_ACTION = "NOTIFICATION_DELETED";
var receiver = new MyBroadcastReceiver();
RegisterReceiver(receiver, new IntentFilter(NOTIFICATION_DELETED_ACTION));
Intent intent = new Intent(NOTIFICATION_DELETED_ACTION);
intent.PutExtra(.......)
var deleteIntent = PendingIntent.GetActivity(Application.Context, 0, intent, PendingIntentFlags.CancelCurrent);
notificationBuilder.SetDeleteIntent(deleteIntent);
var notificationManager = GetSystemService(Context.NotificationService) as NotificationManager;
notificationManager.Notify(1, notificationBuilder.Build());
//});
}
Any ideas how to create a notification (inside the service) that will be able to trigger its swipe-to-dismiss event?
notification's swipe-to-dismiss event is triggered only in case if that notification has been created in my activity
When you When you use SetDeleteIntent(deleteIntent) method, make sure your deleteIntent is initialized by using PendingIntent.GetBroadcast method.
GetBroadcastet means retrieve a PendingIntent that will perform a broadcast, like calling Context.sendBroadcast(). When you use GetActivity method, it means retrieve a PendingIntent that will start a new activity. That's reason that your notification does not trigger OnReceive in the BroadcastReceiver. For more information you could read this document.
Modify your code :
var deleteIntent = PendingIntent.GetActivity(Application.Context, 0, intent, PendingIntentFlags.CancelCurrent);
To :
var deleteIntent = PendingIntent.GetBroadcast(Application.Context, 0, intent, PendingIntentFlags.CancelCurrent);
Then in your GCM Service, your notification's swipe-to-dismiss event will be triggered .
I have to make a server call when i dismiss the notification (simply slide it) from my android application, Which event i have to call or what i have to include when in am building the notification ?
I think Notification.deleteIntent is what you are looking for. The doc says:
The intent to execute when the notification is explicitly dismissed by the user, either with the "Clear All" button or by swiping it away individually. This probably shouldn't be launching an activity since several of those will be sent at the same time.
DeleteIntent:
DeleteIntent is a PendingIntent object that can be associated with a notification and gets fired when the notification gets deleted, ether by :
User specific action
User Delete all the notifications.
You can set the Pending Intent to a broadcast Receiver and then perform any action you want.
Intent intent = new Intent(this, MyBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, intent, 0);
Builder builder = new Notification.Builder(this):
..... code for your notification
builder.setDeleteIntent(pendingIntent);
MyBroadcastReceiver
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
.... code to handle cancel
}
}
I'm able to queue and launch notifications through AlarmManager, I'm also able to launch my application when clicking the notification. Unfortunately the notification isn't removing itself when the application is launched.
Notification setup:
Intent intent = new Intent(mainActivity, NotificationPublisher.class);
intent.setAction("handle");
PendingIntent pIntent = PendingIntent.getBroadcast(mainActivity, 0, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
Notification.Builder builder = new Notification.Builder(mainActivity)
.setSmallIcon(R.drawable.phone)
.setContentTitle(title)
.setContentText(textContent)
.setAutoCancel(true)
.setContentIntent(pIntent);
return builder.getNotification();
The notification click broadcasts and hits this function:
void handle(Context context, Intent intent) {
System.out.println("handle");
Context mainContext = Extension.mainContext;
Activity mainActivity = Extension.mainActivity;
Intent launchIntent = new Intent(mainContext, mainActivity.getClass());
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(launchIntent);
}
The handle function will launch the activity but not remove the notification from the status bar. Interestingly... If I remove the call to startActivity, the notification will close.
Things I've tried:
Setting the auto cancel flag manually
Using the builder.build() instead
NotificationManger cancel(id) and/or cancelAll
Using NotificationCompat.Builder
Using a regular launch intent for the setContentIntent instead of manually calling startActivity
Based on this statement from your question:
Interestingly... If I remove the call to startActivity, the
notification will close.
I'm assuming that your Activity is just reposting the Notification.
I worked around this by launching my App 300ms after clicking the notification.
I am using an Activitiy with various Tabs on it. From a different part of the application, Notifications are created to tell the user that something has changed. I now managed to Call the Activity, when the user clicks on the Notification. But how can i determine wheter a Activity is created the "normal" way during runtime or by clicking on the notification?
(Depending on the notification clicked, i want to forward to another tab instead of showing the main Tab.)
Intent intent = new Intent(ctx, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0, intent, 0);
// TODO: Replace with .Build() for api >= 16
Notification noti = new Notification.Builder(ctx)
.setContentTitle("Notification"
.setContentText(this.getName())
.setSmallIcon(R.drawable.icon)
.setContentIntent(pendingIntent)
.setDefaults(
Notification.DEFAULT_SOUND
| Notification.DEFAULT_LIGHTS)
.setAutoCancel(true)
.getNotification();
NotificationManager notificationManager = (NotificationManager) ctx
.getSystemService(Context.NOTIFICATION_SERVICE);
// Hide the notification after its selected
notificationManager.notify(this.getId(), noti);
This successfully calls my MainActivity. But is there some Method that is called when the Activity is triggered by the pendingIntent?
Thought about to define something like this in the Main Activity:
onTriggeredByNotification(Notification noti){
//determinte tab, depending on Notification.
}
Pass a boolean value from notification and check for the same in the onCreate method of the activity.
Intent intent = new Intent(ctx, MainActivity.class);
intent.putExtra("fromNotification", true);
...
if (getIntent().getExtras() != null) {
Bundle b = getIntent().getExtras();
boolean cameFromNotification = b.getBoolean("fromNotification");
}
You can try this in your Notification
Intent intent=new Intent();
intent.setAction("Activity1");
In the Activity override onNewIntent() method and get action so you can determine the activity is called or not.
Better than using the reserved action field of your intent as specified by #ricintech, you could use an extra parameter in your pending intent and detect it in your onCreate method and in your onNewIntent metod inside your activity.