Android: How to determine if IntentService is running? - android

I have an activity for upload from which I am calling Intent service. In there I am handling the API request call.
I want an activity to know whether the service is running or not, to show an uploading tag.
I tried following to determine if the service is running:
public void startUploadServiceTask() {
if (Util.isNetworkAvailable(mContext)) {
if (!isMyServiceRunning(UploadDriveService.class)) {
startService(new Intent(mContext,
UploadService.class));
}
} else {
Toast.makeText(mContext,
"Service is already running.", Toast.LENGTH_SHORT)
.show();
}
} else {
Toast.makeText(mContext,
getString(R.string.please_check_internet_connection),
Toast.LENGTH_SHORT).show();
}
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager
.getRunningServices(Integer.MAX_VALUE)) {
Log.e("ALL SERVICE", service.service.getClassName().toString());
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
But in Activity Manager Running Service Info, I am not getting the class of intent service that I am running, so this always stands false.
I have used Broadcast for API calls response.
I have even checked this code.
if(startService(someIntent) != null) {
Toast.makeText(getBaseContext(), "Service is already running", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getBaseContext(), "There is no service running, starting service..", Toast.LENGTH_SHORT).show();
}
But in this code, on checking the service it also starts the service again, so service is called twice.
Please help me out with this.

IntentService needs to implement onHandleIntent() This method is invoked on the worker thread with a request to process Intent request and IntentService will be "alive" as long as it is processing a intent request (am not considering low memory and other corener cases here, but just thinking in terms of logic),
And When all requests have been handled, the IntentService stops itself, (and hence you should not call stopSelf() explicitly)
With this theory in place, You may try below logic: Declare a class variable inside your IntentService class.
public static boolean isIntentServiceRunning = false;
#Override
protected void onHandleIntent(Intent workIntent) {
if(!isIntentServiceRunning) {
isIntentServiceRunning = true;
}
//Your other code here for processing request
}
And in onDestroy() of IntentService class if you may choose, set isIntentServiceRunning = false;
And use isIntentServiceRunning to check if IntentService is Running!

In your code you are trying to get the status of service from Activity. The correct way is that status should be given by the service.
There are several possibilities for an activity to communicate with a service and vice versa. As you are using Broadcast receiver so you can broadcast a message in onHandleIntent() method when the service started.
and then when your task completes or in case of any error, again you can call the broadcast receiver for service finished event.
here is a link for a nice tutorial.

Related

I am new to android. I wish to use android service for blocking call only when the service is started

This is the code should be run only when the service is running. And the service should be stopped in some other part.
public void onReceive(Context context, Intent intent)
{
this.context=context;
this.intent=intent;
if (!intent.getAction().equals("android.intent.action.PHONE_STATE"))
return;
else
{
number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
if (Callblockactivity.blockList.contains(new Blacklist(number))) {
System.out.println("i");
}
else {
disconnectPhoneItelephony(context);
return;
}
}
}
Now, the service should be started in mainactivity as follow.
if (speed >10) {
//service should be started.
}
else {
//service should be stopped
}
Please help with this.
use startService to start a Service. Use stopSelf or stopService to stop your service.
And you may use a static boolean variable inside your service in order to keep the flag whether the service is running.
Instead of that variable also you may dynamically register a receiver when you start your service, and unregister it when you stop the service.

Toggle Service Activity

I'm developing a service that need to run foreground, and users can toggle it on/off through an activity. So basically, the activity MAY be killed, but the service is safe as long as it is not stopped by user.
However, I'm getting this trouble: how to turn off the service if it is on? That mean, if my activity was killed, then restarted, so I get no reference of the started service intent to call stopService.
Below is my current code. It works fine if the user call deactivate after the service is started by the same activity. The button status is always correct, but when my activity is restarted by the OS, this.serviceIntent is null.
protected boolean isServiceRunning() {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (SynchronizationService.class.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
#Override
protected void onResume() {
super.onResume();
this.togglingByCode = true;
this.butActivate.setChecked(this.isServiceRunning());
this.togglingByCode = false;
}
public void onActivateButtonClick(final boolean pIsChecked) {
if (this.togglingByCode) { return; }
if (pIsChecked) {
this.saveSettings();
this.serviceIntent = new Intent(this, SynchronizationService.class);
this.serviceIntent.putExtra(KEY_WEBSERVICE, this.txtWebService.getText().toString());
this.serviceIntent.putExtra(KEY_PASSWORD, this.txtPassword.getText().toString());
this.serviceIntent.putExtra(KEY_INTERVAL, Integer.parseInt(this.txtRefreshInterval.getText().toString()));
this.serviceIntent.putExtra(KEY_TIMEOUT, this.preferences.getInt(KEY_TIMEOUT, DEFAULT_TIMEOUT));
this.serviceIntent.putExtra(KEY_RETRY, this.preferences.getInt(KEY_RETRY, DEFAULT_RETRY));
this.startService(this.serviceIntent);
} else {
this.stopService(this.serviceIntent);
this.serviceIntent = null;
}
}
Please tell me how to stop the service correctly. Thank you.
P.s: I know a trick that make serviceIntent static, but I don't feel safe about it. If there is no any other way, then I will use it.
Simply initialize your serviceIntent in the activity's onCreate... You can start your service, kill your activity, reopen it and stop the service with the same serviceIntent.

How to force an IntentService to stop immediately with a cancel button from an Activity?

I have an IntentService that is started from an Activity and I would like to be able to stop the service immediately from the activity with a "cancel" button in the activity. As soon as that "cancel" button is pressed, I want the service to stop executing lines of code.
I've found a number of questions similar to this (i.e. here, here, here, here), but no good answers. Activity.stopService() and Service.stopSelf() execute the Service.onDestroy() method immediately but then let the code in onHandleIntent() finish all the way through before destroying the service.
Since there is apparently no guaranteed way to terminate the service's thread immediately, the only recommended solution I can find (here) is to have a boolean member variable in the service that can be switched in the onDestroy() method, and then have just about every line of the code in onHandleIntent() wrapped in its own "if" clause looking at that variable. That's an awful way to write code.
Does anybody know of a better way to do this in an IntentService?
Here is the trick, make use of a volatile static variable and check continue condition in some of lines in your service that service continue should be checked:
class MyService extends IntentService {
public static volatile boolean shouldContinue = true;
public MyService() {
super("My Service");
}
#Override
protected void onHandleIntent(Intent intent) {
doStuff();
}
private void doStuff() {
// do something
// check the condition
if (shouldContinue == false) {
stopSelf();
return;
}
// continue doing something
// check the condition
if (shouldContinue == false) {
stopSelf();
return;
}
// put those checks wherever you need
}
}
and in your activity do this to stop your service,
MyService.shouldContinue = false;
Stopping a thread or a process immediately is often a dirty thing. However, it should be fine if your service is stateless.
Declare the service as a separate process in the manifest:
<service
android:process=":service"
...
And when you want to stop its execution, just kill that process:
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<RunningAppProcessInfo> runningAppProcesses = am.getRunningAppProcesses();
Iterator<RunningAppProcessInfo> iter = runningAppProcesses.iterator();
while(iter.hasNext()){
RunningAppProcessInfo next = iter.next();
String pricessName = getPackageName() + ":service";
if(next.processName.equals(pricessName)){
Process.killProcess(next.pid);
break;
}
}
I've used a BroadcastReceiver inside the service that simply puts a stop boolean to true. Example:
private boolean stop=false;
public class StopReceiver extends BroadcastReceiver {
public static final String ACTION_STOP = "stop";
#Override
public void onReceive(Context context, Intent intent) {
stop = true;
}
}
#Override
protected void onHandleIntent(Intent intent) {
IntentFilter filter = new IntentFilter(StopReceiver.ACTION_STOP);
filter.addCategory(Intent.CATEGORY_DEFAULT);
StopReceiver receiver = new StopReceiver();
registerReceiver(receiver, filter);
// Do stuff ....
//In the work you are doing
if(stop==true){
unregisterReceiver(receiver);
stopSelf();
}
}
Then, from the activity call:
//STOP SERVICE
Intent sIntent = new Intent();
sIntent.setAction(StopReceiver.ACTION_STOP);
sendBroadcast(sIntent);
To stop the service.
PD: I use a boolean because In my case I stop the service while in a loop but you can probably call unregisterReceiver and stopSelf in onReceive.
PD2: Don't forget to call unregisterReceiver if the service finishes it's work normally or you'll get a leaked IntentReceiver error.
#Override
protected void onHandleIntent(Intent intent) {
String action = intent.getAction();
if (action.equals(Action_CANCEL)) {
stopSelf();
} else if (action.equals(Action_START)) {
//handle
}
}
Hope it works.
In case of IntentService it does not stop or takes any other request through some intent action until its onHandleIntent method completes the previous request.
If we try to start IntentService again with some other action, onHandleIntent will be called only when previous intent / task is finished.
Also stopService(intent); or stopSelf(); does not work until the onHandleIntent() method finishes its task.
So I think here better solution is to use normal Service here.
I hope it will help!
If using an IntentService, then I think you are stuck doing something like you describe, where the onHandleIntent() code has to poll for its "stop" signal.
If your background task is potentially long-running, and if you need to be able to stop it, I think you are better off using a plain Service instead. At a high level, write your Service to:
Expose a "start" Intent to start an AsyncTask to perform your background work, saving off a reference to that newly-created AsyncTask.
Expose a "cancel" Intent to invoke AsyncTask.cancel(true), or have onDestroy() invoke AsyncTask.cancel(true).
The Activity can then either send the "cancel" Intent or just call stopService().
In exchange for the ability to cancel the background work, the Service takes on the following responsibilities:
The AsyncTask doInBackground() will have to gracefully handle InterruptedException and/or periodically check for Thread.interrupted(), and return "early".
The Service will have to ensure that stopSelf() is called (maybe in AsyncTask onPostExecute/onCancelled).
As #budius already mentioned in his comment, you should set a boolean on the Service when you click that button:
// your Activity.java
public boolean onClick() {
//...
mService.performTasks = false;
mService.stopSelf();
}
And in your Intent handling, before you do the important task of committing/sending the intent information, just use that boolean:
// your Service.java
public boolean performTasks = true;
protected void onHandleIntent(Intent intent) {
Bundle intentInfo = intent.getBundle();
if (this.performTasks) {
// Then handle the intent...
}
}
Otherwise, the Service will do it's task of processing that Intent. That's how it was meant to be used,
because I can't quite see how you could solve it otherwise if you look at the core code.
Here is some sample code to start/stop Service
To start,
Intent GPSService = new Intent(context, TrackGPS.class);
context.startService(GPSService);
To stop,
context.stopService(GPSService);
context.stopService(GPSService);

how to prevent service to run again if already running android

On click of a button I want to start service using method startService(new Intent(currentActivity.this,MyService.class)) but if service is running I don't want to call this method to avoid run service that is already running.How this is possible.I am using both Intent service and Service in same project and want to apply same condition for both.
A service will only run once, so you can call startService(Intent) multiple times.
You will receive an onStartCommand() in the service. So keep that in mind.
Source:
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; however, services can use their stopSelf(int) method to ensure the service is not stopped until started intents have been processed.
At: http://developer.android.com/reference/android/app/Service.html on topic: Service Lifecycle
Use startService().
Start Service will call onStartCommand() If the Service isn't started yet it will Call onCreate(). Initialize your variables and/or start a Thread in onCreate().
Bind your service; when starting call:
Intent bindIntent = new Intent(this,ServiceTask.class);
startService(bindIntent);
bindService(bindIntent,mConnection,0);
Then to check if your service is working, use a method like:
public static boolean isServiceRunning(String serviceClassName){
final ActivityManager activityManager = (ActivityManager)Application.getContext().getSystemService(Context.ACTIVITY_SERVICE);
final List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);
for (RunningServiceInfo runningServiceInfo : services) {
if (runningServiceInfo.service.getClassName().equals(serviceClassName)){
return true;
}
}
return false;
}
Whenever we start any service from any activity , Android system calls the service's onStartCommand() method And If the service is not already running, the system first calls onCreate(), and then it calls onStartCommand().
So mean to say is that android service start's only once in its lifecycle and keep it running till stopped.if any other client want to start it again then only onStartCommand() method will invoked all the time.
So, for avoiding restarting a task again and again, You can use boolean values, that the task is already started or ongoing. Put the method both in oncreate and onstartCommand, and checked with the boolean:
boolean isTimerTaskRunning = false;
private boolean isServiceKeepRunning(){
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
return settings.getBoolean("silentModeKeepRunning", true);
}
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate: Called");
Log.i(TAG, "onCreate: keepRunning "+isServiceKeepRunning());
if(!isTimerTaskRunning) {
startTimerTask();
isTimerTaskRunning = true;
}
//startForeground(REQUEST_CODE /* ID of notification */, notificationbuilder().build());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
localData = new LocalData(this);
// return super.onStartCommand(intent, flags, startId);
Log.i(TAG, "onStartCommand: Called");
Log.i(TAG, "onStartCommand: keepRunning "+isServiceKeepRunning());
Toast.makeText(this, "This is The Mode For Silent. ", Toast.LENGTH_LONG).show();
if(!isTimerTaskRunning) {
Log.i(TAG, "TimerTask was not Running - started from onStartCommand");
startTimerTask();
isTimerTaskRunning = true;
}else {
Log.i(TAG, "TimerTask was already Running - checked from onStartCommand");
}
//return START_REDELIVER_INTENT;
startForeground(REQUEST_CODE /* ID of notification */, notificationbuilder().build());
return START_STICKY;
}

Android bindService or/and startService

I want to create Service using bindService method.
But when I close one Activity my Service is destroyed, and I don't want that.
I try to put service in foreground using startForeground(NOTIFICATION_ID, notification); service onCreate , but service still destroy.
Now I try with call two methods for starting Service at same time :
Intent bindIntent= new Intent(this, ServiceC.class);
startService(bindIntent);
bindService(bindIntent, onService, BIND_AUTO_CREATE);
By calling these two methods Service not destroyed. My app work fine with this method.
Can someone explain to me whether this is a good way or if it is not can you please give me idea why startForeground(NOTIFICATION_ID, notification); does not work ?
What is the best way to use bindService but at the same time I don't want the service to self destroy.
I Used the same solution and it's a legitimate one. From Service ref:
A service can be both started and have
connections bound to it. In such a
case, the system will keep the service
running as long as either it is
started or there are one or more
connections to it with the
Context.BIND_AUTO_CREATE flag. Once
neither of these situations hold, the
service's onDestroy() method is called
and the service is effectively
terminated.
startForeground() is not working because it just tries to prevent the service from being killed by the system, but its lifecycle is another thing: if nothing is more bound to that service and it wasn't started, it just stops.
If you start service with startService() it is not destroyed. Tried starting a service, which extends IntentService and have a loop in onHandleIntent(). When loop is finished, then service destroyed and it is not related with Activity finish. User can close application, but service is not being killed.
public class MyService extends IntentService
{
private static final String serviceName = "MyService ";
public MyService () {
super(serviceName);
}
#Override
public void onDestroy()
{
Log.v(serviceName, "onDestroy");
Toast.makeText(this, serviceName+" stopped", Toast.LENGTH_LONG).show();
super.onDestroy();
}
#Override
protected void onHandleIntent(Intent arg0) {
long endTime = System.currentTimeMillis() + 30*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
Log.v(serviceName, "Service loop");
wait(1000);
} catch (Exception e) {
}
}
}
}
}

Categories

Resources