Android: How to stop service when I click on my notification - android

Is there any way that when I click on the notification and then this notification can stop the service? And my notification is in my service.
Every time when I click on my notification, the activity will run onResume() method. I cannot stop this in this onResume() since I have another notification.
My app process is: a notification helps to tell the user it is now counting down the time, and when time is up, I will begin another notification to tell the user your time is up. So, I cannot stopservice before the "timeup" notification. My thought is, When the user click on "timeup" notification, then I can stop the service.
Can I do that?

The lifecycle of an application puts OnResume at the start of every launch, so the best method would be to assign a new request code to each new notification and give the one you wish to recognize an action. If the action is received, you can stop the service. If it is not, then the app will be able to differentiate that it is a different notification and respond accordingly.
...
Intent intent = new Intent(this, TARGET.class);
intent.setAction("CUSTOM_ACTION");
PendingIntent pIntent = PendingIntent.getService(this,
(int) System.currentTimeMillis(), intent,
PendingIntent.FLAG_UPDATE_CURRENT);
...
#Override
public void onResume(){
super.onResume();
if (getIntent().getAction().equals("CUSTOM_ACTION")) {
// kill service
} else {
// other stuff
}
}

Related

How can I create an app with the behavior of the default Android "timer" app?

I want to create an app that allows the user to set a timer. When they start the timer, they see a screen with a countdown. Simultaneously, a notification appears in the system tray (the top bar). This notification contains the current state of the countdown. If the app is minimized and the user taps that notification, they return to the countdown screen in the app.
I'm trying to do this with a foreground Service, and then implementing the notification like so:
Intent notificationIntent = new Intent(this, TimerActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
PendingIntent pendingIntent = PendingIntent.getActivity(
this,
0,
notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
The problem is, this seems to restart the activity, not resume it (onCreate gets called again), so the timer appears zeroed out in the activity. Is there a way around this?

Foreground service start once and display activity on click

I have 5 activities in my app. Every activity starts the same foreground service.
In onStartCommand method of the service foreground notification is created which unfortunately means that every call of startForegroundService() in any activity plays notification sound (even though the service is already running). How can I create the foreground notification only once or at least how not to play notification sound on successive startForegroundService() calls?
The other related question is: how can I go back to my application when I click the foreground notification? I have 5 activites and I would like to reopen the activity that was the last one the user was interacting with.
#1. before starting the service just check if its already running or not. In that case this will help you https://stackoverflow.com/a/5921190/6413387
#2. To reopen your last opened activity, you need to update the pending intent of your notification. Hope you will find your answer here https://stackoverflow.com/a/20142620/6413387
How can I create the foreground notification only once or at least how not to play notification sound on successive startForegroundService() calls?
You can check if the notification is already visible and show it only if it's not visible. You need to have a reference to the notification PendingIntent and notificationId.
fun isNotificationVisible(context: Context, notificationIntent: Intent, notificationId: Int): Boolean {
return PendingIntent.getActivity(context, notificationId, notificationIntent, PendingIntent.FLAG_NO_CREATE) != null
}
how can I go back to my application when I click the foreground notification?
You need a PendingIntent to open the app from a notification. To open the last activity shown you can remember this using Preferences in the onResume() method of each activity and route the notification into a routing activity that starts the right activity according to the value saved into the preferences.
val intent = Intent(context, RouteActivity::class.java)
val notificationBuilder = NotificationCompat.Builder(context, channelId)
.setContentIntent(intent)
val notificationManager = NotificationManagerCompat.from(context)
val notification = notificationBuilder.build()
notificationManager.notify(notificationId, notification)
Another way to do this is to update the notification PendingIntent if it's already visible with the last activity shown. In this case you don't have to store any value on Preferences and you don't need a route activity.

What is the best way to finish() an activity from a foreground service without bringing the app to the foreground?

I am trying to build an app that can be used for calling.
My CallActivity is declared singleTop in the manifest file. I have a foreground service (CallService) which is started as soon as the app goes to the background while the user is on a call, since the device must not sleep during a call.
The notification for my CallService allows the user to either resume the call or hangup. My goal is to have the user press a button on the notification and hangup the ongoing call without bringing the app to the foreground.
I have tried using PendingIntent.getActivity() to start the CallActivity once the app is in background, from the CallService. But I have not been able to hangup the call yet. Here is some code...
Intent returnToCallIntent = new Intent(this, CallActivity.class);
PendingIntent returnPendingIntent = PendingIntent.getActivity(this, 0, returnToCallIntent, 0);
Intent hangUpCallIntent = new Intent(this, CallActivity.class);
hangUpCallIntent.putExtra("ACTION_FINISH_ACTIVITY", true);
PendingIntent hangUpPendingIntent = PendingIntent.getActivity(this, 0, hangUpCallIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Right now both pending intents resolve to the same action which is hanging up the call while bring the app to the foreground. I figured out that this is happening because the 2 intents only differ in their extras and hence android does not distinguish them, i.e. intent#filterEquals() does not see any difference between them.
But the more important question is how can I finish() the CallActivity and have it pop off the backstack silently, without bringing it to the foreground. Also, after the CallActivity has been stopped, I need to stop the CallService in the background. So when the user taps the app in the recents screen, she/he should see the activity which was prior to the CallActivity on the backstack.
PS: Logic to hang up the call has been done in onNewIntent() method in CallActivity.
You can have your Activity register an anonymous BroadcastReceiver that listens for a specific broadcast Intent. When your Service wants to finish the Activity, it can just send the broadcast Intent that the Activity is listening for.
In onReceive() of the BroadcastReceiver, just call finish(). This won't bring the Activity to the foreground.

Multiple fullscreen android notifications at the same time not stacking

I am working on an android project that has an alarm clock like functionality.
I schedule an intentService for each alarm instance (fires at 9pm, for example.), this intentService builds the notification and displays it. The notification includes a fullScreenIntent, which works as expected and launches the activity. I use the following code to do this:
alarmActivityIntent = new Intent(this, AlarmActivity.class);
PendingIntent alarmActivityPendingIntent = PendingIntent.getActivity(this, alertSchedule.getIntentId(), alarmActivityIntent, PendingIntent.FLAG_CANCEL_CURRENT);
mBuilder.setFullScreenIntent(alarmActivityPendingIntent, true);
Notification mNotification = mBuilder.build();
mNotificationManager.notify(alertSchedule.getIntentId(), mNotification);
This works as expected when only one alarm is set to fire at a specific time, however if two alarms are set to fire at a specific time the behavior changes.
I want the first fullScreenIntent to start its activity, then when that activity finishes, show the next one. I believe I want to build up a task stack, and push these alarm intents onto it. However this is all new to me.
Is it possible to group these notifications?
If you are using the full screen Intent feature, you don't need to use an IntentService or a Notification at all. Just have the AlarmManager start your Activity when it fires.
You don't want to build a task stack, that is all too complicated. If you have multiple alarms that can fire at the same time, you can have the AlarmManager start the same Activity each time. Set the launch mode of this Activity to singleTop (in the manifest), so that if the Activity is already showing when the alarm fires, it will not create another instance of the Activity on top of the existing one, but instead will deliver the Intent by calling onNewIntent() on the existing instance of the Activity. In onNewIntent() you can save the data (extras) of the Intent in a queue that will be processed when the user finishes the currently shown Activity. To do that, just override onBackPressed() so that when the user presses the BACK button to finish the current Activity, you can check if there are any additional alarms waiting in the queue. If there are none, you can just call super.onBackPressed() to finish the Activity. If there is anything in the queue, you can remove the first element in the queue and display that in your Activity. Keep doing that until the queue is empty.

ongoing notification opening existing Activity

I want to show a notification while a timer is running and when the user clicks the notifiaction it opens the timer activity.
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this, Activity.class).addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
The problem right now is that when I start the timer and press home and then click the notification it opens the Activity with the running timer.
But when I start the timer, then open another activity (via ActionBar.NAVIGATION_MODE_LIST), then press home and click the notification it opens a new Activity (empty).
I thought addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); would help (thats what I used to navigate between Activities)
im using android:launchMode="singleTop" and android:configChanges="orientation|screenSize"
for every Activity.
I wouldn't rely on your activity persisting and it is unnecessary
Store the timer start time into sharedpreferences and then simply load up the start time when the activity is recreated.
If something is meant to happen after a certain time, like a countdown time, then you'll need to set up an Alarm and handle it that way.
Remember that activities are just UI. Don't trust an activity to be doing anything when the user isn't looking at it.

Categories

Resources