diff --git a/.idea/caches/gradle_models.ser b/.idea/caches/gradle_models.ser deleted file mode 100644 index 9e15848a1..000000000 Binary files a/.idea/caches/gradle_models.ser and /dev/null differ diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index ae78c113f..681f41ae2 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -1,6 +1,9 @@ + +
diff --git a/.idea/misc.xml b/.idea/misc.xml index 10b5291fa..317a96c49 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,48 +1,4 @@ - - - - - - - - - + \ No newline at end of file diff --git a/android-sdk.iml b/android-sdk.iml index ad4065b84..74149ab95 100644 --- a/android-sdk.iml +++ b/android-sdk.iml @@ -13,7 +13,7 @@ - + \ No newline at end of file diff --git a/build.gradle b/build.gradle index e8e190f32..e7ae1bf48 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,6 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:3.5.2' - // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/library/src/main/java/com/qiniu/android/common/Constants.java b/library/src/main/java/com/qiniu/android/common/Constants.java index 810ce638a..7345431e1 100644 --- a/library/src/main/java/com/qiniu/android/common/Constants.java +++ b/library/src/main/java/com/qiniu/android/common/Constants.java @@ -2,7 +2,7 @@ public final class Constants { - public static final String VERSION = "7.5.0"; + public static final String VERSION = "7.5.1"; public static final String UTF_8 = "utf-8"; } diff --git a/library/src/main/java/com/qiniu/android/http/DnsPrefetcher.java b/library/src/main/java/com/qiniu/android/http/DnsPrefetcher.java index fe27293a6..34b8f72fb 100644 --- a/library/src/main/java/com/qiniu/android/http/DnsPrefetcher.java +++ b/library/src/main/java/com/qiniu/android/http/DnsPrefetcher.java @@ -23,6 +23,7 @@ import java.util.Iterator; import java.util.List; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; /** *

@@ -33,9 +34,11 @@ public class DnsPrefetcher { public static DnsPrefetcher dnsPrefetcher = null; private static String token; + private static Configuration config; private static ConcurrentHashMap> mConcurrentHashMap = new ConcurrentHashMap>(); private static List mHosts = new ArrayList(); + private static AtomicReference mDnsCacheKey = new AtomicReference(); private DnsPrefetcher() { @@ -52,10 +55,33 @@ public static DnsPrefetcher getDnsPrefetcher() { return dnsPrefetcher; } - public DnsPrefetcher init(String token) throws UnknownHostException { + /** + * 不用判断是否预取,每次调用UploadManager都直接预取一次。 + * uploadManager只会new一次,但是uploadManager.put方法有多次,如果期间网络发生变化 + * 这个方法预取的结果应该被ConcurrentHashMap自动覆盖 + */ + public void localFetch() { + List localHosts = new ArrayList(); + //local + List listZoneinfo = getLocalZone(); + for (ZoneInfo zone : listZoneinfo) { + for (String host : zone.upDomainsList) { + localHosts.add(host); + } + } + localHosts.add(Config.preQueryHost); + + if (localHosts != null && localHosts.size() > 0) + preFetch(localHosts); + } + + + public DnsPrefetcher init(String token, Configuration config) throws UnknownHostException { this.token = token; - preHosts(); - preFetch(); + this.config = config; + List preHosts = preHosts(); + if (preHosts != null && preHosts.size() > 0) + preFetch(preHosts); return this; } @@ -86,43 +112,47 @@ public List getInetAddressByHost(String host) { return mConcurrentHashMap.get(host); } - private void preHosts() { + private List preHosts() { HashSet set = new HashSet(); - + List preHosts = new ArrayList<>(); //preQuery sync ZoneInfo zoneInfo = getPreQueryZone(); if (zoneInfo != null) { for (String host : zoneInfo.upDomainsList) { if (set.add(host)) - mHosts.add(host); + preHosts.add(host); } } + //local List listZoneinfo = getLocalZone(); for (ZoneInfo zone : listZoneinfo) { for (String host : zone.upDomainsList) { if (set.add(host)) - mHosts.add(host); + preHosts.add(host); } } if (set.add(Config.preQueryHost)) - mHosts.add(Config.preQueryHost); + preHosts.add(Config.preQueryHost); + return preHosts; } - private void preFetch() { + private void preFetch(List fetchHost) { List rePreHosts = new ArrayList(); - for (String host : mHosts) { + for (String host : fetchHost) { List inetAddresses = null; try { inetAddresses = okhttp3.Dns.SYSTEM.lookup(host); mConcurrentHashMap.put(host, inetAddresses); + mHosts.add(host); } catch (UnknownHostException e) { e.printStackTrace(); rePreHosts.add(host); } } - rePreFetch(rePreHosts, null); + if (rePreHosts.size() > 0) + rePreFetch(rePreHosts, null); } /** @@ -151,6 +181,7 @@ private boolean rePreFetch(String host, Dns customeDns) { inetAddresses = customeDns.lookup(host); } mConcurrentHashMap.put(host, inetAddresses); + mHosts.add(host); return true; } catch (UnknownHostException e) { e.printStackTrace(); @@ -214,7 +245,11 @@ ZoneInfo preQueryIndex(DnsPrefetcher.ZoneIndex index) { ResponseInfo getZoneJsonSync(DnsPrefetcher.ZoneIndex index) { Client client = new Client(); - String address = "http://" + Config.preQueryHost + "/v2/query?ak=" + index.accessKey + "&bucket=" + index.bucket; + String schema = "https://"; + if (!config.useHttps) { + schema = "http://"; + } + String address = schema + Config.preQueryHost + "/v2/query?ak=" + index.accessKey + "&bucket=" + index.bucket; return client.syncGet(address, null); } @@ -264,6 +299,33 @@ public boolean equals(Object obj) { * @return true:重新预期并缓存, false:不需要重新预取和缓存 */ public static boolean checkRePrefetchDns(String token, Configuration config) { + if (mDnsCacheKey.get() == null) + return true; + + String currentTime = String.valueOf(System.currentTimeMillis()); + String localip = AndroidNetwork.getHostIP(); + String akScope = StringUtils.getAkAndScope(token); + + if (currentTime == null || localip == null || akScope == null) + return true; + DnsCacheKey dnsCacheKey = (DnsCacheKey) mDnsCacheKey.get(); + if (dnsCacheKey == null || dnsCacheKey.getCurrentTime() == null) + return true; + long cacheTime = (Long.parseLong(currentTime) - Long.parseLong(dnsCacheKey.getCurrentTime())) / 1000; + if (!localip.equals(dnsCacheKey.getLocalIp()) || cacheTime > config.dnsCacheTimeMs || !akScope.equals(dnsCacheKey.getAkScope())) { + return true; + } + + return false; + } + + /** + * uploadManager初始化时,加载本地缓存到内存 + * + * @param config + * @return 如果不存在缓存返回true,需要重新预取;如果存在且满足使用,返回false + */ + public static boolean recoverCache(Configuration config) { Recorder recorder = null; try { recorder = new DnsCacheFile(Config.dnscacheDir); @@ -285,15 +347,14 @@ public static boolean checkRePrefetchDns(String token, Configuration config) { String currentTime = String.valueOf(System.currentTimeMillis()); String localip = AndroidNetwork.getHostIP(); - String akScope = StringUtils.getAkAndScope(token); - if (currentTime == null || localip == null || akScope == null) + if (currentTime == null || localip == null) return true; long cacheTime = (Long.parseLong(currentTime) - Long.parseLong(cacheKey.getCurrentTime())) / 1000; - if (!cacheKey.getLocalIp().equals(localip) || cacheTime > config.dnsCacheTimeMs || !cacheKey.getAkScope().equals(akScope)) { + if (!cacheKey.getLocalIp().equals(localip) || cacheTime > config.dnsCacheTimeMs) { return true; } - + mDnsCacheKey.set(cacheKey); return recoverDnsCache(data); } @@ -308,12 +369,16 @@ public static void startPrefetchDns(String token, Configuration config) { String akScope = StringUtils.getAkAndScope(token); if (currentTime == null || localip == null || akScope == null) return; - String cacheKey = new DnsCacheKey(currentTime, localip, akScope).toString(); + DnsCacheKey dnsCacheKey = new DnsCacheKey(currentTime, localip, akScope); + String cacheKey = dnsCacheKey.toString(); + Recorder recorder = null; DnsPrefetcher dnsPrefetcher = null; try { recorder = new DnsCacheFile(Config.dnscacheDir); - dnsPrefetcher = DnsPrefetcher.getDnsPrefetcher().init(token); + dnsPrefetcher = DnsPrefetcher.getDnsPrefetcher().init(token, config); + //确认预取结束后,需要更新缓存mDnsCacheKey + mDnsCacheKey.set(dnsCacheKey); } catch (IOException e) { e.printStackTrace(); return; diff --git a/library/src/main/java/com/qiniu/android/storage/UploadManager.java b/library/src/main/java/com/qiniu/android/storage/UploadManager.java index 78b6f0da9..d4f122821 100644 --- a/library/src/main/java/com/qiniu/android/storage/UploadManager.java +++ b/library/src/main/java/com/qiniu/android/storage/UploadManager.java @@ -28,7 +28,7 @@ public final class UploadManager { /** * 保证代码只执行一次,防止多个uploadManager同时开始预取dns */ - static AtomicBoolean atomicStruct = new AtomicBoolean(false); + static AtomicBoolean atomicLocalPrefetch = new AtomicBoolean(false); /** * default 3 Threads @@ -44,6 +44,7 @@ public UploadManager(Configuration config) { this.config = config; this.client = new Client(config.proxy, config.connectTimeout, config.responseTimeout, config.urlConverter, config.dns); + startLocalPrefetch(config); } public UploadManager(Configuration config, int multitread) { @@ -51,6 +52,7 @@ public UploadManager(Configuration config, int multitread) { this.multithreads = multitread >= 1 ? multitread : DEF_THREAD_NUM; this.client = new Client(config.proxy, config.connectTimeout, config.responseTimeout, config.urlConverter, config.dns); + startLocalPrefetch(config); } public UploadManager(Recorder recorder) { @@ -69,6 +71,20 @@ public UploadManager(Recorder recorder, KeyGenerator keyGen, int multitread) { this(new Configuration.Builder().recorder(recorder, keyGen).build(), multitread); } + //初始化一个UploadManager只允许执行一次,开启一个线程,对sdk内置host进行预取 + private void startLocalPrefetch(final Configuration config) { + if (atomicLocalPrefetch.compareAndSet(false, true)) { + if (DnsPrefetcher.recoverCache(config)) { + new Thread(new Runnable() { + @Override + public void run() { + DnsPrefetcher.getDnsPrefetcher().localFetch(); + } + }).start(); + } + } + } + private static boolean areInvalidArg(final String key, byte[] data, File f, String token, UpToken decodedToken, final UpCompletionHandler complete) { if (complete == null) { @@ -98,7 +114,8 @@ private static boolean areInvalidArg(final String key, byte[] data, File f, Stri return false; } - private static ResponseInfo areInvalidArg(final String key, byte[] data, File f, String token, + private static ResponseInfo areInvalidArg(final String key, byte[] data, File f, String + token, UpToken decodedToken) { String message = null; if (f == null && data == null) { @@ -141,17 +158,16 @@ public void put(final byte[] data, final String key, final String token, if (areInvalidArg(key, data, null, token, decodedToken, complete)) { return; } - - if (atomicStruct.compareAndSet(false, true)) { - if (DnsPrefetcher.checkRePrefetchDns(token, config)) { - new Thread(new Runnable() { - @Override - public void run() { - DnsPrefetcher.startPrefetchDns(token, config); - } - }).start(); - } + //此处是对uc.qbox.me接口获取的域名进行预取 + if (DnsPrefetcher.checkRePrefetchDns(token, config)) { + new Thread(new Runnable() { + @Override + public void run() { + DnsPrefetcher.startPrefetchDns(token, config); + } + }).start(); } + Zone z = config.zone; z.preQuery(token, new Zone.QueryHandler() { @Override @@ -179,7 +195,8 @@ public void onFailure(int reason) { * @param completionHandler 上传完成的后续处理动作 * @param options 上传数据的可选参数 */ - public void put(String filePath, String key, String token, UpCompletionHandler completionHandler, + public void put(String filePath, String key, String token, UpCompletionHandler + completionHandler, final UploadOptions options) { put(new File(filePath), key, token, completionHandler, options); } @@ -194,23 +211,23 @@ public void put(String filePath, String key, String token, UpCompletionHandler c * @param complete 上传完成的后续处理动作 * @param options 上传数据的可选参数 */ - public void put(final File file, final String key, final String token, final UpCompletionHandler complete, + public void put(final File file, final String key, final String token, + final UpCompletionHandler complete, final UploadOptions options) { final UpToken decodedToken = UpToken.parse(token); if (areInvalidArg(key, null, file, token, decodedToken, complete)) { return; } - - if (atomicStruct.compareAndSet(false, true)) { - if (DnsPrefetcher.checkRePrefetchDns(token, config)) { - new Thread(new Runnable() { - @Override - public void run() { - DnsPrefetcher.startPrefetchDns(token, config); - } - }).start(); - } + //此处是每次上传时判断,对uc.qbox.me接口获取的host+sdk内置的host进行预取(去重) + if (DnsPrefetcher.checkRePrefetchDns(token, config)) { + new Thread(new Runnable() { + @Override + public void run() { + DnsPrefetcher.startPrefetchDns(token, config); + } + }).start(); } + Zone z = config.zone; z.preQuery(token, new Zone.QueryHandler() { @Override diff --git a/library/src/main/java/com/qiniu/android/storage/UploadOptions.java b/library/src/main/java/com/qiniu/android/storage/UploadOptions.java index 7550467ab..92b1f6d6f 100644 --- a/library/src/main/java/com/qiniu/android/storage/UploadOptions.java +++ b/library/src/main/java/com/qiniu/android/storage/UploadOptions.java @@ -15,6 +15,7 @@ public final class UploadOptions { /** * 扩展参数,以x:开头的用户自定义参数 + * 可添加网络检测次数:netCheckTime,int类型,默认600,每增加1,检测时间增加500ms */ final Map params; @@ -48,8 +49,18 @@ public UploadOptions(Map params, String mimeType, boolean checkC this(params, mimeType, checkCrc, progressHandler, cancellationSignal, null); } - public UploadOptions(Map params, String mimeType, boolean checkCrc, + public UploadOptions(final Map params, String mimeType, boolean checkCrc, UpProgressHandler progressHandler, UpCancellationSignal cancellationSignal, NetReadyHandler netReadyHandler) { + int netReadyCheckTime = 6; + try { + String netCheckTime = params.get("netCheckTime"); + if (netCheckTime != null) { + netReadyCheckTime = Integer.parseInt(netCheckTime); + } + } catch (Exception e) { + e.printStackTrace(); + } + Log.e("qiniutest","netCheckTime:"+netReadyCheckTime); this.params = filterParam(params); this.mimeType = mime(mimeType); this.checkCrc = checkCrc; @@ -65,13 +76,14 @@ public boolean isCancelled() { return false; } }; + final int finalNetReadyCheckTime = netReadyCheckTime; this.netReadyHandler = netReadyHandler != null ? netReadyHandler : new NetReadyHandler() { @Override public void waitReady() { if (Thread.currentThread() == Looper.getMainLooper().getThread()) { return; } - for (int i = 0; i < 6; i++) { + for (int i = 0; i < finalNetReadyCheckTime; i++) { try { Thread.sleep(500); } catch (InterruptedException e) {