run an IntentService at most once - android

I have an IntentService and I want for the startCommand to be called only if it's not already running.
The reason for this is this service is processing all existing rows in database. It can be called to start several times but if it's already running it shouldn't be started again. And similar to IntentService after there are no rows to be processed, it should close itself.
Is this achievable? Maybe with PendingIntent and FLAG_NO_CREATE ?
I could create this with a Service and a separate thread instead of a IntentService but IntentService already has the thread implemented.

Maybe with PendingIntent and FLAG_NO_CREATE ?
That flag refers to creating the PendingIntent, not the service.
Is this achievable?
Off the cuff:
Step #1: In your service, add an AtomicBoolean field (here called isRunning), initially set to false.
Step #2: Override onStartCommand(). If isRunning is false, set it to true and chain to super.onStartCommand() to inherit normal IntentService behavior. If isRunning is true, do not chain to super.onStartCommand().
Step #3: In onHandleIntent(), wrap all your work in a try/finally block, where you set isRunning to false in finally.
Net: a startService() invocation will only go through normal IntentService processing if onHandleIntent() is not already running.

Related

Starting service multiple times will nest calls made in onStartCommand()?

I am calling startService() multiple times in my class.
there is a function in my service's onStartCommand(), like this -
Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(StaticValues.TAG, "service started.");
processItem();
return 0;
}
My question is, if I start service again, onStartComamnd() will be called again. So will this call wait till my previous call is over or it will execute both calls to processItem() parallelly?
Edit : Answer I found from links in comments
startService() is asynchronous. So while you are looping the calls, the service itself hasn't gotten any resources and didn't start yet.
The Service will only run in one instance. However, everytime you start the service, the onStartCommand() method is called.
Check : What happens if a Service is started multiple times?
A Service can only be started once, if you want to and love to complicate things use a boolean flag
Using startService() overrides the default service lifetime that is managed by bindService(Intent, ServiceConnection, int): it requires the service to remain running until stopService(Intent) is called, regardless of whether any clients are connected to it. Note that calls to startService() are not nesting: no matter how many times you call startService(), a single call to stopService(Intent) will stop it.
If the service is being started or is already running, the
ComponentName of the actual service that was started is returned; else
if the service does not exist null is returned.
Note that multiple calls to Context.startService() do not nest (though
they do result in multiple corresponding calls to onStartCommand()),
so no matter how many times it is started a service will be stopped
once Context.stopService() or stopSelf() is called;
Link to the Docs
Life Cycle of a Service

Sending message from Activity to intentService

My question is as follows:
I started my intentService from my main Activity. This intentService does some audio processing with audioRecord.
However, when I need to start another activity in my application (recording video in this case), i need to stop the intentService in the background (because it is hogging the audio resource).
Is there a way to stop the intentService from the main activity?
You can use stopService() from your main activity like this:
stopService(new Intent(yourMainActivity.this,yourIntentService.class));
use the same pre-declared intent which you used to start the IntentService and call
stopService(intent);
if you create a new intent and use it to stop the service, the service will not respond to it until its finishes processing the previous intent.
but it should be noted that this will not immediately stop the service. So a workaround to this is to have a Global boolean variable. When its set to true the processing within the service will carry out, and when you want to end it set the boolean variable to false from your activity. and then you can stop the service from within itself by calling
stopSelf();

How to prevent multiple invokes for onHandleIntent() - IntentService

When I start a service (IntentService) it will call the onHandleIntent() which is the service function. While it is running, if I call startService() again, it caches the invoke, and calls the onHandleIntent() again. Actually what I want to do is, pass some new data to the current running service instance, without creating an additional. (Like signaling in threads or a listener).
How do I do it?
In my onHandleIntent() I want to use while(true){....} , so it will run forever.
Extend the normal Service class. On the first onStartCommand() that you receive, start a background thread that has your "while(true) {...}" code. On the onStartCommand() calls thereafter, check for the existence of your worker thread and when it exists, signal it.
Without knowing what you are going to use this Service for it is hard to give you any better advice. However, some things to think about:
- Check out the Looper/Handler classes that are also used by the IntentService.. They may give you some nice way to code your "while(true)" loop, including signalling.
- Remember that the onStartCommand() method should return within a few seconds (it is running on the main thread) so if you want to hand off new work (that is received through the Intent passed in onStartCommand) you should make sure this hand-off doesn't take too long. The Looper/Handler classes may help you here as well.
Check whether your service is already started, if not start it:
private boolean isMyServiceRunning() {
ActivityManager manager = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if ("com.example.Service".equals(service.service.getClassName())) {
return true;
}
}
return false;
}

Stop a service after time

I want to stop my Service after a user defined time (choosen in a activity).
Now I want to start the timer in the service, but I cant use static timer because I have to stop the service (stopService(), stopSelf() are non-static methods.
Is there a simple way to do it?
(Now I used a handler with a runnable which checks if a variable is set to true and then starts the timer)
Use AlarmManager. Call set() on an AlarmManager, supplying the time when you want your service to stop and a getService() PendingIntent that will send a command to your service. In onStartCommand(), when you receive the Intent command from the PendingIntent, call stopSelf().

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