0

我有一个 AsyncTask 一个一个下载文件,当它在 android 2.x 上运行时,我将它作为一个队列,很好。在 android 4.0+ 中它停止工作。这里我给 AsyncTask 传递了一个 ProgressBar,所以它会更新加载进度条,并指出它在哪里。

奇怪的部分是进度条会很快 100% 不匹配文件的实际大小。而且logcat中文件输出的长度也错误...

所有任务都将串行执行,因此不会损害 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();

        }
    }
4

2 回答 2

1

Android 4.0中的较新版本可能HttpUrlConnection导致服务器使用HTTP/1.1 中支持的Chunked Transfer Encoding 。Android 2.x 版本可能不支持 CTE。当使用 CTE 发送响应时(例如,在文件/视频流传输期间),服务器不会返回内容长度。因此,您可能希望ProgressBar在内容长度不可用时显示不确定。

于 2012-11-12T18:10:23.567 回答
0

删除后我终于发现了问题conn.setDoOutput(true)所在,它在 android 2.x 和 4.x 模拟器上运行良好,我认为 acj 也有道理,有时分块传输编码也是原因。

于 2012-11-13T06:41:39.837 回答