Stopping a service passed through Notification Intent - android

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

Related

Does a Pending Intent have a lifetime?

I have an application which in turn runs a foreground service. The application has a start/stop button as part of its notification which as can be guessed starts and stops the foreground service. Upon clicking on the start button a Pending Intent gets triggered.
Consider the following scenario:
The application has been destroyed [removed from the recent items list] but the notification is still visible.
I am able to start and stop the foreground service even when the app has been destroyed, as on clicking the notification button triggers a Pending intent (which in turn call a broadcast receiver).
But, what I have observed is that after a day or two, upon clicking the buttons on the notification the pending intent is not triggered (that is the foreground service does not start). This begs the question, does pending intent have a lifetime after the encompassing application has been destroyed? Or am I missing something else here?
My pending intent call:
Intent notificationBroadcastIntent = new Intent(this, MyBroadcastReceiver.class);
PendingIntent playIntent = PendingIntent.getBroadcast(this, MY_REQUEST_CODE,
notificationBroadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);
The Broadcast Receiver called by the pending intent (which in turn starts the foreground service):
#Override
public void onReceive(Context context, Intent intent) {
Log.i(MyBroadcastReceiver.class.getSimpleName(), "MyBroadcastReceiver called to update service notification");
if (isMyForegroundServiceRunning(MyForegroundService.class, context)) {
Intent stopIntent = new Intent(context, MyForegroundService.class);
stopIntent.setAction(STOP_SERVICE_ACTION);
context.startService(stopIntent);
} else {
Intent startIntent = new Intent(context, MyForegroundService.class);
startIntent.setAction(START_SERVICE_ACTION);
context.startService(startIntent);
}
}
PendingIntents do not expire. However, they are not persistent and will not survive a reboot of the device.
To see if the PendingIntent still exists, you can use the following adb command:
adb shell dumpsys activity intents
This lists all of the PendingIntents in the system. You can also look at the notifications using:
adb shell dumpsys notification
This will show all Notifications, including the PendingIntents that are set for them.

Auto open Activity when notification is send without clicking on notification

Is it possible to perform some function in an app activity when the notification is sent, without the user clicking on the Notification bar?
Example: I have an onClick method which is needed to be called when Notification is sent.
Yes from notificationReceiver onReceive() method you can directly call startActivity like below
Intent resultIntent = new Intent(getApplicationContext(), ActivityName.class);
resultIntent.setData(Uri.parse("content://"
+ Calendar.getInstance().getTimeInMillis()));
resultIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(resultIntent);

How can I start MainActivity(That its app compeltely killed) from the runnning service again when new data recieving from server(as an event)?

This is the scenario...
App is opened
User clicks on a button that starts a service.
(Service always is run in background and check recieving new data from server)
User presses home key and then long presses home key and clears application from task list completely.
Service continues to run, although app has closed.
I can determine whether that app has been killed or not by reading this link:
How to determine app is running from service
How can I start MainActivity(That its app compeltely killed) from the runnning service again when new data recieving from server(as an event) ?
You can broadcast an action and use a BroadCastReceiver to receive it and start the MainActivity from onReceive method of the BroadCastReceiver:
public void onReceive(Context context, ...)
{
Intent intent = new Intent(context,MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
or from a service use:
Intent intent = new Intent(this,MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

Can an activity be triggered immediately when a notifcation arrives?

I need to implement this feature but I am not sure if this is possible on android.
We have gcm listener service running. But let's say the app is open, and a notification arrives from the server. I need to have an activity triggered automatically without touching the notification status bar on the top of the phone screen.
In other words, without any user interaction once the notification arrives, if the app is running, an activity must be triggered immediately.
I took a look at this thread, but this is not really what I need.
Intent - if activity is running, bring it to front, else start a new one (from notification)
any clues or more info?
thx!
You can start an activity without another prior activity by using the FLAG_ACTIVITY_NEW_TASK flag.
Context c = getApplicationContext(); // or getContext(), or any other context you can find from the current app
Intent i = new Intent(c, YourActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);

How to start an app the same way Android Launcher does (resume)

There are a lot of questions/answers about how to start an application from within your application in Android. But those solutions do not produce the same flow as if an icon was tapped in Android launcher.
For example, I do this (this is used with notifications):
intent = context.getPackageManager().getLaunchIntentForPackage("com.test.startup");
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
pendingIntent = PendingIntent.getActivity(context, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
Then when I tap on notification the app is started, however, it is started somewhat differently than when I tap the icon in the App drawer. Specifically: with this approach my main Activity is always created (i.e. onCreate() then onResume() is called). However, if application was already started and then put in background, then starting it from Launcher will only cause onResume() of currently shown activity to be called (not onCreate() on the main one). Is there a way to trigger the same resume flow programmatically from within my app?
To summarize the task: when user taps on notification I need my app to be either started (if it's not already), or brought to the foreground in its current state (if it's in background) and have some data passed to it. The app will then take care of handling/rendering that data.
Your app is behaving the way it supposed to. Even if you try the launch the app from App drawer it will call the same callback. You have to understand the lifecycle. As your activity is in the background onCreate will not get called. But for the handling the data from the notification intent you should utilize callback method OnNewIntent() in activity. You should override this method and extract the data the from the new intent and should update UI. After onNewIntent onresume will be called.
I hope this solves your problem.
Here is my onPause code which works the way you expected i.e when user clicks on the notification it doesnt call onCreate again:
notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
intent = new Intent(getApplicationContext(), PlayerActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pIntent = PendingIntent.getActivity(getBaseContext(), 0, intent,0);
NotificationCompat.Builder noti =
new NotificationCompat.Builder(this)
.setSmallIcon(android.R.drawable.ic_media_play)
.setContentTitle("Nepali Music And more")
.setContentText("Playing");
noti.setContentIntent(pIntent);
noti.setAutoCancel(true);
noti.setOngoing(true);
Notification notification = noti.getNotification();
notificationManager.notify(1, notification);
Focus mainly on the intent flags
You want to use the intent flags Intent.FLAG_ACTIVITY_CLEAR_TOP to find your activity and clear the stack above it. You also need the Intent.FLAG_ACTIVITY_SINGLE_TOP flag to prevent your activity from being recreated (to resume).
The Intent.FLAG_ACTIVITY_SINGLE_TOP is necessary since by default, the launch mode is "standard" which lets you create multiple instances of your activity. If you were to set your launch mode to SingleTop, then this flag own't be necessary

Categories

Resources