Активность с ProgressBar -> Сервис -> AsyncTask на скачивание - а как обновить прогресс?

это текущее состояние/ситуация: у меня есть действие, которое связывает службу, которая создает AsyncTasks, которые загружают различные веб-ресурсы. Это работает хорошо, но ProgressBar ничего не показывает.

Раньше у меня была активность, которая создавала AsyncTask, которая загружала некоторые вещи. AsyncTask получил представление, которое содержит ProgressBar. Поэтому я мог бы обновить прогресс, используя onProgressUpdate и publishProgress. Очевидно, это больше не работает, потому что у меня нет ссылки на ProgressBar.

Итак, у вас есть какие-либо идеи о том, как обновить прогресс?

Заранее спасибо.


person dAnjou    schedule 28.12.2009    source источник


Ответы (3)


Попросите Service уведомить работающую на тот момент Activity о ходе работы с onProgressUpdate(). Это может быть через широковещательную рассылку Intent или через объект обратного вызова, зарегистрированный Activity (и незарегистрированный, когда Activity уничтожается, например, при повороте экрана).

person CommonsWare    schedule 28.12.2009
comment
Спасибо. Теперь у меня есть класс ProgressReceiver, который расширяет BroadcastReceiver. Намерения от onProgressUpdate() попадают туда, и я могу прочитать их прогресс. Но как я могу обновить ProgressBar? Извините, я не понимаю :( - person dAnjou; 29.12.2009
comment
Сделайте этот ProgressReceiver внутренним классом вашей Activity, зарегистрированным через registerReceiver() и незарегистрированным через unregisterReceiver(). Затем ProgressReceiver может просто вызвать setProgress() или incrementProgressBy() на вашем ProgressBar. - person CommonsWare; 29.12.2009
comment
@Commonsware, вы не думаете, что трансляция чего-то каждую секунду будет потреблять память или батарею? например, если я загружу какой-нибудь файл размером 10 МБ и имею пропускную способность сети 100 кбит/с, то он будет транслироваться 100 раз... скорее я предпочитаю интерфейс между сервисом и активностью... это будет облегчено?? - person Himanshu Mori; 21.10.2016
comment
@HimanshuMori: этому вопросу и ответу почти семь лет. Вы не думаете, что трансляция чего-то каждую секунду будет потреблять память или батарею? -- не по сравнению с самой загрузкой. Загрузка потребует на несколько порядков больше энергии, а влияние памяти здесь незначительно. При этом в настоящее время я бы рекомендовал шину событий (LocalBroadcastManager, EventBus от greenrobot), чтобы несколько повысить эффективность, но, что более важно, повысить безопасность. - person CommonsWare; 21.10.2016

Очень хорошо объяснил, просто пропустил пример :) Я пошел бросить его, и вот он.

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);    
}
person Paulo Almeida    schedule 12.04.2011
comment
он был опубликован, возможно, теперь с изменениями API может потребоваться некоторая полировка. - person Paulo Almeida; 14.08.2012
comment
BroadcastReceiver — хорошая идея, но я бы посоветовал использовать LocalBroadcastManager из библиотеки поддержки Android. Он отправляет только Intents в ВАШЕМ приложении, поэтому он более безопасен и эффективен. - person Tom; 23.08.2012

Вы можете так же легко показать прогресс с помощью Toast, который устраняет все проблемы с пользовательским интерфейсом:

public class foo extends Service {
private Toast toast;

@SuppressLint("ShowToast")
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);
    ctxt = getApplicationContext();
    toast = Toast.makeText(ctxt, "", Toast.LENGTH_SHORT);
    ...
}

public void functionCalledByYourAsyncWithUpdates(String progress){
    toast.setText (progress);
    toast.show;
}
}
person heights1976    schedule 21.10.2015