I have an application which is doing some repetitive background tasks. I'm using service and Alarmmanager with setrepeating method. The only way to stop this service is a button which appears on my activity screen (of course android system can kill it for any reason at any time but I don't care what android system does). My problem is when my activity is destroyed by android system after a while, I have a service which is running forever unless Android kills it. My question is how can I get a reference of this service to stop it after creating new activity(I assume I'm creating new activity after the old one destroyed)?.
Consider bindService and unbindService.
When your activity is created, you can call bindService, and use the returned binder in order to communicate with your service. A service can be both bound and started, in case you don't want unbind to kill your service after your activity ends.
Another approach could be using a LocalBroadcastManager in order to communicate between your activity and service.
Finally, consider either Otto or Eventbus - two awesome opensource projects for communicating between components in your android project.
Use the bind service and unbind service methods on your MainActivity so that you can call unbind service onDestroy() when ever your apps activity is either explicitly destroyed by user or the android system, the service class is destroyed alongside.
Use this post as a guide: Example: Communication between Activity and Service using Messaging
I think I couldn't explain my problem clearly. But I found my answer at this post How to get reference to running service?
Dawid Sajdak answer
private boolean isMyServiceRunning() {
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if ("your.service.classname".equals(service.service.getClassName())) {
return false;
}
}
return true;
}
if(isMyServiceRunning()) {
stopService(new Intent(ServiceTest.this,MailService.class));
}
Related
I have a public class Tracking extends Service witch is called from practically every activity with something like this:
Intent serviceIntent = new Intent(this, Tracking.class);
serviceIntent.putExtra("name", "Tabla3b Kras");
serviceIntent.putExtra("time", TimeGenerator.getTime());
startService(serviceIntent);
And that works fine, public void onCreate()is called only the fisrst time and, public int onStartCommand(Intent intent, int flags, int startId) is called every other time.
The problem I have is that when the user closes the app. Let's say double back press or going in the open apps list and dismising it. I get a "Unfortunately, "appname" has stopped working.
I know that I can close the service in onStop(), but since I am calling the service from almost all the activities do I have to implement onStop() in all of them or is it enough to just do it in MainActivity.java? And will the service stop if the user changes between activities?
Service is a background process. It is not meant to start/stop from every activity.
You can start your service only once in your app. Like you started in your first activity (splash) or application level class. You don't need to start service in every activity.
Same you don't need to stop your service from every activity. You can stop your service once when you handle onBackPress().
How do I then pass variables to the service from other activites?
There are several ways you can communicate between Activities & Services.
Use Binder. You can follow this answer.
You can use Handler. Follow this.
You can use BroadcastReceiver. Follow this.
Use EventBus by GreenBot. This library is getting popular now a day becasue of ease of implement.
If you ask my preference, I used BroadcastReceiver & Binder earlier days. But now I use EventBus. You can simple implementation steps in EventBus documentation.
Suggestion:
Check if your service is already running or not. Start service before use if not running.
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;
}
I have an app which has a single activity which has a checkbox the starts and stops a foreground service. The activity also has some other settings which control that service.
The problem is that after some time navigating other apps the service continues to run fine but the activity gets killed. If I restart the activity the checkbox will be set to default, off. If I switch it to on, a second service starts, while the first one is still running and can't be controlled anymore.
I can't figure out how to handle this situation. It's necessary for the service to run indefinitely and there doesn't seem to be anyway to keep the activity from dying. Maybe there's a way for the new activity to find the old service?
Try to kill the service in OnPause() method of your activity .that solve my problem few times ago.
To check if particular service is running, write the below method your activity, and call it when you want to check the state of the service
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;
}
"service continues to run fine but the activity gets killed"
services are given more importance than activities, if android where given a choice to kill an activity or a service it always kill an activity first.
"a second service starts"
services can only be started once no matter how many times you start a service.
"checkbox will be set to default"
use sharedpreferences to persist values.
I have a Foreground Service for my app, which must run the whole time and never stops. While I was testing it few times, it seems after 3-4 days Android decides it just to stop it, and never restart it again, and in my Activity I have a check for the service if its running, and if it isnt to start it.
Even though, the service is not starting, and I can't debug it, because this is not happening immidiatelly.
So this is my check, is there something wrong in it?
if (!isMyServiceRunning(MyService.class)) {
startService(new Intent(this, MyService.class));
}
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;
}
I call this check in onResume() of the Activity, and I can't just run it everytime when the activity starts, because I have a constantly running Thread in the service, which will get more than one instance if started several times...
So here is what I want:
Either have more reliable way to check for the service if its running
or
Just start the service every time the activity starts, to prevent problems, and the thread inside of it must always have just 1 instance (I have already declared is as static)
You can make your service Bindable and bind your Activity to the service when the Activity starts/resumes. This way you will be sure the service is running. But I think you have a problem with your service. My I ask you to post more information about the service? It is not normal the OS to kill a foreground service with no traces.
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.
I have read the other threads about checking if a service is running but this is not working for me.
My situation is that am creating a background web server service but not binding to it because I want it to continue running after the activity ends. The service creates a notification so users can see it is running. The user can stop the service through a button on the Activity.
This is all working fine, except on launch of the activity, I can't determine if the service is already running. Am using the following:
if (isMyServiceRunning() == false)
{
Intent ws = new Intent(this, WebServerService.class);
startService(ws);
}
And this
private boolean isMyServiceRunning() {
String sClassName;
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE))
{
sClassName = service.service.getClassName();
DebugMsg("Service: " + sClassName);
if (sClassName.contains("com.<mydomain>.webservice"))
{
return true;
}
}
return false;
}
I get a list of services running, for both system and 3rd party services. But my service doesn't show up in the list, even though I know it's running. If I go into the phone's Settings -> Applications -> Running Services, I can see it running there.
I read in the documentation somewhere that calling startService on a service that is already running should be ignored. But that isn't the case as I can see in the debugger that both OnCreate and OnStart are being called.
It is important that I do not create a new service each time because the background service may be in the middle of serving a file. The activity does not need to do any communication with the service - only start it if it isn't running and kill it if the user hits a button.
Any idea on why my service is not showing up in the getRunningServices list?
Step #1: Add static boolean isRunning=false to your service.
Step #2: Set isRunning to true in onCreate() of the service.
Step #3: Set isRunning to false in onDestroy() of the service.
Step #4: Examine isRunning to see if the service is running.
I read in the documentation somewhere that calling startService on a service that is already running should be ignored. But that isn't the case as I can see in the debugger that both OnCreate and OnStart are being called.
I am very confident that onCreate() is not called when startService() is invoked on a running service. onStartCommand() (and, hence, onStart() for older services) will be called for every startService() call.
It is important that I do not create a new service each time
Services are natural singletons. There will be precisely 0 or 1 copies of the service in memory. There will never be 2 or more.
Actually, my service is now showing up in the list of services. I'm now thinking that maybe the service name wasn't registered until after restarting the phone, because I didn't make any changes but everything is working now after restarting.