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 */ 42 public class UrlDownloaderTask extends AsyncTask<Void, Integer, Long> { 43 44 private final URL mUrl; 45 private final File mFile; 46 private final ProgressDialog mDialog; 47 48 private Throwable mException; 49 private OutputStream mProgressReportingOutputStream; 50 51 private final class ProgressReportingOutputStream extends FileOutputStream { 52 private int mProgress = 0; 53 54 private ProgressReportingOutputStream(File f) throws FileNotFoundException { 55 super(f); 56 } 57 58 @Override 59 public void write(byte[] buffer, int offset, int count) throws IOException { 60 super.write(buffer, offset, count); 61 mProgress += count; 62 publishProgress(mProgress); 63 } 64 } 65 66 public UrlDownloaderTask(String url, String out, Context context) throws MalformedURLException { 67 super(); 68 if (context != null) { 69 mDialog = new ProgressDialog(context); 70 } else { 71 mDialog = null; 72 } 73 mUrl = new URL(url); 74 String fileName = new File(mUrl.getFile()).getName(); 75 mFile = new File(out, fileName); 76 } 77 78 @Override 79 protected void onPreExecute() { 80 Log.v("Downloading " + mUrl); 81 if (mDialog != null) { 82 mDialog.setTitle("Downloading"); 83 mDialog.setMessage(mFile.getName()); 84 // mDialog.setIndeterminate(true); 85 mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 86 mDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { 87 @Override 88 public void onCancel(DialogInterface dialog) { 89 cancel(true); 90 } 91 }); 92 mDialog.show(); 93 } 94 } 95 96 @Override 97 protected Long doInBackground(Void... params) { 98 try { 99 return download(); 100 } catch (Exception e) { 101 if (mFile.exists()) { 102 // Clean up bad downloads. 103 mFile.delete(); 104 } 105 mException = e; 106 return null; 107 } 108 } 109 110 @Override 111 protected void onProgressUpdate(Integer... progress) { 112 if (mDialog == null) { 113 return; 114 } 115 if (progress.length > 1) { 116 int contentLength = progress[1]; 117 if (contentLength == -1) { 118 mDialog.setIndeterminate(true); 119 } else { 120 mDialog.setMax(contentLength); 121 } 122 } else { 123 mDialog.setProgress(progress[0].intValue()); 124 } 125 } 126 127 @Override 128 protected void onPostExecute(Long result) { 129 if (mDialog != null && mDialog.isShowing()) { 130 mDialog.dismiss(); 131 } 132 if (isCancelled()) { 133 return; 134 } 135 if (mException != null) { 136 Log.e("Download failed.", mException); 137 } 138 } 139 140 @Override 141 protected void onCancelled() { 142 if (mDialog != null) { 143 mDialog.setTitle("Download cancelled."); 144 } 145 } 146 147 private long download() throws Exception { 148 URLConnection connection = null; 149 try { 150 connection = mUrl.openConnection(); 151 } catch (IOException e) { 152 throw new Sl4aException("Cannot open URL: " + mUrl, e); 153 } 154 155 int contentLength = connection.getContentLength(); 156 157 if (mFile.exists() && contentLength == mFile.length()) { 158 Log.v("Output file already exists. Skipping download."); 159 return 0l; 160 } 161 162 try { 163 mProgressReportingOutputStream = new ProgressReportingOutputStream(mFile); 164 } catch (FileNotFoundException e) { 165 throw new Sl4aException(e); 166 } 167 168 publishProgress(0, contentLength); 169 170 int bytesCopied = IoUtils.copy(connection.getInputStream(), mProgressReportingOutputStream); 171 if (bytesCopied != contentLength && contentLength != -1) { 172 throw new IOException("Download incomplete: " + bytesCopied + " != " + contentLength); 173 } 174 mProgressReportingOutputStream.close(); 175 Log.v("Download completed successfully."); 176 return bytesCopied; 177 } 178 } 179