Marek
Marek

Reputation: 1249

AsyncTask stops after some time

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

Answers (2)

mondakuwar
mondakuwar

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

paul_hundal
paul_hundal

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

Related Questions