2012-11-12 29 views
0

我有一个AsyncTask一个接一个的下载文件,并且我把它作为一个队列,当它在android 2.x上运行时,很好。在Android 4.0+中,它停止工作。在这里,我将一个ProgressBar传递给了AsyncTask,所以它会更新加载进度条并指明它的位置。Android - 在4.0+设备上下载失败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

我终于在删除conn.setDoOutput(true)后发现有什么问题,它在android 2.x和4.x仿真器上都能正常工作,我认为acj也有重要意义,有时Chunked Transfer Encoding也是原因。

1

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

相关问题