Android - Large file downloads stop - using async/progressdialog
Asked Answered
C

3

7

I have a simple code that is supposed to do one task, when the button is clicked download a file, save it to the SD card, and open it. Everything works except during the download, for larger files, the connection drops and the progress bar hangs - almost always at 20%. I have searched and searched and cannot figure out what to do to keep the connection alive and allow the download to complete. Any ideas how to keep the connection alive so the download completes instead of stalling at 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);
           }


   }
}

Edit with logcat information:

--------- 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
Ceramics answered 30/4, 2012 at 23:16 Comment(8)
How do you define 'large' files? What size?Wilkinson
Does the phone go to sleep during the download?Abundance
@MisterSquonk - not too big, approximately 8MB. The max I will need to download would be about 35MB.Ceramics
@Abundance - No the screen does not go into sleep mode. Also, I am running the code on my phone instead of using an emulator if that makes a differenceCeramics
@user1363871: Are you in control of the server end? In other words, can you see any logs at the server that might show download progress?Wilkinson
@MisterSquonk - No, I can't see anything serverside. As of now I'm just downloading random files on the internet (using filetype:doc in google)...Ceramics
can you add some debug print in the exception handler (just in case)? Did you check if the logcat shows anything suspect? I have some code I use to download ~50MB files, pretty much the same as yours and it works fine on phone or emulator...Olimpiaolin
@Olimpiaolin - I will edit my post with a logcat taken that shows the install of the program on my phone from eclipse while the program is hanging during download. Can you tell me where it differs from yours? Maybe I can tweak it some.Ceramics
A
2

I've tried to download your file a few times, looks like download stalls for a few seconds here and there, and it might trigger a timeout in your application. Try to specify timeouts explicitly in range 10-20 seconds.

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;
}
Agential answered 1/5, 2012 at 11:14 Comment(3)
Should I change the code in any other way than timeouts in your opinion? I'm pretty new to this and am trying to learn on the fly, would it be too much to ask for an example of the timeouts? Thanks!Ceramics
i've added an example, it uses HttpClient instead of url.connection,and you have to add correct outputFile variable for your output file.Agential
I'm hoping this helps someone experiencing the same problem - selecting as accepted answer. Thanks.Ceramics
O
1

What seems to be the problem is that process 199 in your logcat seem to be your activity, but then it shows:

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

(and the second line shows that it is killing your asynctask...).

I don't think there is anything wrong with the download code by itself. I think you should look more in the activity (what are you doing during that time beside that asynctask, what are you displaying on the screen...etc...).

Seems also that you are pretty low in heap space.

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

Those are from the garbage collection and happen just before your app crashed, maybe that could be a problem too?

Olimpiaolin answered 1/5, 2012 at 3:44 Comment(2)
I think I can explain that, after a bit of time waiting on the file download and it not going anywhere I did "long press back to terminate" the app. So thats why its being killed and removed... as of the heap space I don't know what to say. I restarted my phone and it still hangs.Ceramics
I don't know if this means anything, but I tested multiple files online to download. Taking the length of file in logcat and dividing by the percentage that the download stops I always get a value of between 428799 - 471531.. Does this mean anything? Maybe with my buffer or something like that?Ceramics
P
1

every thread in Android is being killed by the system if it doesn't respond for more than five minutes. maybe you should consider downloading as a service or overriding the onProgress and get the thread to stay alive

Parrnell answered 1/5, 2012 at 11:19 Comment(2)
Can you show or link me to an example to download as a service?Ceramics
it seems to me like doing the onProgress will be a better solutionParrnell

© 2022 - 2024 — McMap. All rights reserved.