I am using android foreground service for continuous location updates that starts when user clicks a button. My question is what if the user presses the button twice? Will there be two foreground process running? If so, how to check whether foregroundservice running already or not.
So that I can apply a condition before calling the foreground service. Please let me know if there a way.
Services are singletons- only one will exist at a time. However, it will call onStartCommand again with a new Intent if you call startService or startForegroundService again. So make sure that call won't cause you to rerequest location updates if you already have.
You can check if your service is running or not by using this function:
private fun isMyServiceRunning(serviceClass: Class<*>): Boolean {
val manager = getSystemService(ACTIVITY_SERVICE) as ActivityManager
for (service in manager.getRunningServices(Int.MAX_VALUE)) {
if (serviceClass.name == service.service.className) {
return true
}
}
return false
}
If your service is not running start the service:
if (!isMyServiceRunning(MyService::class.java) {
startService(...)
}
Related
My Android application starts a local foreground service (in the same process as my activity). The service have to stay alive, even if the system destroys the activity due low memory.
Next time a user starts the app, I need to check whether the service is running or not.
I tried to store state in public static boolean Started = false; flag in service class (I know that it is bad practice).
My activity starts in the process where service is running. I thought, that static constructor is called ones. So, I would be able to check this flag in activity. However, static data is reinitialized to defaults.
Could any one give me a cue about this behavior?
here is just an example how I restart the service when apps come forground
public void storeLastLocation() {
if (!isStoreLocationActive){
Log.d("IQ MA", "storeLastLocation() called");
String access_token = Configs.access_token;
Intent intent = new Intent(MainActivity.this, StoreLocationService.class);
intent.putExtra("access_token", access_token);
stopService(intent);
startService(intent);
isStoreLocationActive = true;
}
}
then store boolean on service is running
I have added Google Now search within my application. The way it works is, the user types something in the EditText object and oonce they press the button, this intent runs -
Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
String term = searchInput.getText().toString();
intent.putExtra(SearchManager.QUERY, term);
startActivity(intent);
However I am having issues killing the service after the intent has been launched.
calling finish();after the intent will not work unless I am directing the intent to a different class itself.
Here's a video preview fo what I mean, you can clearly see I am pressing home to close the app but when I reopen it . It opens to the Google Now app. But when pressing back, it stops. How exactly can I get the intent to stop after I press the home key?
And my app is a dialogue type app so I have excluded it from the recent menu because of allot of reasons. Everywhere else the app kills itself as soon as the user exits it but here the service keeps running.
Video - Video Preview
I have also tried many questions answers, have researched but nothing has helped so far. I may be doing something wrong. Could someone kindly help me out here, thank you very much! :)
A started service must manage its own lifecycle. That is, the system does not stop or destroy the service unless it must recover system memory and the service continues to run after onStartCommand() returns. So, the service must stop itself by calling stopSelf() or another component can stop it by calling stopService().
use stopSelf() upon compleetion of task assigned to service.
And if you want to finishs ervice when application finishes, then in onDestroy(), call stopService() after checking whether its running or not, such method can be used:
public static boolean isMyServiceRunning(Class<?> serviceClass, Activity pActivity) {
ActivityManager manager = (ActivityManager) pActivity.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
to stop service from activity use below code:
stopService(new Intent(yourMainActivity.this,yourIntentService.class));
or you can write condition in service to stop itself like below:
if(check your condition here)
stopSelf();
You don't have to stop an IntentService - it will terminate itself when it has no more work to do.
It runs on separate worker thread.
Multiple intents are queued on the same worker thread.
So even if your Activity was destroyed from where this service was started it will continue performing its tasks until all the queued ones are complete and after completion it is automatically terminated.
Caution: It's important that your application stops its services when it's done working, to avoid wasting system resources and consuming battery power. If necessary, other components can stop the service by calling stopService(). Even if you enable binding for the service, you must always stop the service yourself if it ever received a call to onStartCommand().
stopService() : Request that a given application service be stopped. If the service is not running, nothing happens. Otherwise it is stopped. Note that calls to startService() are not counted -- this stops the service no matter how many times it was started.
Note: that if a stopped service still has ServiceConnection objects bound to it with the BIND_AUTO_CREATE set, it will not be destroyed until all of these bindings are removed.
I am having difficulties trying to handle service behaviour in such case.
Basically I have a service running on a separate process that needs to issue httprequests every certain time whenever the app is closed, then write something into preferences or throw a notification.
The logic works fine. The problem I'm having is that I cannot find a way to properly stop/disable that service whenever the app is running, aswell as start it again when the app is being finished or put into background.
I've tried stopping it at #onResume()/#onStart() callbacks of my activities aswell as starting it at #onStop()/#onDestroy() but behaviour doesnt run as expected in any case...
I'll paste here some code snippets of what i've tried so far:
I start/stop services using:
stopService(new Intent(this,NotificationService.class));
startService(new Intent(this, NotificationService.class));
Random activity from my app (all implement this in their callbacks):
#Override
protected void onResume() {
if (Utility.isMyServiceRunning(this)){
Utility.serviceClose(this);
}
super.onResume();
}
#Override
protected void onStop() {
if (!Utility.isMyServiceRunning(this)){
startService(new Intent(this, NotificationService.class));
}
super.onStop();
}
This somehow doesnt work or brings unexpected behaviour since the app moves from many activities, and service ends up being alive when the app is running or stopped when the app is in background/finished.
I've also tried to toggle on/off service logic on service timertask every cicle by asking:
#Override
public void run() {
ActivityManager activityManager = (ActivityManager) getBaseContext().getSystemService( ACTIVITY_SERVICE );
List<RunningAppProcessInfo> procInfos = activityManager.getRunningAppProcesses();
for(int i = 0; i < procInfos.size(); i++){
if(procInfos.get(i).processName.equals("com.example.myapp")) {
return;
}
}
//service http request logic here
}
But that doesnt work either because process "com.example.myapp" never gets killed (and of course I cannot/want to force finish that), so it never issues any httprequest.
Any Ideas on how to implement this? Any help would be very welcome.
Thanks in advance.
How about binding to your service and then communicating directly with it? Implement a simple on/off boolean, expose a getter/setter on the binding, and then make sure the service checks the boolean before it does any work. That way you can disable it while the app is running without having to actually start/stop the service repeatedly.
http://developer.android.com/guide/components/bound-services.html
Solved with better handling of onStop() onResume() callbacks.
I am asking a vexed question that has been (partially, to my mind) addressed here and here. Let's say like in many examples we want to create a music application, using (say) a single activity and a service. We want the service to persist when the Activity is stopped or destroyed. This kind of lifecycle suggests a started service:
A service is "started" when an application component (such as an
activity) starts it by calling startService(). Once started, a service
can run in the background indefinitely, even if the component that
started it is destroyed
Ok, but we also want to be able to communicate with the service, so we need a service binding. No problem, we have both a bound and started service as this answer suggests:
At activity startup (or some other point) we call startService()
After that we call bindService() to obtain the IBinder interface, and proceed from there.
So far so good, but a problem arises from the fact that when the activity starts, we do not know if the service is around or not. It may have been started or it may not have been. The answer could be something like:
At startup, try to bind to the service (use bindService() without the BIND_AUTO_CREATE flag)
If that fails, then start the service using startService(), and then bind to it.
This idea is premised on a particular reading of the docs for bindService():
Connect to an application service, creating it if needed.
If zero flag means "service is not really needed" than we are OK. So we try something like this using the following code:
private void connectToService() {
Log.d("MainActivity", "Connecting to service");
// We try to bind to an existing service
Intent bindIntent = new Intent(this, AccelerometerLoggerService.class);
boolean bindResult = bindService(bindIntent, mConnection, 0);
if (bindResult) {
// Service existed, so we just bound to it
Log.d("MainActivity", "Found a pre-existing service and bound to it");
} else {
Log.d("MainActivity", "No pre-existing service starting one");
// Service did not exist so we must start it
Intent startIntent = new Intent(this, AccelerometerLoggerService.class);
ComponentName startResult = startService(startIntent);
if (startResult==null) {
Log.e("MainActivity", "Unable to start our service");
} else {
Log.d("MainActivity", "Started a service will bind");
// Now that the service is started, we can bind to it
bindService(bindIntent, mConnection, 0);
if (!bindResult) {
Log.e("MainActivity", "started a service and then failed to bind to it");
} else {
Log.d("MainActivity", "Successfully bound");
}
}
}
}
And what we get is a successful binding every time:
04-23 05:42:59.125: D/MainActivity(842): Connecting to service
04-23 05:42:59.125: D/MainActivity(842): Found a pre-existing service and bound to it
04-23 05:42:59.134: D/MainActivity(842): onCreate
The global question is "Am I misunderstanding bound versus started services and how to use them?" More specific questions are:
Is it the correct understanding of the docs to think that zero flag passed to bindService() means "Do not start the service"? If not, is there no way to call bindService() without starting the service?
Why does bindService() return true even if the service is not running? In this case it doesn't seem like the service has been started, based on Log calls.
If there the previous point is the correct/expected behavior of bindService(), is there a workaround (i.e. somehow ensure that startService is called only if the service is not running?)
P.S. I've moved on from the problem in my own code: I issue startService() calls regardless, since repeated startService() are simply ignored. However, I would still like to understand the issues better.
If you bindService with 0 flag then the service will not start. You can bindService with BIND_AUTO_CREATE flag and if the service is not started, it will be started. However, when you unbindService the service will be destroy.
bindService with 0 flag always returns true.
You can always call startService. If the service is already running then a new service will not be created. The running service onStartCommand will be called.
There should not be any problem if you startService in onCreate and then bindService in onResume and unbindService in onPause.
In my project I am starting a service when a button is clicked.
But I don't want to start that service again when that button is clicked unless the previous one is already stopped. So I need to check first whether the service is running or not. I used the following method
private boolean isMyServiceRunning() {
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if ("com.example.MyService".equals(service.service.getClassName())) {
return true;
}
}
return false;
}
But its not working for me, it doesnt give any exception but always returns false. what should I do now?
I think the reason why your service is not listed in running services is the way you start your service. The following proposal is the same thread you took your method from.
You MUST call startService for your service to be properly registered and
passing BIND_AUTO_CREATE will not suffice.
Like the following:
Intent bindIntent = new Intent(this,ServiceTask.class);
startService(bindIntent);
bindService(bindIntent,mConnection,0);
Try this and see if it works for you too.
Your method return false because after stop, process is destroyed by system if there are no any clients bound to service.