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