diff --git a/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java b/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java index b02cdceb..b9dcb150 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java +++ b/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java @@ -30,6 +30,7 @@ import android.text.TextUtils; import android.util.Log; import android.widget.PopupWindow; import com.arialyy.aria.core.command.CmdFactory; +import com.arialyy.aria.util.CAConfiguration; import com.arialyy.aria.util.CheckUtil; import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.core.command.IDownloadCmd; @@ -48,12 +49,12 @@ import java.util.Set; * Aria管理器,任务操作在这里执行 */ @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public class AriaManager { - private static final String TAG = "AriaManager"; - private static final Object LOCK = new Object(); - private static volatile AriaManager INSTANCE = null; - private Map mTargets = new HashMap<>(); + private static final String TAG = "AriaManager"; + private static final Object LOCK = new Object(); + private static volatile AriaManager INSTANCE = null; + private Map mTargets = new HashMap<>(); private DownloadManager mManager; - private LifeCallback mLifeCallback; + private LifeCallback mLifeCallback; private AriaManager(Context context) { regAppLifeCallback(context); @@ -73,6 +74,24 @@ import java.util.Set; return getTarget(obj); } + /** + * 设置CA证书信息 + * + * @param caAlias ca证书别名 + * @param caPath assets 文件夹下的ca证书完整路径 + */ + public void setCAInfo(String caAlias, String caPath) { + if (TextUtils.isEmpty(caAlias)) { + Log.e(TAG, "ca证书别名不能为null"); + return; + } else if (TextUtils.isEmpty(caPath)) { + Log.e(TAG, "ca证书路径不能为null"); + return; + } + CAConfiguration.CA_ALIAS = caAlias; + CAConfiguration.CA_PATH = caPath; + } + /** * 获取下载列表 */ @@ -100,7 +119,7 @@ import java.util.Set; */ public void stopAllTask() { List allEntity = mManager.getAllDownloadEntity(); - List stopCmds = new ArrayList<>(); + List stopCmds = new ArrayList<>(); for (DownloadEntity entity : allEntity) { if (entity.getState() == DownloadEntity.STATE_DOWNLOAD_ING) { stopCmds.add(CommonUtil.createCmd(entity, CmdFactory.TASK_STOP)); @@ -159,8 +178,8 @@ import java.util.Set; * 删除所有任务 */ public void cancelAllTask() { - List allEntity = mManager.getAllDownloadEntity(); - List cancelCmds = new ArrayList<>(); + List allEntity = mManager.getAllDownloadEntity(); + List cancelCmds = new ArrayList<>(); for (DownloadEntity entity : allEntity) { cancelCmds.add(CommonUtil.createCmd(entity, CmdFactory.TASK_CANCEL)); } @@ -174,9 +193,9 @@ import java.util.Set; } private AMReceiver putTarget(Object obj) { - String clsName = obj.getClass().getName(); - AMReceiver target = null; - String key = ""; + String clsName = obj.getClass().getName(); + AMReceiver target = null; + String key = ""; if (!(obj instanceof Activity)) { if (obj instanceof android.support.v4.app.Fragment) { key = clsName + "_" + ((Fragment) obj).getActivity().getClass().getName(); @@ -249,12 +268,12 @@ import java.util.Set; */ private void handleDialogLift(Dialog dialog) { try { - Field dismissField = CommonUtil.getField(dialog.getClass(), "mDismissMessage"); - Message dismissMsg = (Message) dismissField.get(dialog); + Field dismissField = CommonUtil.getField(dialog.getClass(), "mDismissMessage"); + Message dismissMsg = (Message) dismissField.get(dialog); //如果Dialog已经设置Dismiss事件,则查找cancel事件 if (dismissMsg != null) { - Field cancelField = CommonUtil.getField(dialog.getClass(), "mCancelMessage"); - Message cancelMsg = (Message) cancelField.get(dialog); + Field cancelField = CommonUtil.getField(dialog.getClass(), "mCancelMessage"); + Message cancelMsg = (Message) cancelField.get(dialog); if (cancelMsg != null) { Log.e(TAG, "你已经对Dialog设置了Dismiss和cancel事件。为了防止内存泄露," + "请在dismiss方法中调用Aria.whit(this).removeSchedulerListener();来注销事件"); @@ -316,12 +335,12 @@ import java.util.Set; * onDestroy */ private void destroySchedulerListener(Object obj) { - Set keys = mTargets.keySet(); - String clsName = obj.getClass().getName(); + Set keys = mTargets.keySet(); + String clsName = obj.getClass().getName(); for (Iterator> iter = mTargets.entrySet().iterator(); iter.hasNext(); ) { Map.Entry entry = iter.next(); - String key = entry.getKey(); + String key = entry.getKey(); if (key.equals(clsName) || key.contains(clsName)) { AMReceiver receiver = mTargets.get(key); if (receiver.obj != null) { diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/DownloadTaskQueue.java b/Aria/src/main/java/com/arialyy/aria/core/queue/DownloadTaskQueue.java index 06228179..d4a8f86a 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/queue/DownloadTaskQueue.java +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/DownloadTaskQueue.java @@ -89,21 +89,15 @@ public class DownloadTaskQueue implements ITaskQueue { @Override public void stopTask(Task task) { if (!task.isDownloading()) Log.w(TAG, "停止任务失败,【任务已经停止】"); - task.stop(); - //if (task.isDownloading()) { - // if (mExecutePool.removeTask(task)) { - // task.stop(); - // } - //} else { - // task.stop(); - // Log.w(TAG, "停止任务失败,【任务已经停止】"); - //} + if (mExecutePool.removeTask(task)) { + task.stop(); + } else { + task.stop(); + Log.w(TAG, "停止任务失败,【任务已经停止】"); + } } @Override public void cancelTask(Task task) { - //if (mExecutePool.removeTask(task) || mCachePool.removeTask(task)) { - // task.cancel(); - //} task.cancel(); } @@ -119,10 +113,6 @@ public class DownloadTaskQueue implements ITaskQueue { } } - //@Override public IDownloadSchedulers getDownloadSchedulers() { - // return mSchedulers; - //} - @Override public int size() { return mExecutePool.size(); } @@ -159,12 +149,10 @@ public class DownloadTaskQueue implements ITaskQueue { @Override public Task createTask(String target, DownloadEntity entity) { Task task; if (TextUtils.isEmpty(target)) { - //task = TaskFactory.getInstance().createTask(mContext, entity, mSchedulers); task = TaskFactory.getInstance().createTask(mContext, entity, DownloadSchedulers.getInstance()); } else { task = TaskFactory.getInstance() - //.createTask(target.getClass().getName(), mContext, entity, mSchedulers); .createTask(target, mContext, entity, DownloadSchedulers.getInstance()); } mCachePool.putTask(task); @@ -197,29 +185,15 @@ public class DownloadTaskQueue implements ITaskQueue { return mCachePool.pollTask(); } - //@Override public void setScheduler(IDownloadSchedulers schedulers) { - // mSchedulers = schedulers; - //} - public static class Builder { Context context; - IDownloadSchedulers schedulers; public Builder(Context context) { this.context = context.getApplicationContext(); } - //public Builder setDownloadSchedulers(IDownloadSchedulers schedulers) { - // this.schedulers = schedulers; - // return this; - //} - public DownloadTaskQueue build() { DownloadTaskQueue queue = new DownloadTaskQueue(context); - //if (schedulers == null) { - // schedulers = DownloadSchedulers.getInstance(); - //} - //queue.setScheduler(schedulers); return queue; } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/ITaskQueue.java b/Aria/src/main/java/com/arialyy/aria/core/queue/ITaskQueue.java index 73163766..68576119 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/queue/ITaskQueue.java +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/ITaskQueue.java @@ -73,11 +73,4 @@ public interface ITaskQueue extends IDownloader { * @return 下载任务 or null */ public Task getNextTask(); - - ///** - // * 设置下载调度器 - // * - // * @param schedulers 下载调度器{@link IDownloadSchedulers} - // */ - //public void setScheduler(IDownloadSchedulers schedulers); } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java index 5f5b8a4e..22a7d283 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java @@ -16,6 +16,7 @@ package com.arialyy.aria.core.scheduler; +import android.os.CountDownTimer; import android.os.Message; import android.text.TextUtils; import android.util.Log; @@ -154,10 +155,8 @@ public class DownloadSchedulers implements IDownloadSchedulers { private void callback(int state, Task task, OnSchedulerListener listener) { if (listener != null) { - //Task task = mQueue.getTask(entity); if (task == null) { - //Log.e(TAG, "队列中没有下载链接【" + entity.getDownloadUrl() + "】的任务"); - Log.e(TAG, "传递的下载任务"); + Log.e(TAG, "TASK 为null,回调失败"); return; } switch (state) { @@ -195,9 +194,13 @@ public class DownloadSchedulers implements IDownloadSchedulers { * @param entity 失败实体 */ @Override public void handleFailTask(final DownloadEntity entity) { - new Thread(new Runnable() { - @Override public void run() { - final Configuration config = Configuration.getInstance(); + final Configuration config = Configuration.getInstance(); + CountDownTimer timer = new CountDownTimer(config.getReTryInterval(), 1000) { + @Override public void onTick(long millisUntilFinished) { + + } + + @Override public void onFinish() { if (entity.getFailNum() <= config.getReTryNum()) { Task task = mQueue.getTask(entity); mQueue.reTryStart(task); @@ -210,7 +213,8 @@ public class DownloadSchedulers implements IDownloadSchedulers { startNextTask(entity); } } - }).start(); + }; + timer.start(); } /** diff --git a/Aria/src/main/java/com/arialyy/aria/core/task/DownloadUtil.java b/Aria/src/main/java/com/arialyy/aria/core/task/DownloadUtil.java index c69ee94a..80714b08 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/task/DownloadUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/task/DownloadUtil.java @@ -20,7 +20,9 @@ import android.content.Context; import android.util.Log; import android.util.SparseArray; import com.arialyy.aria.core.DownloadEntity; +import com.arialyy.aria.util.CAConfiguration; import com.arialyy.aria.util.CommonUtil; +import com.arialyy.aria.util.SSLContextUtil; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -29,43 +31,47 @@ import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.ProtocolException; import java.net.URL; +import java.net.URLConnection; import java.util.Properties; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; /** * Created by lyy on 2015/8/25. * 下载工具类 */ final class DownloadUtil implements IDownloadUtil, Runnable { - private static final String TAG = "DownloadUtil"; + private static final String TAG = "DownloadUtil"; private static final Object LOCK = new Object(); /** * 线程数 */ - private final int THREAD_NUM; + private final int THREAD_NUM; //下载监听 - private IDownloadListener mListener; - private int mConnectTimeOut = 5000 * 4; //连接超时时间 - private int mReadTimeOut = 5000 * 20; //流读取的超时时间 + private IDownloadListener mListener; + private int mConnectTimeOut = 5000 * 4; //连接超时时间 + private int mReadTimeOut = 5000 * 20; //流读取的超时时间 /** * 已经完成下载任务的线程数量 */ - private boolean isDownloading = false; - private boolean isStop = false; - private boolean isCancel = false; - private boolean isNewTask = true; + private boolean isDownloading = false; + private boolean isStop = false; + private boolean isCancel = false; + private boolean isNewTask = true; private boolean isSupportBreakpoint = true; - private int mCompleteThreadNum = 0; - private int mCancelNum = 0; - private long mCurrentLocation = 0; - private int mStopNum = 0; - private int mFailNum = 0; - private Context mContext; - private DownloadEntity mDownloadEntity; + private int mCompleteThreadNum = 0; + private int mCancelNum = 0; + private long mCurrentLocation = 0; + private int mStopNum = 0; + private int mFailNum = 0; + private Context mContext; + private DownloadEntity mDownloadEntity; private ExecutorService mFixedThreadPool; - private File mDownloadFile; //下载的文件 - private File mConfigFile;//下载信息配置文件 + private File mDownloadFile; //下载的文件 + private File mConfigFile;//下载信息配置文件 private SparseArray mTask = new SparseArray<>(); DownloadUtil(Context context, DownloadEntity entity, IDownloadListener downloadListener) { @@ -222,8 +228,8 @@ final class DownloadUtil implements IDownloadUtil, Runnable { @Override public void run() { try { - URL url = new URL(mDownloadEntity.getDownloadUrl()); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + URL url = new URL(mDownloadEntity.getDownloadUrl()); + HttpURLConnection conn = handleConnection(url); setConnectParam(conn); conn.setRequestProperty("Range", "bytes=" + 0 + "-"); conn.setConnectTimeout(mConnectTimeOut * 4); @@ -242,12 +248,16 @@ final class DownloadUtil implements IDownloadUtil, Runnable { handleBreakpoint(conn); } else if (code == HttpURLConnection.HTTP_OK || len < 0) { //在conn.setRequestProperty("Range", "bytes=" + 0 + "-");下,200为不支持断点状态 + if (len < 0) { + failDownload("任务【" + mDownloadEntity.getDownloadUrl() + "】下载失败,文件长度小于0"); + return; + } isSupportBreakpoint = false; mListener.supportBreakpoint(false); Log.w(TAG, "该下载链接不支持断点下载"); handleBreakpoint(conn); } else { - failDownload("下载失败,返回码:" + code); + failDownload("任务【" + mDownloadEntity.getDownloadUrl() + "】下载失败,返回码:" + code); } } catch (IOException e) { failDownload("下载失败【downloadUrl:" @@ -259,6 +269,30 @@ final class DownloadUtil implements IDownloadUtil, Runnable { } } + /** + * 处理链接 + * + * @throws IOException + */ + private HttpURLConnection handleConnection(URL url) throws IOException { + HttpURLConnection conn; + URLConnection urlConn = url.openConnection(); + if (urlConn instanceof HttpsURLConnection) { + conn = (HttpsURLConnection) urlConn; + SSLContext sslContext = + SSLContextUtil.getSSLContext(CAConfiguration.CA_ALIAS, CAConfiguration.CA_ALIAS); + if (sslContext == null) { + sslContext = SSLContextUtil.getDefaultSLLContext(); + } + SSLSocketFactory ssf = sslContext.getSocketFactory(); + ((HttpsURLConnection) conn).setSSLSocketFactory(ssf); + ((HttpsURLConnection) conn).setHostnameVerifier(SSLContextUtil.HOSTNAME_VERIFIER); + } else { + conn = (HttpURLConnection) urlConn; + } + return conn; + } + /** * 处理断点 */ @@ -301,15 +335,15 @@ final class DownloadUtil implements IDownloadUtil, Runnable { } } } - int blockSize = fileLength / THREAD_NUM; - int[] recordL = new int[THREAD_NUM]; - int rl = 0; + int blockSize = fileLength / THREAD_NUM; + int[] recordL = new int[THREAD_NUM]; + int rl = 0; for (int i = 0; i < THREAD_NUM; i++) { recordL[i] = -1; } for (int i = 0; i < THREAD_NUM; i++) { - long startL = i * blockSize, endL = (i + 1) * blockSize; - Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i); + long startL = i * blockSize, endL = (i + 1) * blockSize; + Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i); if (state != null && Integer.parseInt(state + "") == 1) { //该线程已经完成 mCurrentLocation += endL - startL; Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++"); @@ -377,12 +411,12 @@ final class DownloadUtil implements IDownloadUtil, Runnable { */ private static class ConfigEntity { //文件大小 - long fileSize; - String downloadUrl; - int threadId; - long startLocation; - long endLocation; - File tempFile; + long fileSize; + String downloadUrl; + int threadId; + long startLocation; + long endLocation; + File tempFile; } /** @@ -391,7 +425,7 @@ final class DownloadUtil implements IDownloadUtil, Runnable { private class SingleThreadTask implements Runnable { private static final String TAG = "SingleThreadTask"; private ConfigEntity configEntity; - private String configFPath; + private String configFPath; private long currentLocation = 0; private SingleThreadTask(ConfigEntity downloadInfo) { @@ -406,10 +440,11 @@ final class DownloadUtil implements IDownloadUtil, Runnable { @Override public void run() { HttpURLConnection conn = null; - InputStream is = null; + InputStream is = null; try { URL url = new URL(configEntity.downloadUrl); - conn = (HttpURLConnection) url.openConnection(); + //conn = (HttpURLConnection) url.openConnection(); + conn = handleConnection(url); if (isSupportBreakpoint) { Log.d(TAG, "线程_" + configEntity.threadId @@ -433,7 +468,7 @@ final class DownloadUtil implements IDownloadUtil, Runnable { //设置每条线程写入文件的位置 file.seek(configEntity.startLocation); byte[] buffer = new byte[1024]; - int len; + int len; //当前子线程的下载位置 currentLocation = configEntity.startLocation; while ((len = is.read(buffer)) != -1) { @@ -593,8 +628,8 @@ final class DownloadUtil implements IDownloadUtil, Runnable { * 将记录写入到配置文件 */ private void writeConfig(String key, String record) throws IOException { - File configFile = new File(configFPath); - Properties pro = CommonUtil.loadConfig(configFile); + File configFile = new File(configFPath); + Properties pro = CommonUtil.loadConfig(configFile); pro.setProperty(key, record); CommonUtil.saveConfig(configFile, pro); } diff --git a/Aria/src/main/java/com/arialyy/aria/orm/DbUtil.java b/Aria/src/main/java/com/arialyy/aria/orm/DbUtil.java index 4f6fe2b1..10b64600 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/DbUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/DbUtil.java @@ -113,7 +113,6 @@ public class DbUtil { params[i] = "'" + expression[i + 1] + "'"; } sql = String.format(sql, params); - Log.d(TAG, sql); print(DEL_DATA, sql); mDb.execSQL(sql); close(); @@ -185,7 +184,6 @@ public class DbUtil { params[i] = "'" + expression[i + 1] + "'"; } sql = String.format(sql, params); - Log.d(TAG, sql); print(FIND_DATA, sql); Cursor cursor = mDb.rawQuery(sql, null); return cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null; diff --git a/Aria/src/main/java/com/arialyy/aria/util/CAConfiguration.java b/Aria/src/main/java/com/arialyy/aria/util/CAConfiguration.java new file mode 100644 index 00000000..ac755396 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/util/CAConfiguration.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.arialyy.aria.util; + +/** + * Created by Aria.Lao on 2017/1/11. + */ + +public class CAConfiguration { + public static String CA_PATH, CA_ALIAS; +} diff --git a/Aria/src/main/java/com/arialyy/aria/util/SSLContextUtil.java b/Aria/src/main/java/com/arialyy/aria/util/SSLContextUtil.java new file mode 100644 index 00000000..6ab8f3dc --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/util/SSLContextUtil.java @@ -0,0 +1,112 @@ +package com.arialyy.aria.util; + +import com.arialyy.aria.core.DownloadManager; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +/** + * Created by Aria.Lao on 2017/1/11. + */ + +public class SSLContextUtil { + + /** + * 颁发服务器证书的 CA 未知 + * + * @param caAlias CA证书别名 + * @param caPath 保存在assets目录下的CA证书完整路径 + */ + public static SSLContext getSSLContext(String caAlias, String caPath) { + // Load CAs from an InputStream + // (could be from a resource or ByteArrayInputStream or ...) + CertificateFactory cf = null; + try { + cf = CertificateFactory.getInstance("X.509"); + InputStream caInput = DownloadManager.APP.getAssets().open(caPath); + Certificate ca; + ca = cf.generateCertificate(caInput); + System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN()); + + // Create a KeyStore containing our trusted CAs + String keyStoreType = KeyStore.getDefaultType(); + KeyStore keyStore = KeyStore.getInstance(keyStoreType); + keyStore.load(null, null); + keyStore.setCertificateEntry(caAlias, ca); + + // Create a TrustManager that trusts the CAs in our KeyStore + String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); + tmf.init(keyStore); + KeyManagerFactory kmf = + KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(keyStore, null); + + // Create an SSLContext that uses our TrustManager + SSLContext context = SSLContext.getInstance("TLS"); + context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom()); + return context; + } catch (CertificateException | NoSuchAlgorithmException | IOException | KeyStoreException | KeyManagementException | UnrecoverableKeyException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 服务器证书不是由 CA 签署的,而是自签署时,获取默认的SSL + */ + public static SSLContext getDefaultSLLContext() { + SSLContext sslContext = null; + try { + sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, new TrustManager[] { trustManagers }, new SecureRandom()); + } catch (Exception e) { + e.printStackTrace(); + } + return sslContext; + } + + /** + * 创建自己的 TrustManager,这次直接信任服务器证书。这种方法具有前面所述的将应用与证书直接关联的所有弊端,但可以安全地操作。 + */ + private static TrustManager trustManagers = new X509TrustManager() { + + @Override public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + } + + @Override public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + + } + + @Override public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + }; + + public static final HostnameVerifier HOSTNAME_VERIFIER = new HostnameVerifier() { + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; +} diff --git a/README.md b/README.md index c63f85e8..022aec0a 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ - 支持多线程、多任务下载 - 支持任务自动切换 - 支持下载速度直接获取 + - 支持https地址下载 [Aria怎样使用?](#使用) @@ -16,11 +17,9 @@ ## 下载 [![Download](https://api.bintray.com/packages/arialyy/maven/Aria/images/download.svg)](https://bintray.com/arialyy/maven/Aria/_latestVersion)
```java -compile 'com.arialyy.aria:Aria:2.3.8' +compile 'com.arialyy.aria:Aria:2.3.9' ``` - - ## 示例 ![多任务下载](https://github.com/AriaLyy/DownloadUtil/blob/v_2.0/img/download_img.gif) ![Dialog使用](https://github.com/AriaLyy/DownloadUtil/blob/v_2.0/img/dialog_use.gif "") @@ -52,6 +51,7 @@ compile 'com.arialyy.aria:Aria:2.3.8' } ``` ### 四、通过下载链接,你还能使用Aria执行很多操作,如: +Aria支持https下载,如果你希望使用自己的ca证书,那么你需要进行[Aria https证书配置](#https证书配置) - 添加任务(不进行下载) ```java @@ -118,8 +118,22 @@ compile 'com.arialyy.aria:Aria:2.3.8' Aria.get(this).openBroadcast(true); ``` +### https证书配置 + + 将你的证书导入`assets`目录 + + 调用以下代码配置ca证书相关信息 + ```java + /** + * 设置CA证书信息 + * + * @param caAlias ca证书别名 + * @param caPath assets 文件夹下的ca证书完整路径 + */ + Aria.get(this).setCAInfo("caAlias","caPath"); + ``` + *** ## 开发日志 + + v_2.3.9 支持https链接下载 + v_2.3.8 修复数据错乱的bug、添加fragment支持 + v_2.3.6 添加dialog、popupWindow支持 + v_2.3.3 @@ -128,7 +142,6 @@ compile 'com.arialyy.aria:Aria:2.3.8' - 修复一个内存泄露的bug + v_2.3.1 重命名为Aria,下载流程简化 + v_2.1.1 增加,选择最大下载任务数接口 - + v_2.1.0 修复大量bug License ------- diff --git a/app/src/main/java/com/arialyy/simple/single_task/SingleTaskActivity.java b/app/src/main/java/com/arialyy/simple/single_task/SingleTaskActivity.java index b66ae0b4..04639b8b 100644 --- a/app/src/main/java/com/arialyy/simple/single_task/SingleTaskActivity.java +++ b/app/src/main/java/com/arialyy/simple/single_task/SingleTaskActivity.java @@ -49,10 +49,10 @@ public class SingleTaskActivity extends BaseActivity { public static final int DOWNLOAD_RESUME = 0x05; public static final int DOWNLOAD_COMPLETE = 0x06; public static final int DOWNLOAD_RUNNING = 0x07; + private static final String DOWNLOAD_URL = - "http://static.gaoshouyou.com/d/3a/93/573ae1db9493a801c24bf66128b11e39.apk"; - //private static final String DOWNLOAD_URL = - // "http://www.yangqiang.im/wp-content/uploads/2016/10/%E6%8A%BD%E8%B1%A1%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F.png"; + //"http://kotlinlang.org/docs/kotlin-docs.pdf"; + "https://atom-installer.github.com/v1.13.0/AtomSetup.exe?s=1484074138&ext=.exe"; @Bind(R.id.progressBar) HorizontalProgressBarWithNumber mPb; @Bind(R.id.start) Button mStart; @Bind(R.id.stop) Button mStop; @@ -114,6 +114,7 @@ public class SingleTaskActivity extends BaseActivity { setBtState(false); break; case DOWNLOAD_COMPLETE: + mPb.setProgress(100); Toast.makeText(SingleTaskActivity.this, "下载完成", Toast.LENGTH_SHORT).show(); mStart.setText("重新开始?"); mCancel.setEnabled(false);