Ashish Tanna
Ashish Tanna

Reputation: 677

file download using asynctask stops in middle

I am creating an app for my client, one of his requirements is to download and install an external apk (size approx. 62mb) on the device. The devices will be rooted, so that's not a problem. But, while downloading the apk using AsyncTask, the progress bar resets to 0% after reaching 34% (exact 34% every time, even on different devices) and throws java.io.IOException: unexpected end of stream.

Here is the code I'm using :

public class InstallAPK extends AsyncTask<Void,Integer,Void> {

ProgressDialog progressDialog;
int status = 0;

private Context context;
public InstallAPK(Context context, ProgressDialog progress){
    this.context = context;
    this.progressDialog = progress;
}

public void onPreExecute() {
    if(progressDialog!=null)
        progressDialog.show();
}

@Override
protected Void doInBackground(Void... arg0) {
    try {
        URL url = new URL(context.getString(R.string.kodi_apk_link));
        HttpURLConnection c = (HttpURLConnection) url.openConnection();
        c.setRequestMethod("GET");
        c.setDoOutput(true);
        c.connect();

        // getting file length
        int lenghtOfFile = c.getContentLength();
        Log.e("File length", ""+lenghtOfFile);

        File outputFile = new File(context.getFilesDir(), context.getString(R.string.kodi_apk_name));
        if(outputFile.exists()){
            if(outputFile.length() != lenghtOfFile)
                outputFile.delete();
            else {
                publishProgress(-1);
                final String libs = "LD_LIBRARY_PATH=/vendor/lib:/system/lib ";
                final String commands = libs + "pm install -r " + context.getFilesDir().getAbsolutePath() + "/"
                        + context.getString(R.string.kodi_apk_name);
                installApk(commands);
                return null;                    
            }
        }
        FileOutputStream fos = new FileOutputStream(outputFile);

        InputStream is = c.getInputStream();
        //i tried both, with and without buffered reader
        BufferedInputStream bufferedInputStream = new BufferedInputStream(is);

        byte[] buffer = new byte[1024];
        int len1 = 0, total=0;

        if (lenghtOfFile != -1)
        {
            buffer = new byte[lenghtOfFile];
            do {
                len1 += bufferedInputStream.read(buffer, len1, lenghtOfFile-len1);
                publishProgress((int)((len1*100)/lenghtOfFile));
            } while (len1 < lenghtOfFile);
        }

        //I was using this code before, but it's not working too
        /*while ((len1 = is.read(buffer)) != -1) {
            total += len1;
            publishProgress((int)((total*100)/lenghtOfFile));
            fos.write(buffer, 0, len1);
        }*/
        fos.flush();
        fos.close();
        bufferedInputStream.close();
        is.close();

        //Log.e("Directory path", myDir.getAbsolutePath());

        publishProgress(-1);

        final String libs = "LD_LIBRARY_PATH=/vendor/lib:/system/lib ";

        final String commands = libs + "pm install -r " + context.getFilesDir().getAbsolutePath() + "/"
                + context.getString(R.string.kodi_apk_name);

        installApk(commands);


    } catch (FileNotFoundException fnfe) {
        status = 1;
        Log.e("File", "FileNotFoundException! " + fnfe);
    }

    catch(Exception e)
    {
        Log.e("UpdateAPP", "Exception " + e);
    }
    return null;
}

protected void onProgressUpdate(Integer... progress) {
    if(progress[0]!=-1) {
        // setting progress percentage
        progressDialog.setProgress(progress[0]);
    } else {
        progressDialog.setIndeterminate(true);
        progressDialog.setMessage("Installing Kodi...");
    }
}

public void onPostExecute(Void unused) {
    if(progressDialog!=null) {
        progressDialog.dismiss();
    }
    if(status == 1)
        Toast.makeText(context,"App Not Available",Toast.LENGTH_LONG).show();
    else
        Toast.makeText(context,"Successfully installed the app",Toast.LENGTH_LONG).show();

    Intent LaunchIntent = context.getPackageManager().getLaunchIntentForPackage(context.getString(R.string.kodi_apk_package));
    if(LaunchIntent!=null)
        context.startActivity(LaunchIntent);
    else
        Toast.makeText(context, "Error in installig Kodi, Try again.", Toast.LENGTH_LONG).show();
}

private void installApk(String commands) {
    try {
        Process p = Runtime.getRuntime().exec("su");
        InputStream es = p.getErrorStream();
        DataOutputStream os = new DataOutputStream(p.getOutputStream());

        os.writeBytes(commands + "\n");

        os.writeBytes("exit\n");
        os.flush();

        int read;
        byte[] buffer = new byte[4096];
        String output = new String();
        while ((read = es.read(buffer)) > 0) {
            output += new String(buffer, 0, read);
        }

        Log.v("AutoUpdaterActivity", output.toString());

        p.waitFor();

    } catch (IOException e) {
        Log.v("AutoUpdaterActivity", e.toString());
    } catch (InterruptedException e) {
        Log.v("AutoUpdaterActivity", e.toString());
    }
}

}

Upvotes: 0

Views: 624

Answers (2)

Ashish Tanna
Ashish Tanna

Reputation: 677

I tried everything to make this code work. But, it didn't. Then I found an alternative to this. I tried IntentService to download the apk, and surprisingly it worked. I think AsyncTask might have some kind of limit for downloading. To download using IntentService I used this code. The answer is very informative. It also has some other alternatives for downloading.

Upvotes: 1

pRaNaY
pRaNaY

Reputation: 25312

You should add connection timeout for HttpURLConnection.

      HttpURLConnection c = (HttpURLConnection) url.openConnection();
      c.setRequestMethod("GET");
      c.setDoOutput(true);
      //set timeout to 5 seconds , set your time here
      c.setConnectTimeout(5000);
      c.connect();
   
Its work for me.I hope its work for you.

Upvotes: 0

Related Questions