title: How can I display real-time progress updates from a Spring Boot backend in Android?
body: <p>I have an Android app that communicates with a Spring Boot backend.  The backend is responsible for importing records into a database when the user requests it through the app.  I would like the backend to send the names of the records back to the app while the processing is happening in real time so that the app user knows what is happening on the server.  Currently the backend only returns a status string when the all of the processing has been completed.  How can I get the backend to send status information back to the app as the records are being processed, and how do I handle it in the app?  I've included the relevant code from my backend and from the Android app below.</p>
  
  <p>I've tried searching on-line, but the closest thing I've found is <a href="https://stackoverflow.com/questions/27310554/android-real-time-updates-from-server">Android real time updates from server</a>.  One user suggests using an AsyncTask, which I'm doing, but doesn't provide an example implementation.</p>
  
  <p>Backend code:</p>
  
  <pre><code>@Controller
  @RequestMapping("/myproject")
  public class TestController {
      @Autowired
      JdbcTemplate jdbcTemplate;
  
      @GetMapping("/import_new_record")
      public @ResponseBody String importNewRecord() throws IOException
      {
          int count = 0;
          // a list of records to be imported; in real life, each item in the list will be one line from a text file
          String[] recordList = {"foo1","bar1","foo2","bar2","foo3","bar3"};
          for (String record: recordList)
          {
              // update the db
              this.jdbcTemplate.update("INSERT INTO mydb.mytable (id, record) VALUES (?, ?)", count, record);
  
              // send count and record string back to app
              // .....
  
              // increment ID
              count++;
          }
      return String.valueOf(count);
      }
  }
  </code></pre>
  
  <p>Android app:</p>
  
  <pre><code>public class ImportRecordActivity extends Activity
  {
      ProgressBar pb;
      TextView tvNew;
  
      @Override
      protected void onCreate(Bundle b) {
          super.onCreate(b);
          setContentView(R.layout.activity_import_record);
  
          pb = (ProgressBar) findViewById(R.id.indeterminateBar);
          pb.setVisibility(ProgressBar.INVISIBLE);
  
          tvNew = (TextView) findViewById(R.id.tvNew);
          tvNew.setOnClickListener(new View.OnClickListener()
          {
              @Override
              public void onClick(View v)
              {
                  new ImportNewRecords().execute(1);
              }
          });
      }
  
  // AsyncTask to trigger record import on the backend
      private class ImportNewRecords extends AsyncTask&lt;Integer, Integer, String&gt;
      {
          String result;
          String myServerAddress = "localhost";
  
          protected String doInBackground(Integer... args) {
              StringBuilder sb = new StringBuilder();
              try {
                  publishProgress(100);
                  URL url = new URL("http://"+myServerAddress+":8080/myproject/import_new_record");
                  HttpURLConnection con = (HttpURLConnection) url.openConnection();
                  BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(con.getInputStream()));
                  String s;
                  while ((s = bufferedReader.readLine()) != null) {
                      sb.append(s + "\n");
                  }
                  result = sb.toString();
              } catch (Exception e) {
                  e.printStackTrace();
              }
              return result;
          }
  
  
          // Display an indeterminate progress bar
          // Presumably the code to display real-time progress should go here
          @Override
          protected void onProgressUpdate(Integer... args) {
              pb.setVisibility(ProgressBar.VISIBLE);
          }
  
          @Override
          protected void onPostExecute(String result) {
              // kill the progress bar
              pb.setVisibility(ProgressBar.INVISIBLE);
              // display the number of records imported in a Toast
              result = StringUtils.trim(result);
              Toast toast = Toast.makeText(ImportRecordActivity.this, result, Toast.LENGTH_LONG);
              View view = toast.getView();
              TextView text = view.findViewById(android.R.id.message);
              toast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL, 0, 0);
              toast.show();
          }
  
          @Override
          protected void onPreExecute()
          {
          }
      }
  }
  </code></pre>