Reputation: 1249
I have a CustomAsyncTask class that enables infinite barcode scanner and I execute it in CustomApplication.
Unfortunately CustomAsyncTask::doInBackground
stops after some time (minute or two).
private class ScanAsync extends AsyncTask<Void, String, Void>
{
boolean blocked = false;
@Override
protected Void doInBackground(Void... params)
{
while(true)
{
if (!blocked)
{
String received = GlobalAccess.scan.scan(500);
if (received != null && !received.isEmpty())
{
blocked = true;
publishProgress(received);
}
}
else
{
try
{
Thread.sleep(500);
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
}
}
}
@Override
protected void onProgressUpdate(String... values)
{
super.onProgressUpdate(values);
//TODO: something with received value
blocked = false;
}
}
I need this background task to be always on. Is there any good solution for this? I have tried IntentService, but the result was the same - after some time it stopped working.
EDIT
I have created this Service, although it block my main thread, but it should work in background right? Also If I put a breakpoint on if(!blocked)
and press F9 it works fine (scanning part), but if I remove breakpoint and let it run - after few seconds it just turns off (scanner), but if I put a breakpoint again - it works again (sic!).
public class ScanService extends Service
{
boolean blocked = false;
public ScanService()
{
}
@Nullable
@Override
public IBinder onBind(Intent intent)
{
return null;
// TODO: Return the communication channel to the service.
//throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
while(true)
{
if (!blocked)
{
String received = GlobalAccess.scan.scan(500);
if (received != null && !received.isEmpty())
{
//blocked = true;
}
}
else
{
try
{
Thread.sleep(500);
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
}
}
}
}
Upvotes: 0
Views: 191
Reputation: 114
Use a Service instead of AsyncTask. AsyncTasks are only designed to run with shorter background tasks. Keep in mind that whatever you run in a Service
will execute on the main thread, so you should use a background thread within your Service
.
Can you tell why the AsyncTask or IntentService is stopping? With an IntentService
, with your while(true) loop, it should run indefinitely unless the app gets shut down for some reason.
Edit -
You need to do this to prevent your loop from blocking the main thread -
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while(true) {
// your code here
}
}
});
t.start();
}
I don't know why your Service is stopping. You need to be looking at your Logcat output. Set the filter to Error and you're crash should show up there.
Upvotes: 1
Reputation: 381
Yes, there is an elegant solution for this type of thing. Use a service. In particular, the JobScheduler api is meant to handle this kind of stuff. Reason for using this is, as you stated, you have a long running task and you don't want to have to manage it dying. In addition, the JobScheduler is built to handle side effects of the OS. I assume that you want your job to run, but allow the app to perform its normal set of operations. Though, as a note, the API is smart in considering factors, such as battery levels, OS resources being used, wifi connectivity, so the jobs can be deferred.
The official documentation is here https://developer.android.com/reference/android/app/job/JobScheduler.html
An example of how to use it can be found here https://code.tutsplus.com/tutorials/using-the-jobscheduler-api-on-android-lollipop--cms-23562
Upvotes: 0