Activity with ProgressBar -> Service -> AsyncTask for downloading - but how to update the progress?

10,214

Solution 1

Have the Service notify the then-running Activity about the progress from onProgressUpdate(). That could be via a broadcast Intent, or via a callback object registered by the Activity (and unregistered when the Activity is destroyed, such as on a screen rotation).

Solution 2

Very nice explained indeed just missing the example :) I went throw it and here it is.

public class Detail extends Activity {

    private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if(intent.getAction().equals(DownloadService.CUSTOM_INTENT)) {
                mProgressDialog.setProgress(intent.getFlags());
            }
        }
    };

    // Flag if receiver is registered 
    private boolean mReceiversRegistered = false;
    // Define a handler and a broadcast receiver
    private final Handler mHandler = new Handler();

    @Override
    protected void onResume() {
      super.onResume();

      // Register Sync Recievers
      IntentFilter intentToReceiveFilter = new IntentFilter();
      intentToReceiveFilter.addAction(DownloadService.CUSTOM_INTENT);
      this.registerReceiver(mIntentReceiver, intentToReceiveFilter, null, mHandler);
      mReceiversRegistered = true;
    }

    @Override
    public void onPause() {
      super.onPause();

      // Make sure you unregister your receivers when you pause your activity
      if(mReceiversRegistered) {
        unregisterReceiver(mIntentReceiver);
        mReceiversRegistered = false;
      }
    }
}








public class DownloadService extends Service {
    private static final String CLASS_NAME = DownloadService.class.getSimpleName();
    private List<Download> downloads = new ArrayList<Download>();
    private int currentPosition;
    public static final String sdcardPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/";
    private Context ctx;
    @Override
    public IBinder onBind(Intent arg0) {
        ctx = getApplicationContext();
        return mBinder;
    }


    private class DownloadFile extends AsyncTask<String, Integer, String> {

        @Override
        protected String doInBackground(String... _url) {
            Log.d(Constants.LOG_TAG, CLASS_NAME + " Start the background GetNewsTask \nURL :" + _url[0]);
            int count;
            File finalFile = new File(sdcardPath + Constants.APK_LOCAL_PATH + "/" + splitName(_url[0]));
            try {
                if (!finalFile.exists()) {
                    Log.i(Constants.LOG_TAG, CLASS_NAME + " Donwloading apk from the Web");
                    URL url = new URL(_url[0]);
                    URLConnection conexion = url.openConnection();
                    conexion.connect();
                    // this will be useful so that you can show a tipical 0-100%
                    // progress bar
                    int lenghtOfFile = conexion.getContentLength();
                    // downlod the file
                    InputStream input = new BufferedInputStream(url.openStream());
                    File dir = new File(sdcardPath + Constants.APK_LOCAL_PATH);
                    if (!dir.exists())
                        dir.mkdirs();
                    OutputStream output = new FileOutputStream(sdcardPath + Constants.APK_LOCAL_PATH + "/" + splitName(_url[0]));
                    byte data[] = new byte[1024];
                    long total = 0;
                    while ((count = input.read(data)) != -1) {
                        total += count;
                        // publishing the progress....
                        publishProgress((int) (total * 100 / lenghtOfFile));
                        output.write(data, 0, count);
                    }
                    output.flush();
                    output.close();
                    input.close();
                } else {
                    Log.i(Constants.LOG_TAG, CLASS_NAME + " Apk in SDcard");
                    publishProgress(100);
                }
            } catch (Exception e) {
            }

            return null;

        }

        @Override
        protected void onProgressUpdate(Integer... progress) {
            Intent i = new Intent();
            i.setAction(CUSTOM_INTENT);
            i.setFlags(progress[0]);
            ctx.sendBroadcast(i);
        }
    }

    private String splitName(String url) {
        String[] output = url.split("/");
        return output[output.length - 1];
    }

    public static final String CUSTOM_INTENT = "es.tempos21.sync.client.ProgressReceiver";

    private final IDownloadService.Stub mBinder = new IDownloadService.Stub() {

        public void downloadAsynFile(String url) throws DeadObjectException {
            try {
                DownloadFile d = new DownloadFile();
                d.execute(url);
            } catch (Exception e) {
                Log.e(Constants.LOG_TAG, CLASS_NAME + " " +e.getMessage());         }
        }


        }
};


interface IDownloadService {

    void downloadAsynFile(String url);    
}
Share:
10,214
dAnjou
Author by

dAnjou

Money is secondary. I care about how people work together. I care about internal and external transparency, integrity and open and honest communication. Ideally I'd like to contribute to something that improves everyday life or even society itself. I'd like to contribute with everything I've got, not just with code. My strong suit is definitely Python in the context of web services. However, I'm very interested to learn other stacks (Go looks very nice) or even move into the "DevOps" or "infrastructure-as-code" field.

Updated on June 14, 2022

Comments

  • dAnjou
    dAnjou almost 2 years

    this is the current state/situation: I have an Activity which binds a Service which creates AsyncTasks which downloads various web resources. That works well, but of course the ProgressBar shows nothing.

    Previously i had an Activity which created an AsyncTask which downloaded some stuff. The AsyncTask got the View which holds the ProgressBar. So i could update the progress using onProgressUpdate and publishProgress. Obviously this doesn't work any longer because I have no reference to the ProgressBar.

    So, do you have any idea on how to update the progress?

    Thanks in advance.