Home | History | Annotate | Download | only in android_scripting
      1 /*
      2  * Copyright (C) 2016 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy of
      6  * the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations under
     14  * the License.
     15  */
     16 
     17 package com.googlecode.android_scripting;
     18 
     19 import android.app.ProgressDialog;
     20 import android.content.Context;
     21 import android.content.DialogInterface;
     22 import android.os.AsyncTask;
     23 
     24 
     25 import com.googlecode.android_scripting.IoUtils;
     26 import com.googlecode.android_scripting.Log;
     27 import com.googlecode.android_scripting.exception.Sl4aException;
     28 
     29 import java.io.File;
     30 import java.io.FileNotFoundException;
     31 import java.io.FileOutputStream;
     32 import java.io.IOException;
     33 import java.io.OutputStream;
     34 import java.net.MalformedURLException;
     35 import java.net.URL;
     36 import java.net.URLConnection;
     37 
     38 /**
     39  * AsyncTask for extracting ZIP files.
     40  *
     41  * @author Damon Kohler (damonkohler (at) gmail.com)
     42  * @author Alexey Reznichenko (alexey.reznichenko (at) gmail.com)
     43  */
     44 public class UrlDownloaderTask extends AsyncTask<Void, Integer, Long> {
     45 
     46   private final URL mUrl;
     47   private final File mFile;
     48   private final ProgressDialog mDialog;
     49 
     50   private Throwable mException;
     51   private OutputStream mProgressReportingOutputStream;
     52 
     53   private final class ProgressReportingOutputStream extends FileOutputStream {
     54     private int mProgress = 0;
     55 
     56     private ProgressReportingOutputStream(File f) throws FileNotFoundException {
     57       super(f);
     58     }
     59 
     60     @Override
     61     public void write(byte[] buffer, int offset, int count) throws IOException {
     62       super.write(buffer, offset, count);
     63       mProgress += count;
     64       publishProgress(mProgress);
     65     }
     66   }
     67 
     68   public UrlDownloaderTask(String url, String out, Context context) throws MalformedURLException {
     69     super();
     70     if (context != null) {
     71       mDialog = new ProgressDialog(context);
     72     } else {
     73       mDialog = null;
     74     }
     75     mUrl = new URL(url);
     76     String fileName = new File(mUrl.getFile()).getName();
     77     mFile = new File(out, fileName);
     78   }
     79 
     80   @Override
     81   protected void onPreExecute() {
     82     Log.v("Downloading " + mUrl);
     83     if (mDialog != null) {
     84       mDialog.setTitle("Downloading");
     85       mDialog.setMessage(mFile.getName());
     86       // mDialog.setIndeterminate(true);
     87       mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
     88       mDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
     89         @Override
     90         public void onCancel(DialogInterface dialog) {
     91           cancel(true);
     92         }
     93       });
     94       mDialog.show();
     95     }
     96   }
     97 
     98   @Override
     99   protected Long doInBackground(Void... params) {
    100     try {
    101       return download();
    102     } catch (Exception e) {
    103       if (mFile.exists()) {
    104         // Clean up bad downloads.
    105         mFile.delete();
    106       }
    107       mException = e;
    108       return null;
    109     }
    110   }
    111 
    112   @Override
    113   protected void onProgressUpdate(Integer... progress) {
    114     if (mDialog == null) {
    115       return;
    116     }
    117     if (progress.length > 1) {
    118       int contentLength = progress[1];
    119       if (contentLength == -1) {
    120         mDialog.setIndeterminate(true);
    121       } else {
    122         mDialog.setMax(contentLength);
    123       }
    124     } else {
    125       mDialog.setProgress(progress[0].intValue());
    126     }
    127   }
    128 
    129   @Override
    130   protected void onPostExecute(Long result) {
    131     if (mDialog != null && mDialog.isShowing()) {
    132       mDialog.dismiss();
    133     }
    134     if (isCancelled()) {
    135       return;
    136     }
    137     if (mException != null) {
    138       Log.e("Download failed.", mException);
    139     }
    140   }
    141 
    142   @Override
    143   protected void onCancelled() {
    144     if (mDialog != null) {
    145       mDialog.setTitle("Download cancelled.");
    146     }
    147   }
    148 
    149   private long download() throws Exception {
    150     URLConnection connection = null;
    151     try {
    152       connection = mUrl.openConnection();
    153     } catch (IOException e) {
    154       throw new Sl4aException("Cannot open URL: " + mUrl, e);
    155     }
    156 
    157     int contentLength = connection.getContentLength();
    158 
    159     if (mFile.exists() && contentLength == mFile.length()) {
    160       Log.v("Output file already exists. Skipping download.");
    161       return 0l;
    162     }
    163 
    164     try {
    165       mProgressReportingOutputStream = new ProgressReportingOutputStream(mFile);
    166     } catch (FileNotFoundException e) {
    167       throw new Sl4aException(e);
    168     }
    169 
    170     publishProgress(0, contentLength);
    171 
    172     int bytesCopied = IoUtils.copy(connection.getInputStream(), mProgressReportingOutputStream);
    173     if (bytesCopied != contentLength && contentLength != -1) {
    174       throw new IOException("Download incomplete: " + bytesCopied + " != " + contentLength);
    175     }
    176     mProgressReportingOutputStream.close();
    177     Log.v("Download completed successfully.");
    178     return bytesCopied;
    179   }
    180 }
    181