Android - 大文件下载停止 - 使用async / progressdialog

时间:2012-04-30 23:16:52

标签: java android asynchronous download progressdialog

我有一个简单的代码应该执行一项任务,当单击按钮下载文件,将其保存到SD卡,然后打开它。一切正常,除了在下载期间,对于较大的文件,连接丢失和进度条挂起 - 几乎总是在20%。我搜索并搜索过,无法弄清楚如何保持连接活动并允许下载完成。 有关如何保持连接处于活动状态的任何想法,以便下载完成而不是停滞在20%?

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class DownloadTestActivity extends Activity {

   public static final int DIALOG_DOWNLOAD_PROGRESS = 0;
   private Button startBtn;
   private ProgressDialog mProgressDialog;

   /** Called when the activity is first created. */
   @Override
   public void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.main);
           mProgressDialog = new ProgressDialog(DownloadTestActivity.this);
           mProgressDialog.setMessage("Downloading...");
           mProgressDialog.setIndeterminate(false);
           mProgressDialog.setMax(100);
           mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

           startBtn = (Button) findViewById(R.id.startBtn);
           startBtn.setOnClickListener(new OnClickListener() {
                   public void onClick(View v) {
                           startDownload();
                   }
           });
   }

   private void startDownload() {
           DownloadFile downloadFile = new DownloadFile();
           downloadFile
                           .execute("http://www.website.com/file.pdf");

   }

   class DownloadFile extends AsyncTask<String, Integer, String> {

           @Override
           protected void onPreExecute() {
                   super.onPreExecute();
                   mProgressDialog.show();
           }

           @Override
           protected void onProgressUpdate(Integer... progress) {
                   super.onProgressUpdate(progress);
                   mProgressDialog.setProgress(progress[0]);
           }

           @Override
           protected String doInBackground(String... aurl) {
                   try {
                           URL url = new URL(aurl[0]);
                           URLConnection connection = url.openConnection();
                           connection.connect();

                           int fileLength = connection.getContentLength();
                           Log.d("ANDRO_ASYNC", "Lenght of file: " + fileLength);

                           InputStream input = new BufferedInputStream(url.openStream());
                           String path = Environment.getExternalStorageDirectory()
                                           + "/Android/Data/"
                                           + getApplicationContext().getPackageName() + "/files";
                           File file = new File(path);
                           file.mkdirs();
                           File outputFile = new File(file, "test1.doc");
                           OutputStream output = new FileOutputStream(outputFile);

                           byte data[] = new byte[8192];
                           long total = 0;
                           int count;
                           while ((count = input.read(data)) != -1) {
                                   total += count;
                                   publishProgress((int) (total * 100 / fileLength));
                                   output.write(data, 0, count);
                           }

                           output.flush();
                           output.close();
                           input.close();
                           showPdf();

                   } catch (Exception e) {
                   }
                   return null;
           }

           private void showPdf() {
                   // TODO Auto-generated method stub
           if(mProgressDialog != null){
                   mProgressDialog.dismiss();
           }

                   File file = new File(Environment.getExternalStorageDirectory()
                                   + "/Android/Data/"
                                   + getApplicationContext().getPackageName()
                                   + "/files/test1.doc");
                   PackageManager packageManager = getPackageManager();
                   Intent testIntent = new Intent(Intent.ACTION_VIEW);
                   testIntent.setType("application/msword");
                   List list = packageManager.queryIntentActivities(testIntent,
                                   PackageManager.MATCH_DEFAULT_ONLY);
                   Intent intent = new Intent();
                   intent.setAction(Intent.ACTION_VIEW);
                   Uri uri = Uri.fromFile(file);
                   intent.setDataAndType(uri, "application/msword");
                   startActivity(intent);
           }


   }
}

使用logcat信息进行编辑:

--------- beginning of /dev/log/system
W/InputManagerService(  199): Window already focused, ignoring focus gain of:     com.android.internal.view.IInputMethodClient$Stub$Proxy@4137b898
--------- beginning of /dev/log/main
D/AndroidRuntime(20673): 
D/AndroidRuntime(20673): >>>>>> AndroidRuntime START com.android.internal.os.RuntimeInit <<<<<<
D/AndroidRuntime(20673): CheckJNI is OFF
D/AndroidRuntime(20673): Calling main entry com.android.commands.pm.Pm
D/AndroidRuntime(20673): Shutting down VM
D/dalvikvm(20673): GC_CONCURRENT freed 101K, 82% free 467K/2560K, paused 1ms+0ms
D/dalvikvm(20673): Debugger has detached; object registry had 1 entries
I/AndroidRuntime(20673): NOTE: attach of thread 'Binder Thread #3' failed
D/AndroidRuntime(20687): 
D/AndroidRuntime(20687): >>>>>> AndroidRuntime START com.android.internal.os.RuntimeInit <<<<<<
D/AndroidRuntime(20687): CheckJNI is OFF
D/AndroidRuntime(20687): Calling main entry com.android.commands.am.Am
I/ActivityManager(  199): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.myapp/.Activity} from pid 20687
D/AndroidRuntime(20687): Shutting down VM
D/dalvikvm(20687): GC_CONCURRENT freed 102K, 81% free 489K/2560K, paused 0ms+0ms
D/jdwp    (20687): Got wake-up signal, bailing out of select
D/dalvikvm(20687): Debugger has detached; object registry had 1 entries
I/AndroidRuntime(20687): NOTE: attach of thread 'Binder Thread #3' failed
D/dalvikvm(20698): Late-enabling CheckJNI
I/ActivityManager(  199): Start proc com.myapp for activity     com.myapp/.Activity: pid=20698 uid=10102 gids={1015, 3003}
I/dalvikvm(20698): Turning on JNI app bug workarounds for target SDK version 10...
V/PhoneStatusBar(  271): setLightsOn(true)
D/AudioHardware(   98): AudioHardware pcm playback is going to standby.
D/AudioHardware(   98): closePcmOut_l() mPcmOpenCnt: 1
I/ActivityManager(  199): Displayed com.myapp/.Activity: +197ms
W/InputManagerService(  199): Starting input on non-focused client com.android.internal.view.IInputMethodClient$Stub$Proxy@4199ed28 (uid=10098 pid=20011)
I/ActivityManager(  199): START {cmp=com.myapp/.Choice} from pid 20698
D/AudioHardware(   98): AudioHardware pcm playback is exiting standby.
D/AudioHardware(   98): openPcmOut_l() mPcmOpenCnt: 0
V/PhoneStatusBar(  271): setLightsOn(true)
I/ActivityManager(  199): Displayed com.myapp/.Choice: +93ms
D/ANDRO_ASYNC(20698): Lenght of file: 736768
D/dalvikvm(20698): GC_CONCURRENT freed 103K, 3% free 9403K/9607K, paused 2ms+3ms
W/NetworkStats(  199): found non-monotonic values; saving to dropbox
D/dalvikvm(  199): JIT code cache reset in 5 ms (1048440 bytes 13/0)
D/dalvikvm(  199): GC_CONCURRENT freed 1472K, 13% free 24697K/28231K, paused 12ms+14ms
D/AudioHardware(   98): AudioHardware pcm playback is going to standby.
D/AudioHardware(   98): closePcmOut_l() mPcmOpenCnt: 1
I/ActivityManager(  199): Force stopping package com.myapp uid=10102
I/ActivityManager(  199): Killing proc 20698:com.myapp/10102: force stop
W/ActivityManager(  199): Force removing ActivityRecord{41eb1ec0 com.myapp/.Choice}: app died, no saved state
I/InputDispatcher(  199): Dropping event because there is no focused window or focused application.
I/ActivityManager(  199):   Force finishing activity ActivityRecord{418450c8 com.myapp/.Activity}
I/InputDispatcher(  199): Dropping event because there is no focused window or focused application.
W/InputDispatcher(  199): channel '417b41f0     com.myapp/com.myapp/.Activity (server)' ~     Consumer closed input channel or an error occurred.  events=0x8
E/InputDispatcher(  199): channel '417b41f0 com.myapp/com.myapp.Activity (server)' ~ Channel is unrecoverably broken and will be disposed!
W/InputDispatcher(  199): Attempted to unregister already unregistered input channel '417b41f0 com.myapp/com.myapp.Activity (server)'
W/WindowManager(  199): Failed looking up window
W/WindowManager(  199): java.lang.IllegalArgumentException: Requested window android.os.BinderProxy@41c7ffc8 does not exist
W/WindowManager(  199): at com.android.server.wm.WindowManagerService.windowForClientLocked(WindowManagerService.java:7176)
W/WindowManager(  199): at com.android.server.wm.WindowManagerService.windowForClientLocked(WindowManagerService.java:7167)
W/WindowManager(  199): at com.android.server.wm.WindowState$DeathRecipient.binderDied(WindowState.java:1545)
W/WindowManager(  199): at android.os.BinderProxy.sendDeathNotice(Binder.java:417)
W/WindowManager(  199): at dalvik.system.NativeStart.run(Native Method)
I/WindowManager(  199): WIN DEATH: null
I/WindowManager(  199): WIN DEATH: Window{4175b280     com.myapp/com.myapp.Choice paused=false}
W/WindowManager(  199): Failed looking up window
W/WindowManager(  199): java.lang.IllegalArgumentException: Requested window android.os.BinderProxy@41758028 does not exist
W/WindowManager(  199): at com.android.server.wm.WindowManagerService.windowForClientLocked(WindowManagerService.java:7176)
W/WindowManager(  199): at com.android.server.wm.WindowManagerService.windowForClientLocked(WindowManagerService.java:7167)
W/WindowManager(  199): at com.android.server.wm.WindowState$DeathRecipient.binderDied(WindowState.java:1545)
W/WindowManager(  199): at android.os.BinderProxy.sendDeathNotice(Binder.java:417)
W/WindowManager(  199): at dalvik.system.NativeStart.run(Native Method)
I/WindowManager(  199): WIN DEATH: null
W/InputManagerService(  199): Got RemoteException sending setActive(false) notification to pid 20698 uid 10102
D/dalvikvm(20011): GC_CONCURRENT freed 460K, 32% free 9468K/13767K, paused 3ms+4ms
D/AudioHardware(   98): AudioHardware pcm playback is exiting standby.
D/AudioHardware(   98): openPcmOut_l() mPcmOpenCnt: 0

3 个答案:

答案 0 :(得分:2)

我已经尝试过几次下载你的文件,看起来像是在这里和那里下载停顿几秒钟,它可能会在你的应用程序中触发超时。尝试在10-20秒范围内明确指定超时。

private DefaultHttpClient httpclient = new DefaultHttpClient();
private HttpGet get = new HttpGet("your url comes here");

protected String[] doInBackground(Void... v) {
    HttpParams httpParameters = new BasicHttpParams();
    // set the timeout in milliseconds until a connection is established
    // the default value is zero, that means the timeout is not used 
    int timeoutConnection = 3000;
    HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
    // set the default socket timeout (SO_TIMEOUT) in milliseconds
    // which is the timeout for waiting for data
    int timeoutSocket = 5000;
    HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);

    httpclient.setParams(httpParameters);

    try {
        HttpEntity entity = httpclient.execute( get ).getEntity();
        FileOutputStream output = new FileOutputStream(outputFile);
        entity.writeTo(output);
        output.close();
        // return something, maybe?
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        httpclient.getConnectionManager().shutdown();
    }
    return null;
}

答案 1 :(得分:1)

似乎问题是你的logcat中的进程199似乎是你的活动,但它显示:

I/ActivityManager(  199): Force stopping package com.viperean.atcassistant uid=10102
I/ActivityManager(  199): Killing proc 20698:com.viperean.atcassistant/10102: force stop
W/ActivityManager(  199): Force removing ActivityRecord{41eb1ec0 com.viperean.atcassistant/.atcChoice}: app died, no saved state

(第二行表明它正在杀死你的asynctask ...)。

我认为下载代码本身没有任何问题。我认为你应该更多地看一下这个活动(那个时候除了那个asynctask你在做什么,你在屏幕上显示什么......等等。)。

似乎你的堆空间也很低。

D/dalvikvm(20698): GC_CONCURRENT freed 103K, 3% free 9403K/9607K, paused 2ms+3ms
D/dalvikvm(  199): JIT code cache reset in 5 ms (1048440 bytes 13/0)
D/dalvikvm(  199): GC_CONCURRENT freed 1472K, 13% free 24697K/28231K, paused 12ms+14ms

那些来自垃圾收集并且在您的应用程序崩溃之前发生,也许这可能也是一个问题?

答案 2 :(得分:1)

如果超过五分钟没有响应,那么Android中的每个线程都会被系统杀死。也许你应该考虑下载为服务或覆盖onProgress并让线程保持活力