简体   繁体   中英

Android - download failed at 4.0+ devices AsyncTask

I have an AsyncTask to download files one by one, and I make it as a queue, when it's running on android 2.x, good. In android 4.0+ it stop working. Here I passed a ProgressBar to AsyncTask, so it will update the loading progress bar, and indicate where it is.

The strange part is the progress bar will go 100% very quick not match the real size of file. And the length of file output in logcat also wrong...

All tasks will execute serially so it won't hurt the parallel limitation above SDK 11. I guess the problem might be inside the download part, just don't know where it is.

public function download ()
{
    .....
    if (task != null) {
        task.cancel (true);
    }
    task = new OnlineDownloadTask (progress);
    task.execute (url, path);
    .....
}

class OnlineDownloadTask extends AsyncTask<String, String, String> {

        private final WeakReference<OfflineQueueIndicatorView> progressbarReference;

        public OnlineDownloadTask(OfflineQueueIndicatorView progress) {
            progressbarReference = new WeakReference<OfflineQueueIndicatorView>(
                    progress);
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected String doInBackground(String... aurl) {
            int count;

            try {

                URL url = new URL(aurl[0]);
                HttpURLConnection conn = (HttpURLConnection) url
                        .openConnection();
                conn.setConnectTimeout(10000);
                conn.setReadTimeout(10000);
                conn.setRequestMethod("GET");
                conn.setAllowUserInteraction(false);
                conn.setDoInput(true);
                conn.setDoOutput(true);
                conn.connect();

                int lengthOfFile = conn.getContentLength();

                android.util.Log.v("offline.downloader", lengthOfFile + "");
                InputStream input = new BufferedInputStream(url.openStream());
                OutputStream output = new FileOutputStream(aurl[1]);

                try {
                    byte data[] = new byte[1024];

                    long total = 0;

                    while ((count = input.read(data)) != -1) {
                        total += count;
                        publishProgress(""
                                + (int) ((total * 100) / lengthOfFile));

                        if (stopoffline) {
                            android.util.Log.v("file.downloader", "stopped");
                            break;
                        }
                        output.write(data, 0, count);
                    }

                    if (stopoffline) {
                        output.flush();
                        output.close();
                        input.close();
                        conn.disconnect();
                        File file = new File(aurl[1]);

                        if (file.exists()) {
                            file.delete();
                        }

                        stopoffline = false;
                        return null;
                    } else {
                        output.flush();
                        output.close();
                        input.close();
                        conn.disconnect();

                        if (DiskCache.getInstance().offlineDirectoryExist(
                                DiskCache.getInstance().offlineCurrentFolder)) {

                        } else {
                            if (!DiskCache
                                    .getInstance()
                                    .makeOfflineFolder(
                                            DiskCache.getInstance().offlineCurrentFolder)) {
                                return null;
                            }
                        }

                        android.util.Log.v("offline",
                                DiskCache.getInstance().offlineCurrentFolder);
                        unzip(aurl[1],
                                DiskCache.getInstance().offlineCurrentFolder);
                        DiskCache.getInstance().deleteFile(aurl[1]);
                        return "succ";
                    }

                } finally {

                    if (output != null) {
                        output.flush();
                        output.close();
                    }

                    if (input != null) {

                        input.close();
                    }

                    if (conn != null) {
                        conn.disconnect();
                    }
                }
            } catch (Exception e) {

                e.printStackTrace();

            }
            return null;

        }

        protected void onProgressUpdate(String... progress) {
            try {
                if (progressbarReference != null) {
                    OfflineQueueIndicatorView p = progressbarReference.get();

                    if (p != null) {
                        int i = Integer.parseInt(progress[0]);
                        p.setProgress(i);
                    }
                }
            }

            catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        protected void onPostExecute(String ret) {

            try {
                if (progressbarReference != null) {

                    if (ret != null) {
                        queue.get(currentId).put("state", "complete");
                    } else {
                        if (queue != null) {
                            if (currentId != null) {
                                queue.get(currentId).put("state", "failed");
                            }
                        }
                    }

                }
            }

            catch (Exception e) {
                e.printStackTrace();
            }

            download();

        }
    }

It's possible that the newer version of HttpUrlConnection in Android 4.0 is causing the server to use Chunked Transfer Encoding , which is supported in HTTP/1.1. The Android 2.x version may not have supported CTE. When sending a response with CTE (eg, during file/video streaming), the server will not return a content length. As such, you may want to show an indeterminate ProgressBar when the content length is not available.

在删除conn.setDoOutput(true) ,我终于找到了问题conn.setDoOutput(true) ,它在android 2.x和4.x模拟器上都能正常工作,我认为acj也很重要,有时Chunked Transfer Encoding也是原因。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM