169

I want some code to run in the background continuously. I don't want to do it in a service. Is there any other way possible?

I have tried calling the Thread class in my Activity but my Activity remains in the background for sometime and then it stops. The Thread class also stops working.

class testThread implements Runnable {
        @Override
        public void run() {
            File file = new File( Environment.getExternalStorageDirectory(), "/BPCLTracker/gpsdata.txt" );
            int i = 0;

            RandomAccessFile in = null;

            try {
                in = new RandomAccessFile( file, "rw" );
            } catch (FileNotFoundException e) {
// TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
// TODO Auto-generated catch block
                e.printStackTrace();
            }
//String line =null;
            while ( true ) {
                HttpEntity entity = null;
                try {
                    if ( isInternetOn() ) {
                        while ( ( line = in.readLine() ) != null ) {

                            HttpClient client = new DefaultHttpClient();
                            String url = "some url";
                            HttpPost request = new HttpPost( url );
                            StringEntity se = new StringEntity( line );
                            se.setContentEncoding( "UTF-8" );
                            se.setContentEncoding( new BasicHeader( HTTP.CONTENT_TYPE, "application/json" ) );
                            entity = se;
                            request.setEntity( entity );
                            HttpResponse response = client.execute( request );
                            entity = response.getEntity();
                            i++;
                        }
                        if ( ( line = in.readLine() ) == null && entity != null ) {
                            file.delete();
                            testThread t = new testThread();
                            Thread t1 = new Thread( t );
                            t1.start();
                        }


                    } else {
                        Thread.sleep( 60000 );
                    } // end of else

                } catch (NullPointerException e1) {
                    e1.printStackTrace();
                } catch (InterruptedException e2) {
                    e2.printStackTrace();
                } catch (IOException e1) {
// TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }// end of while
        }// end of run

    }
Morteza Jalambadani
  • 2,190
  • 6
  • 21
  • 35
user2082987
  • 1,701
  • 2
  • 12
  • 9

9 Answers9

428

IF you need to:

  1. execute code on a background Thread

  2. execute code that DOES NOT touch/update the UI

  3. execute (short) code which will take at most a few seconds to complete

THEN use the following clean and efficient pattern which uses AsyncTask:

AsyncTask.execute(new Runnable() {
   @Override
   public void run() {
      //TODO your background code
   }
});
Brandon Rude
  • 4,349
  • 1
  • 11
  • 4
  • 10
    Note: Requires API level 11 – friederbluemle Nov 25 '15 at 14:06
  • I used the above code you said to send email which doesn't have link with UI. For the first time, it worked fine but if i try to execute the same code again, my app got stuck. Should i kill AsyncTask after execution of code ? – Nimmagadda Gowtham Oct 21 '16 at 16:51
  • 15
    Why wouldn't you use the following which is more lightweight: new Thread(new Runnable() { @Override public void run() { // background code } }).start(); – awardak May 13 '17 at 15:59
  • 3
    Even though you want to update the UI you can use following code snippet inside run: activity.runOnUiThread(new Runnable() { @Override public void run() { //Update UI } }); – Deepak S. Gavkar Dec 29 '17 at 12:51
  • 3
    Is there possibility of this causing memory leak? – frey Jun 22 '18 at 09:29
  • 5
    One thing to note is that AsyncTasks are qeued. If you use this for a bunch of server api calls, they will not run in parallel. – Chase Roberts Jul 23 '18 at 15:38
  • I use animation in splash screen and deserialize date take from server. the problem is performance slow and have leg in screen. this code solved my problem – Abbas Torabi Dec 21 '19 at 07:25
  • 13
    Note: [AsyncTask was deprecated in API level R](https://developer.android.com/reference/android/os/AsyncTask) – Sandre Feb 22 '20 at 11:11
  • @awardak. Thanks! I tried both methods and both worked. I had code which had to be executed in a separate thread to allow a Worker.DoWork to exit before the functionality within it (a reboot) completed. The thread worked, so I'll stick with it. – Stephen Hosking Jul 29 '23 at 09:23
51

Remember Running Background, Running continuously is two different tasks.

For long-term background processes, Threads aren't optimal with Android. However, here's the code, and do it at your own risk.

To approach it in the right way, you need to Start Service First, Inside the service, you need to start the Thread/Async task Which needs Runnable.

Remember Service and Thread will run in the background but our task needs to make triggers (call again and again) to get updates, i.e. once the task is completed we need to recall the function for the next update.

Timer (periodic trigger), Alarm (Timebase trigger), Broadcast (Event base Trigger), recursion will awake our functions.

public static boolean isRecursionEnable = true;

void runInBackground() {
    if (!isRecursionEnable)
        // Handle not to start multiple parallel threads
        return;

    // isRecursionEnable = false; when u want to stop
    // on exception on thread make it true again  
    new Thread(new Runnable() {
        @Override
        public void run() {
            // DO your work here
            // get the data
            if (activity_is_not_in_background) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // update UI
                        runInBackground();
                    }
                });
            } else {
                runInBackground();
            }
        }
    }).start();
}

Using Service: If you launch a Service it will start, It will execute the task, and it will terminate itself after the task execution if the service is not STICKY. This Service termination might also be caused by an exception in code or the user killed it manually from settings.

START_STICKY (Sticky Service) is the option given by Android that the service will restart itself if the service is terminated.

Remember the question difference between multiprocessing and multithreading? Service is a background process (Just like activity without UI), The same way how you launch thread in the activity to avoid load on the MainThread (Activity/UI thread), the same way you need to launch threads on service to avoid load on service.

In a single statement, if you want a run a background continues task, you need to launch a StickyService and run the thread in the service on event base

Sandeep P
  • 4,291
  • 2
  • 26
  • 45
  • Would you recommend this method for running a custom SignalStrengthListener in the background for an average of 20 minutes, while grabbing values from the listener once per second to update the UI thread? Here is more context: http://stackoverflow.com/questions/36167719/asynctask-fatal-exception-when-calling-a-method-from-doinbackground?noredirect=1#comment59973788_36167719 – JParks Mar 23 '16 at 01:58
  • How does the process runs again if you set 'isRecursionEnable=true'? You then call inside the 'run' method for 'runInBackground()' , how wouldn't it enter the if statement at the beginning of the function? – Mickey Apr 26 '18 at 13:29
37

Simple 3-Liner

A simple way of doing this that I found as a comment by @awardak in Brandon Rude's answer:

new Thread( new Runnable() { @Override public void run() { 
  // Run whatever background code you want here.
} } ).start();

I'm not sure if, or how, this is better than using AsyncTask.execute but it seems to work for us. Any comments as to the difference would be appreciated.

Thanks, @awardak!

Joshua Pinter
  • 45,245
  • 23
  • 243
  • 245
24

I want some code to run in the background continuously. I don't want to do it in a service. Is there any other way possible?

Most likely mechanizm that you are looking for is AsyncTask. It directly designated for performing background process on background Thread. Also its main benefit is that offers a few methods which run on Main(UI) Thread and make possible to update your UI if you want to annouce user about some progress in task or update UI with data retrieved from background process.

If you don't know how to start here is nice tutorial:

Note: Also there is possibility to use IntentService with ResultReceiver that works as well.

Simon Dorociak
  • 33,374
  • 10
  • 68
  • 106
  • @user2082987 so did you try it? – Simon Dorociak Mar 18 '13 at 09:32
  • these parameters of asyncTask are confusing – user2082987 Mar 18 '13 at 10:07
  • AsyncTask is just a wrapper around the Thread anyhow, so it doesn't solve the problem of Android killing the application while it is in background – Lassi Kinnunen Nov 20 '18 at 03:36
  • Hi @LassiKinnunen I wrote that answer 5 years ago. Now everything is changed and I'm not currently using AsyncTask because its memory leak not-safe. – Simon Dorociak Nov 20 '18 at 16:16
  • Yes I do realize that but people will still find this through google and I have seen so many comments of people recommending using the google wrappers even when it serves little to no purpose, sorry. As for the original question if someone is looking for some answers in 2018, create a service and launch it and mark it as being in foreground with a notification if you want to maximize chances of it not getting killed. The actual long running process can be handled with handlers or a separate thread. Didn't realize they managed to actually make it not memory leak safe though? – Lassi Kinnunen Nov 22 '18 at 10:13
  • @SimonDorociak so what are you using (or would use) now ? – mangusta Dec 29 '19 at 12:03
23

Today I was looking for this and Mr Brandon Rude gave an excellent answer. Unfortunately, AsyncTask is now deprecated. You can still use it, but it gives you a warning, which is very annoying. So an alternative is to use Executors like this (in kotlin):


        Executors.newSingleThreadExecutor().execute(Runnable {
            // todo: do your background tasks
            runOnUiThread{
                // update ui if you are in an activity
            }
            /*
            requireActivity().runOnUiThread {
               // update views / ui if you are in a fragment
            }
            */
        })

And in java it looks like this:


        Executors.newSingleThreadExecutor().execute(() -> {
            // todo: background tasks
            runOnUiThread(() -> {
                // todo: update your ui / view in activity
            });

            /*
            requireActivity().runOnUiThread((Runnable) () -> {
                // todo: update your ui / view in Fragment
            });
            */
        });
Abandoned Cart
  • 4,512
  • 1
  • 34
  • 41
Qazi Fahim Farhan
  • 2,066
  • 1
  • 14
  • 26
3

//Works accurately for me

new Thread( () -> {
        //run code on background thread 
        
        activity.runOnUiThread(()->{
            //update the UI on main thread
        });

        //here activity is the reference of activity 
    
            
    }).start();

//OR

 new Thread(new Runnable() {
        @Override
        public void run() {
            //run code on background thread 
        
        activity.runOnUiThread(()->{
            //update the UI on main thread
        });

        //here activity is the reference of activity 
        }
    })
Zaman Rajpoot
  • 326
  • 2
  • 5
2

An Alternative to AsyncTask is robospice. https://github.com/octo-online/robospice.

Some of the features of robospice.

1.executes asynchronously (in a background AndroidService) network requests (ex: REST requests using Spring Android).notify you app, on the UI thread, when result is ready.

2.is strongly typed ! You make your requests using POJOs and you get POJOs as request results.

3.enforce no constraints neither on POJOs used for requests nor on Activity classes you use in your projects.

4.caches results (in Json with both Jackson and Gson, or Xml, or flat text files, or binary files, even using ORM Lite).

5.notifies your activities (or any other context) of the result of the network request if and only if they are still alive

6.no memory leak at all, like Android Loaders, unlike Android AsyncTasks notifies your activities on their UI Thread.

7.uses a simple but robust exception handling model.

Samples to start with. https://github.com/octo-online/RoboSpice-samples.

A sample of robospice at https://play.google.com/store/apps/details?id=com.octo.android.robospice.motivations&feature=search_result.

Update: The above is answer is not valid anymore. Use kotlin coroutines for background threading.

Raghunandan
  • 132,755
  • 26
  • 225
  • 256
  • How to store an array obtained from network to SQLite? Basically I would like to: get data from network AND save them to my SQLite - both in background thread, then get my UI notified to refresh ListView. I usually do it with IntentService, but RoboSpice is less typing. – Yar Mar 03 '16 at 18:04
  • @yar you can use a intent service if its a long running operation. Also you can use asynctask but only if its for a short duration. You can create a thread and do all your stuff there. I haven't used robospice for a long time now. There are other networking libraries like volley... – Raghunandan Mar 04 '16 at 06:02
  • OK thanks. I thought about using Robospice, but it looks like it is not too good (flexible) for my needs. I use IntentService for a long time with success. – Yar Mar 04 '16 at 10:42
2
class Background implements Runnable {
    private CountDownLatch latch = new CountDownLatch(1);
    private  Handler handler;

    Background() {
        Thread thread = new Thread(this);
        thread.start();
        try {
            latch.await();
        } catch (InterruptedException e) {
           /// e.printStackTrace();
        }
    }

    @Override
    public void run() {
        Looper.prepare();
        handler = new Handler();
        latch.countDown();
        Looper.loop();
    }

    public Handler getHandler() {
        return handler;
    }
}
Božo Stojković
  • 2,893
  • 1
  • 27
  • 52
  • 6
    Welcome to StackOverflow. Answers with only code in them tend to get flagged for deletion as they are "low quality". Please read the help section on answering questions then consider adding some commentary to your Answer. – Graham Mar 03 '18 at 18:16
1

If you need run thread predioticly with different codes here is example:

Listener:

public interface ESLThreadListener {

    public List onBackground();

    public void onPostExecute(List list);

}

Thread Class

public class ESLThread extends AsyncTask<Void, Void, List> {


    private ESLThreadListener mListener;

    public ESLThread() {

        if(mListener != null){

            mListener.onBackground();
        }
    }

    @Override
    protected List doInBackground(Void... params) {

        if(mListener != null){

            List list = mListener.onBackground();

            return list;
        }

        return null;
    }

    @Override
    protected void onPostExecute(List t) {
        if(mListener != null){

            if ( t != null) {
                mListener.onPostExecute(t);
            }
        }

    }


    public void setListener(ESLThreadListener mListener){

        this.mListener = mListener;
    }
}

Run different codes:

  ESLThread thread = new ESLThread();
                        thread.setListener(new ESLThreadListener() {
                            @Override
                            public List onBackground() {
                                List<EntityShoppingListItems>  data = RoomDB.getDatabase(context).sliDAO().getSL(fId);

                                return data;

                            }

                            @Override
                            public void onPostExecute(List t) {

                                List<EntityShoppingListItems> data = (List<EntityShoppingListItems>)t;
                                adapter.setList(data);
                            }
                        });

                        thread.execute();
Ucdemir
  • 2,852
  • 2
  • 26
  • 44