创建一个DownloadUtils类继承AsyncTask,并实现doInBackground()、onProgressUpdate()、onPostExecute()方法
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class DownloadUtils extends AsyncTask<String, Integer, Integer> { @Override protected Integer doInBackground(String... strings) { }
@Override protected void onProgressUpdate(Integer... values) { }
@Override protected void onPostExecute(Integer integer) { } }
|
添加一个接口类,用于下载回调
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class DownloadUtils extends AsyncTask<String, Integer, Integer> { public interface DownloadListener { void onProgress(int progress);
void onSuccess(File downloadCacheFile);
void onFailed();
void onPaused();
void onCanceled(); } }
|
使用该类创建对象时,要求传入下载回调接口
1 2 3 4 5 6 7
| public class DownloadUtils extends AsyncTask<String, Integer, Integer> { private final DownloadListener downloadListener;
public DownloadUtils(DownloadListener downloadListener) { this.downloadListener = downloadListener; } }
|
注意执行下载任务时一定要在传入的数组中添加三个顺序固定的参数,方法中发起请求时,在请求头中添加了RANGE参数,该参数用作指定下载区间,重启断点续传;使用RandomAccessFile类写入数据,可以指定从目标文件的哪个位置开始插入数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
| public class DownloadUtils extends AsyncTask<String, Integer, Integer> {
@Override protected Integer doInBackground(String... strings) { String downloadUrl = strings[0]; String folderPath = strings[1]; String fileName = strings[2];
if (downloadUrl == null || TextUtils.isEmpty(downloadUrl)) return null; if (folderPath == null || TextUtils.isEmpty(folderPath)) folderPath = Environment.getExternalStorageDirectory().getAbsolutePath(); if (fileName == null || TextUtils.isEmpty(fileName)) fileName = getDownloadFileName(downloadUrl);
String downloadFilePath = folderPath + "/" + fileName; downloadFile = new File(downloadFilePath);
String downloadCacheFilePath = folderPath + "/" + fileName + "_cache"; downloadCacheFile = new File(downloadCacheFilePath);
long downloadCacheFileLength = 0; if (downloadCacheFile.exists() && downloadCacheFile.isFile()) { downloadCacheFileLength = downloadCacheFile.length(); }
long downloadFileLength = getDownloadFileLength(downloadUrl); if (downloadFileLength == 0) { return TYPE_FAILED; } else if (downloadFileLength == downloadCacheFileLength) { return TYPE_SUCCESS; }
OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder() .addHeader("RANGE", "bytes=" + downloadCacheFileLength + "-") .url(downloadUrl) .build();
try { Response execute = okHttpClient.newCall(request).execute(); ResponseBody body = execute.body(); if (execute.isSuccessful() && body != null) { InputStream inputStream = body.byteStream(); RandomAccessFile randomAccessFile = new RandomAccessFile(downloadCacheFile, "rw"); randomAccessFile.seek(downloadCacheFileLength); byte[] bytes = new byte[1024]; int total = 0; int len; while ((len = inputStream.read(bytes)) != -1) { if (isCanceled) { return TYPE_CANCELED; } else if (isPaused) { return TYPE_PAUSED; } else { total += len; randomAccessFile.write(bytes, 0, len); int progressValue = (int) ((total + downloadCacheFileLength) * 100 / downloadFileLength); publishProgress(progressValue); } } body.close(); return TYPE_SUCCESS; } } catch (IOException e) { e.printStackTrace(); } return TYPE_FAILED; }
private long getDownloadFileLength(String url){ OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder().url(url).build(); long length = 0; try { Response execute = okHttpClient.newCall(request).execute(); ResponseBody body = execute.body(); if (execute.isSuccessful() && body != null){ length = body.contentLength(); body.close(); } } catch (IOException e) { e.printStackTrace(); } return length; }
private String getDownloadFileName(String url){ int lastIndexOf = url.lastIndexOf("/"); return url.substring(lastIndexOf); } }
|
更新下载进度
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
@Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); int progress = values[0]; if (progress > lastProgress) { downloadListener.onProgress(progress); lastProgress = progress; } }
|
回调传入的接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
@Override protected void onPostExecute(Integer integer) { super.onPostExecute(integer); switch (integer) { case TYPE_SUCCESS: removeFile(); downloadListener.onSuccess(downloadFile); break; case TYPE_FAILED: downloadListener.onFailed(); break; case TYPE_PAUSED: downloadListener.onPaused(); break; case TYPE_CANCELED: deleteCache(); downloadListener.onCanceled(); break; default: break; } }
private void deleteCache() { downloadCacheFile.delete(); }
private void removeFile() { if (downloadFile.exists() && downloadFile.isFile()) { downloadFile.delete(); } downloadCacheFile.renameTo(downloadFile); }
|
调用时
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| new DownloadUtils(new DownloadUtils.DownloadListener() { @Override public void onProgress(int progress) { }
@Override public void onSuccess(File downloadCacheFile) { }
@Override public void onFailed() { }
@Override public void onPaused() { }
@Override public void onCanceled() { } }).execute(url, folderPath, fileName);
|
整体来看一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
|
public class DownloadUtils extends AsyncTask<String, Integer, Integer> { private static final int TYPE_SUCCESS = 0; private static final int TYPE_FAILED = 1; private static final int TYPE_PAUSED = 2; private static final int TYPE_CANCELED = 3;
private boolean isPaused = false; private boolean isCanceled = false;
private int lastProgress;
private File downloadCacheFile; private File downloadFile;
private final DownloadListener downloadListener;
public DownloadUtils(DownloadListener downloadListener) { this.downloadListener = downloadListener; }
@Override protected Integer doInBackground(String... strings) { String downloadUrl = strings[0]; String folderPath = strings[1]; String fileName = strings[2];
if (downloadUrl == null || TextUtils.isEmpty(downloadUrl)) return null; if (folderPath == null || TextUtils.isEmpty(folderPath)) folderPath = Environment.getExternalStorageDirectory().getAbsolutePath(); if (fileName == null || TextUtils.isEmpty(fileName)) fileName = getDownloadFileName(downloadUrl);
String downloadFilePath = folderPath + "/" + fileName; downloadFile = new File(downloadFilePath);
String downloadCacheFilePath = folderPath + "/" + fileName + "_cache"; downloadCacheFile = new File(downloadCacheFilePath);
long downloadCacheFileLength = 0; if (downloadCacheFile.exists() && downloadCacheFile.isFile()) { downloadCacheFileLength = downloadCacheFile.length(); }
long downloadFileLength = getDownloadFileLength(downloadUrl); if (downloadFileLength == 0) { return TYPE_FAILED; } else if (downloadFileLength == downloadCacheFileLength) { return TYPE_SUCCESS; }
OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder() .addHeader("RANGE", "bytes=" + downloadCacheFileLength + "-") .url(downloadUrl) .build();
try { Response execute = okHttpClient.newCall(request).execute(); ResponseBody body = execute.body(); if (execute.isSuccessful() && body != null) { InputStream inputStream = body.byteStream(); RandomAccessFile randomAccessFile = new RandomAccessFile(downloadCacheFile, "rw"); randomAccessFile.seek(downloadCacheFileLength); byte[] bytes = new byte[1024]; int total = 0; int len; while ((len = inputStream.read(bytes)) != -1) { if (isCanceled) { return TYPE_CANCELED; } else if (isPaused) { return TYPE_PAUSED; } else { total += len; randomAccessFile.write(bytes, 0, len); int progressValue = (int) ((total + downloadCacheFileLength) * 100 / downloadFileLength); publishProgress(progressValue); } } body.close(); return TYPE_SUCCESS; } } catch (IOException e) { e.printStackTrace(); } return TYPE_FAILED; }
private long getDownloadFileLength(String url){ OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder().url(url).build(); long length = 0; try { Response execute = okHttpClient.newCall(request).execute(); ResponseBody body = execute.body(); if (execute.isSuccessful() && body != null){ length = body.contentLength(); body.close(); } } catch (IOException e) { e.printStackTrace(); } return length; }
private String getDownloadFileName(String url){ int lastIndexOf = url.lastIndexOf("/"); return url.substring(lastIndexOf); }
@Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); int progress = values[0]; if (progress > lastProgress) { downloadListener.onProgress(progress); lastProgress = progress; } }
@Override protected void onPostExecute(Integer integer) { super.onPostExecute(integer); switch (integer) { case TYPE_SUCCESS: removeFile(); downloadListener.onSuccess(downloadFile); break; case TYPE_FAILED: downloadListener.onFailed(); break; case TYPE_PAUSED: downloadListener.onPaused(); break; case TYPE_CANCELED: deleteCache(); downloadListener.onCanceled(); break; default: break; } }
private void deleteCache() { downloadCacheFile.delete(); }
private void removeFile() { if (downloadFile.exists() && downloadFile.isFile()) { downloadFile.delete(); } downloadCacheFile.renameTo(downloadFile); }
public void pauseDownload() { this.isPaused = true; }
public void cancelDownload() { this.isCanceled = true; }
public interface DownloadListener { void onProgress(int progress);
void onSuccess(File downloadCacheFile);
void onFailed();
void onPaused();
void onCanceled(); } }
|