Abort service start - android

I have an Android app with a service which connects to a peripheral device and listens to its output. The connection to the peripheral is initiated in the service’s onStartCommand() method.
Establishing the connection involves several “hopefullies” and may sometimes fail with an exception.
How can I prevent the service from becoming a zombie that’s running but has no connection to monitor? Calling stopSelf() from within onStartCommand() doesn’t seem to work.
Rough code:
public int onStartCommand(Intent intent, int flags, int startId) {
try {
// connect to device
} catch (ConnectToDeviceException e) {
stopSelf();
}
return START_REDELIVER_INTENT;
}

I solved it by moving the connection code into an AsyncTask and stopping the service from there if the connection fails.
Since onStartCommand() runs on the UI thread and connecting to a device can take some time, taking this off the UI thread by putting it in an AsyncTask is cleaner anyway.
Simplified code:
public int onStartCommand(Intent intent, int flags, int startId) {
StartupTask startupTask = new StartupTask();
startupTask.execute();
return START_REDELIVER_INTENT;
}
private class StartupTask extends AsyncTask<Void, Void, Void> {
boolean success = true;
#Override
protected Void doInBackground(Void... params) {
try {
// connect to device
} catch (ConnectToDeviceException e) {
success = false;
}
}
#Override
protected void onPostExecute(Void result) {
if (!success)
stopSelf();
}
}

Related

Not able to run service indefinitley in background

I am working on below code to run a service in background,but the problem is i am not getting how to run the service indefinitely even though the app is closed,here on press of back my service is stopping.I have read many tutorials but still confused with this.
public class HelloService extends Service {
private static final String TAG = "HelloService";
private boolean isRunning = false;
#Override
public void onCreate() {
Log.i(TAG, "Service onCreate");
isRunning = true;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service onStartCommand");
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
if (isRunning) {
Log.i(TAG, "Service running");
}
}
//Stop service once it finishes its task
stopSelf();
}
}).start();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
Log.i(TAG, "Service onBind");
return null;
}
#Override
public void onDestroy() {
isRunning = false;
Log.i(TAG, "Service onDestroy");
}
}
On Android there is NO way (at least for a third party app) to have a never ending process running. The system can always kill your service. So you can use a foreground service but the system can kill your service even in this case (even with low probability). In addition, you should consider that the cpu can go to sleep. So you should take a wakelock but in this way you can kill the user battery so it's not a good solution. My suggestion is to always work "on event" for example with a brodacast receiver that starts a intent service, it does some work and then exit. The always running processes are simply a wrong design choices on Android.
One Way is to use while loop but keep a check i.e
while(true) {
if (condition != true) {
Thread.sleep(time);
} else {
break;
}
}

Multiple Services on Multiple Threads Lifecycle

These methods are implemented in a class extending Service. A new service is started every time a button is pressed.
If the button is pressed once, LogCat outputs what I expect, which includes a final output of "Service onDestroy." However, when the button is pressed twice, the second time before the first service ended, "Service onDestroy." displays only once when the first service is done, and the second service prints out the rest of "Service Running" logs but not "Service onDestroy."
Can anyone tell me why? Thank you!
public int onStartCommand(Intent intent,int flags, int startId) {
Log.i(TAG,"Service onStartCommand " + startId);
final int currentId = startId;
Runnable r = new Runnable() {
public void run() {
for (int i = 0; i < 3; i++) {
long endTime = System.currentTimeMillis() + 10*1000;
while (System.currentTimeMillis() < endTime) {
synchronized(this) {
try {
wait(endTime - System.currentTimeMillis());
}catch (Exception e) {
}
}
}
Log.i(TAG,"Service running");
}
stopSelf();
}
};
Thread t = new Thread(r);
t.start();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.i(TAG,"Service onBind");
return null;
}
#Override
public void onDestroy() {
Log.i(TAG,"Service onDestroy");
}
In the guide for Services they use don't use stopSelf() but stopSelf(startId) when extending Service. The first stopSelf() propably stops both executions of your Service.
See here: http://developer.android.com/guide/components/services.html
Edit: Also a service is only created and destroyed once even when there are several executions of it running it is still a single service. In your case (a Bound Service) it will only be destroyed when the last excecution finishes. For logging every excecution ending you could try to override the stopSelf(int startId) method.

How can I control some web API per x minutes on service?

I want to check some web API and do something per x minutes. I think I should write a service on Android (is there any other solution?).
But how can do that?
I am thinking about writing a service class and in the manifest file I should add this line:
<service
android:name="com.xx.yy.noti_check"
android:enabled="true"
>
</service>
And in my noti_check class I check my web API like this on onStartCommand:
public class noti_check extends Service {
Context mcont;
private Handler myhandler ;
private long RETRY_TIME = 15000;
private long START_TIME = 2000;
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onStart(Intent intent, int startId) {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mcont=this;
myhandler= new Handler();
myhandler.postDelayed(myRunnable, START_TIME);
return Service.START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
try {
myhandler.removeCallbacks(myRunnable);
}
catch (Exception e) {
// TODO: handle exception
}
}
private Runnable myRunnable = new Runnable() {
public void run() {
try {
new get_notifyalert(mcont).execute("") ;
}
catch (Exception e) {
// TODO: handle exception
}
myhandler.postDelayed(myRunnable, RETRY_TIME);
}
};
}
Is this is the right way?
Is this the right way?
No. Only have a service running when it is actively delivering value to the user. Watching the clock tick is not actively delivering value to the user. Use AlarmManager for periodic work like this.

Android stop service when ThreadPoolExcutor completed

I have a Service run independently with activity using startService(). This service handle many requests from activity and create Callable then add into ThreadPoolExecutor. It looks like this:
private ExecutorService requestExecutor;
private CompletionService<Result> requestHandleService;
#Override
public int onStartCommand(final Intent intent, int flags, int startId) {
// Create new Request Task and submit
Callable<Result> request = new Callable<Result>(){
public Result call() throws Exception {
}
};
requestHandleService.submit(task);
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy(){
super.onDestroy();
Log.d(TAg,"onDestroy service");
try{
if(requestExecutor!= null){
requestExecutor.shutdown();
}
}catch(Exception ex){
Ln.e(ex);
}finally{
requestExecutor= null;
requestHandleService= null;
}
}
The problem is that I want this Service run independently and parallel with activity. So activity can't control when to stop it. It should only stop when all tasks finished.
I know there is a way to wait for ThreadPool complete, but this can't work for me, because I don't need to keep the list requests. When this service receive request from activity, it should create new a task and submit immediately in onStartCommand.
Is there any way to solve this?
Have you checked out IntentService, this is sort of what this type of service does. If you need the multiple threads then you could wrap the tasks you submit with a check for the Queue used by the ThreadPool to see if it is empty, and if so, shutdown the service and the threadpool.
Callable is just an interface, so just make a callback out of it.
#Override
public void onCreate() {
mHandler = new Handler();
}
#Override
public int onStartCommand(final Intent intent, int flags, int startId) {
// Create new Request Task and submit
Callable<Result> request = new Callable<Result>(){
public Result call() throws Exception {
Result result = // ... mRealTask.call();
mHandler.postDelayed(queueCheck, 300);
return result;
}
};
requestHandleService.submit(task);
return super.onStartCommand(intent, flags, startId);
}
Runnable queueCheck = new Runnable() {
public void run() {
if (requestExecutor.getQueue().isEmpty()) {
stopService(new Intent(this, getClass()));
mHandler.removeCallbacks(this);
}
}
};

Android force close exceptions with thread

Normally, when I close my app I send an intent to my service to signal to safely shutdown using onStartCommand with an extra boolean of true. I do this in my application class' onTerminate. I added the if statements because I was getting a nullptrexception when force closing the app in this block.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
boolean state = intent.getBooleanExtra("terminate", false);
mSafeShutdown = state;
}
else if (mUpdater != null && mUpdater.isRunning()) {
Log.d(TAG, "activity force closed?" +
" Attempting to handle service thread shutdown safely...");
mUpdater.isRunning(false);
try {
mUpdater.join();
} catch (InterruptedException e) {
Log.e(TAG,"Service's UpdaterThread couldn't join");
}
}
return START_STICKY;
}
however, this causes my service to stay alive -
static final int DELAY = 2000;
public void run() {
while (mIsRunning) {
if (!mJobQueue.isEmpty()) {
//do work
}
else if (mSafeShutdown) {
mIsRunning = false;
stopSelf();
}
else {
sleep(DELAY);
}
}
}
The fact that force closing disconnects the debugger its making hard to see exactly whats going on.. Is there a better/safer way to tell my service thread that the application has shut down?
since your thread is a child class, create a method in it to shut it down the thread and call it in your parent class.
An example can be found here
http://download.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html

Categories

Resources