Как реализовать индикатор выполнения загрузки файлов в android

Я загружаю файлы через org.apache.http.client.HttpClient в android, и мне нужно реализовать индикатор выполнения. Можно ли добиться прогресса от:?

HttpPost httppost = new HttpPost("some path");
HttpClient httpclient = new DefaultHttpClient();
try {
File file = new File("file path");
InputStream in = new BufferedInputStream(new FileInputStream(file));
byte[] bArray = new byte[(int) file.length()];
in.read(bArray);
String entity = Base64.encodeToString(bArray, Base64.DEFAULT);
httppost.setEntity(new StringEntity(entity));
HttpResponse response = httpclient.execute(httppost);
}

Если нет, пожалуйста, покажите альтернативный путь. Благодаря

Ответы

Ответ 1

Что вам нужно сделать, так это создать AsyncTask, который может обрабатывать это для вас, переопределяя метод onProgressUpdate.

Вот урезанная версия того, что я тестировал в другом приложении, используя HttpURLConnection. Могут быть некоторые небольшие увольнения, и я думаю, что HttpURLConnection может вообще не одобряться, но это должно сработать. Просто используйте этот класс в любом классе активности, который вы используете (в этом примере я называю его TheActivity), вызывая new FileUploadTask().execute(). Конечно, вам может потребоваться настроить его, чтобы он соответствовал потребностям вашего приложения.

private class FileUploadTask extends AsyncTask<Object, Integer, Void> {

    private ProgressDialog dialog;

    @Override
    protected void onPreExecute() {
        dialog = new ProgressDialog(TheActivity.this);
        dialog.setMessage("Uploading...");
        dialog.setIndeterminate(false);
        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        dialog.setProgress(0);
        dialog.show();
    }

    @Override
    protected Void doInBackground(Object... arg0) {
        try {
            File file = new File("file path");
            FileInputStream fileInputStream = new FileInputStream(file);
            byte[] bytes = new byte[(int) file.length()];
            fileInputStream.read(bytes);
            fileInputStream.close();

            URL url = new URL("some path");
            HttpURLConnection connection = 
                    (HttpURLConnection) url.openConnection();
            OutputStream outputStream = connection.getOutputStream();

            int bufferLength = 1024;
            for (int i = 0; i < bytes.length; i += bufferLength) {
                int progress = (int)((i / (float) bytes.length) * 100);
                publishProgress(progress);
                if (bytes.length - i >= bufferLength) {
                    outputStream.write(bytes, i, bufferLength);
                } else {
                    outputStream.write(bytes, i, bytes.length - i);
                }
            }
            publishProgress(100);

            outputStream.close();
            outputStream.flush();

            InputStream inputStream = connection.getInputStream();
            // read the response
            inputStream.close();

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        dialog.setProgress(progress[0]);
    }

    @Override
    protected void onPostExecute(Void result) {
        try {
            dialog.dismiss();
        } catch(Exception e) {
        }

    }

}

Ответ 2

Я не думаю, что HttpURLConnection просто делает трюк, как отметил @Basbous, фактические данные буферируются до тех пор, пока не вызывается outputStream.flush(). Согласно android issue 3164, теперь он исправлен в платформе post-froyo (Android 2.2, sdk версия 8), вам нужно использовать java.net. HttpURLConnection.setFixedLengthStreamingMode, чтобы обойти поведение буфера.