[英]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.