简体   繁体   English

Android-在4.0+设备AsyncTask上下载失败

[英]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. 我有一个AsyncTask来一步一步下载文件,当它在android 2.x上运行时,我将它作为队列。 In android 4.0+ it stop working. 在android 4.0+中,它停止工作。 Here I passed a ProgressBar to AsyncTask, so it will update the loading progress bar, and indicate where it is. 在这里,我向AsyncTask传递了一个ProgressBar,因此它将更新加载进度栏,并指示其位置。

The strange part is the progress bar will go 100% very quick not match the real size of file. 奇怪的是进度条会非常快地100%匹配文件的实际大小。 And the length of file output in logcat also wrong... 而且logcat中文件输出的长度也出错了...

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. 所有任务将串行执行,因此不会损害SDK 11上方的并行限制。我想问题可能出在下载部分,只是不知道它在哪里。

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. Android 4.0中较新版本的HttpUrlConnection可能导致服务器使用Chunked Transfer Encoding (在HTTP / 1.1中受支持)。 The Android 2.x version may not have supported CTE. Android 2.x版本可能不支持CTE。 When sending a response with CTE (eg, during file/video streaming), the server will not return a content length. 当发送带有CTE的响应时(例如,在文件/视频流期间),服务器将不返回内容长度。 As such, you may want to show an indeterminate ProgressBar when the content length is not available. 因此,当内容长度不可用时,您可能想显示一个不确定的ProgressBar

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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