Android: Service stops when Activity is closed - android

If I understand it correctly,
bindService() with BIND_AUTO_CREATE will start a service and will not die until all bindings are all unbinded.
But if I bindService(BIND_AUTO_CREATE) at onCreate() and hit back button to close the
activity, the service calls onDestroy() and dies also.
I don't call unbind() at anytime.
So is that mean when the Activity got destroyed, the binding got destroyed also and the service gets destroyed also?
What if I want the service to be always running, at the same time when the activity starts
I want to bind it so that I can access the service?
If I call StartService() and then bindService() at onCreate(), it will restart the service at every launch of Activity. (Which I don't want).
So I could I start service once and then bind next time I launch the activity?

You need to use startService so that the service is not stopped when the activity that binds to it is destroyed.
startService will make sure that the service is running even if your activity is destroyed (unless it is stopped because of memory constraints). When you call startService, the onStart method is called on the service. It doesn't restart (terminate and start again) the service. So it depends on how you implement the onStart method on the Service. The Service's onCreate, however, is only called once, so you may want to initialize things there.

I found a solution!
The problem is when you close your activity and your service is not configured as a foreground service, android system will recognize it as unused and close it.
here's an example where I added a notification :
void setUpAsForeground(String text) {
PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0,
new Intent(getApplicationContext(), MainActivity.class),
PendingIntent.FLAG_UPDATE_CURRENT);
mNotification = new Notification();
mNotification.tickerText = text;
mNotification.icon = R.drawable.muplayer;
mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
mNotification.setLatestEventInfo(getApplicationContext(), "MusicPlayer",
text, pi);
startForeground(NOTIFICATION_ID, mNotification);
}
(A foreground service is a service that's doing something the user is actively aware of (such as playing music), and must appear to the user as a notification. That's why we create the notification here)

you can do it with BroadcastReceivers. you'll find a lot on google how to use them

Related

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.

Call onDestroy() of Service

I want to call
onDestroy()
method of Service in android.
I already searched a lot on internet and many answers are like if
service force stop or somehow its onDestroy() will never call.
But I really need to know when service is stop.
My project is about music player.
So it uses service and there is an ongoing notification.
I need to find out when the service stop? and need to stop the music and remove the notification.
But it never shows any log of onDestroy().
Can anyone help me what is the alternative for it? if not onDestroy() then which method and how?
Edit:
I don't want to call onDestroy() explicitly. I want to remove notification when I remove my app from the device menu of running applications. Because when I stop my application, onDestroy() don't call and my notification remains in the status bar.
I have started my service with this code.
Intent playin = new Intent(this, MusicService.class);
startService(playin);
From within the Service class, call:
stopSelf();
From within another class, like your MainActivity for example:
Intent i = new Intent(this, ServiceName.class);
stopService(i);
Both of these will stop your service. Make sure you are returning START_NOT_STICKY so that the service doesn't start back up again.
When you want to stop your service then simply fire an intent to stop the service as shown below.
Intent intent = new Intent();
intent.setClass(getApplicationContext(), YourService.class);
stopService(intent);
This is to stop service forcefully.When you stop service in this manner it's guaranteed that onDestroy method is called by android framework.
Hope this helps to solve you issue.
I want to call onDestroy() method of Service in android.
Do not call this method directly
public void onDestroy ()
Called by the system to notify a Service that it is no longer used and
is being removed. The service should clean up any resources it holds
(threads, registered receivers, etc) at this point. Upon return, there
will be no more calls in to this Service object and it is effectively
dead. Do not call this method directly.
However you can check if the service is running or not.
I need to find out when service stop? and need to stop music and
remove notification.
Use the following way -
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
Then call it using - isMyServiceRunning(MyService.class).
Reference:
1) Service onDestroy().
2) how-to-check-if-a-service-is-running-in-android.
You should use Foreground service. In your case, I think it would be the best choice.
Foreground services show a status bar notification, so that users are actively aware that your app is performing a task in the foreground and is consuming system resources. The notification cannot be dismissed unless the service is either stopped or removed from the foreground.
To work with foreground service you first need to declare permission <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> in your manifest. It is a normal permission so doesn't requires user action.
then, you can start the service for you Activity or other component using applicationContext.startForgroundService(intent). this is to tell the system that this will be a foreground service.
You need to start the foreground service from within your service(usually in onStartCommand()) using startForeground(int, Notification) and stop the service foreground service using stopForeground(boolean)(it takes a boolean asking whether you want to remove the notification or not)
after starting foreground service, if you close your app or the service stops itself, the notification will be remove too.
Note: when you manually want to stop the service, you should call stopSelf() or stopService() as calling stopForeground() is not enough, it merely remove the notification from the status bar.

Android startForeground notification disappears

My android application starts a service to listen to headset buttons. While the service is running, I want to show a notification. Because it's also important it does not get killed, I decided to use the startForeground function in my service.
in the OnCreate of the service, I start BuildNotification():
public void BuildNotification() {
// Make sure the launch mode of the activity is singleTask, otherwise it will create a new one
Intent intent = new Intent(this, ListItemsActivityScroll.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);
// Build notification
note = new NotificationCompat.Builder(this)
.setContentTitle(getString(R.string.notification_text))
.setSmallIcon(R.drawable.vp_launcher)
.setContentText(getString(R.string.notification_content))
.setContentIntent(pIntent).build();
startForeground(1, note);
}
The first time the service is started, the notification gets displayed and stays in the status bar until the service is destroyed. However, if the service gets created for a second time, it shows only for a couple of seconds.
After it disappeared, the service is still running. I also executer 'adb shell dumpsys activity services', which does show the service to be running in the foreground and gives me also the correct flags set to the notitication:
isForeground=true foregroundId=1 foregroundNoti=Notification(contentView=com.example.mediabuttontest/0x10900a7 vibrate=null,sound=null,defaults=0x0,flags=0x62)
The 0x62 flags would mean the following are active: FLAG_FOREGROUND_SERVICE, FLAG_NO_CLEAR, FLAG_ONGOING_EVENT
Which I think is correct for keeping the notification active.
Does anyone understand this behaviour? Why it does work the first time the service is created, but not the second time? Is there any error in my code?
EDIT: Thanks for your time and comments, I've created another test application and started removing code until the problem disappeared. In the end, it was caused by enabling / disabling a broadcast receiver component:
pm.setComponentEnabledSetting(mRemoteControlResponder,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
Somehow, this makes the notification disappear. In the document it also mentions about 'DONT_KILL_APP' can make your application behave unpredicatable:
Be careful when you set this since changing component states can make the containing application's behavior unpredictable.
I guess that's true :)

Service called several times ending itself

I am starting a service with a click on a button :
Intent intent = new Intent(getActivity(), UploadService.class);
getActivity().startService(intent);
My apps makes it possible to launch several services.
I know that the first time, onCreate() is called, then if the services is running, onStartCommand() is called.
onStartCommand returns START_STICKY.
But I'm facing a strange behavior :
On the first click, the Service is called, onCreate() then onStartCommand()... etc.
On the second click, while the Service is still running, onStartCommand()... etc.
But when the first is finished, onDestroy() is called, while the second is still in progress... ?
How to avoid that?
Thanks
If you start the Service that is already running then onDestroy() of Service won't be called and the instance of Service already running will be brought to front but if your Service is finished/stopped explicitly then only its onDestroy() will be called.

Display status bar notification from service in android

Hi
i've got a kind of a dumb problem. Im trying to display a notification from a service. When an activity starts i call the startService like so:
Intent myIntent = new Intent(getApplicationContext(),notif_service.class);
startService(myIntent);
the service calculates something and should display the notification and then stop. the code is as follows:
if (limit_time_value == 2 && start >= 6300000 && notif_past)
{
notif_past=false;
showNotification();
stopSelf();
}
There are two ways that this service can be stopped, ether from itself with stopSelf() or from a button in my activity with
Intent myIntent = new Intent(getApplicationContext(),notif_service.class);
stopService(myIntent);
the problem is that even when i stop the service the notification is shown after the specified time passes. I tried to stop the setvice with Binding it and than calling onDestroy() in which I cancel the notification and again call stopSelf(). Again the notification is shown.
What am I doing wrong? Do I misunderstand how notifications or services work?
You do not indicate precisely where you are performing the work shown in your second code snippet above.
If that work is being done in onStart() or onStartCommand(), that work is being performed on the main application thread, and therefore once it starts it blocks all other main application thread work, such as stopService() and onDestroy().
If that work is being done on a background thread you create, unless you are terminating that background thread, that thread will continue to completion, regardless of whether the service is destroyed. You will need to arrange to terminate the thread yourself.
Call the instance of the NotificationManager class which you have called inside the showNotification() function.
For example, I have used:
NotificationManager nm=(NotificationManager)this.getSystemService(this.NOTIFICATION_SERVICE);
nm.notify(1,builder.build());
If you have done something like this to create your notification, use the same instance to cancel it by calling cancel() function and passing the notificationId (in this case 1).
For example:
nm.cancel(1);
Here 1 denotes the notificationID which you have provided while creating it.

Categories

Resources