我有一个AsyncTask来逐个下载文件,我把它作为一个队列,当它在android 2.x上运行时,很好。在android 4.0+中它停止工作。在这里,我将ProgressBar传递给AsyncTask,因此它将更新加载进度条,并指出它在哪里。
奇怪的是,进度条会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();
}
}
答案 0 :(得分:1)
Android 4.0中较新版本的HttpUrlConnection
可能导致服务器使用HTTP {1.1支持的Chunked Transfer Encoding。 Android 2.x版本可能没有支持CTE。当使用CTE发送响应时(例如,在文件/视频流传输期间),服务器将不返回内容长度。因此,当内容长度不可用时,您可能希望显示不确定的ProgressBar
。
答案 1 :(得分:0)
我在删除conn.setDoOutput(true)
后终于找到了什么问题,它在android 2.x和4.x模拟器上运行良好,我认为acj也有重点,有时Chunked Transfer Encoding也是原因。< / p>