From c6be0aebd924d8d3982ba91250661749d5fe7f49 Mon Sep 17 00:00:00 2001 From: YangSen-qn Date: Thu, 9 Apr 2026 11:10:42 +0800 Subject: [PATCH 1/2] optimize permission dependencies --- .gitignore | 9 +- .idea/encodings.xml | 6 -- .idea/gradle.xml | 19 ---- .idea/misc.xml | 11 --- .idea/scopes/scope_settings.xml | 5 - library/build.gradle | 1 + library/src/main/AndroidManifest.xml | 7 +- .../qiniu/android/utils/AndroidNetwork.java | 95 +++++++++++++------ .../com/qiniu/android/utils/Constants.java | 5 + 9 files changed, 81 insertions(+), 77 deletions(-) delete mode 100644 .idea/encodings.xml delete mode 100644 .idea/gradle.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/scopes/scope_settings.xml diff --git a/.gitignore b/.gitignore index cf98a9627..18e3b47d7 100644 --- a/.gitignore +++ b/.gitignore @@ -40,5 +40,10 @@ java_pid* library/library.iml .idea/* -# Claude Code -.claude/ +# AI tool settings +.claude/settings.local.json +!.claude/skills +!.trae/skills +!.trae/rules +!.kiro/skills +!.kiro/steering diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index 97626ba45..000000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index b188df6b4..000000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 4e9665c8d..000000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/scopes/scope_settings.xml b/.idea/scopes/scope_settings.xml deleted file mode 100644 index 922003b84..000000000 --- a/.idea/scopes/scope_settings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/library/build.gradle b/library/build.gradle index 807123bd1..ff3629239 100755 --- a/library/build.gradle +++ b/library/build.gradle @@ -64,6 +64,7 @@ dependencies { // implementation 'com.google.code.findbugs:jsr305:3.0.2' implementation 'org.conscrypt:conscrypt-android:2.5.3' implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation 'androidx.annotation:annotation:1.9.1' androidTestImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.2.1' diff --git a/library/src/main/AndroidManifest.xml b/library/src/main/AndroidManifest.xml index 3b7e472b2..a9abf90ce 100644 --- a/library/src/main/AndroidManifest.xml +++ b/library/src/main/AndroidManifest.xml @@ -2,12 +2,9 @@ xmlns:tools="http://schemas.android.com/tools"> - - - - + = Build.VERSION_CODES.M) { + NetworkCapabilities caps = connMgr.getNetworkCapabilities(connMgr.getActiveNetwork()); + return caps != null && caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + } + NetworkInfo info = connMgr.getActiveNetworkInfo(); return info != null && info.isConnected(); } catch (Exception e) { @@ -65,14 +66,14 @@ public static boolean isNetWorkReady() { public static String getHostIP() { String hostIp = null; try { - Enumeration nis = NetworkInterface.getNetworkInterfaces(); + Enumeration nis = NetworkInterface.getNetworkInterfaces(); if (nis == null) { return null; } InetAddress ia = null; while (nis.hasMoreElements()) { - NetworkInterface ni = (NetworkInterface) nis.nextElement(); + NetworkInterface ni = nis.nextElement(); Enumeration ias = ni.getInetAddresses(); while (ias.hasMoreElements()) { ia = ias.nextElement(); @@ -80,7 +81,6 @@ public static String getHostIP() { hostIp = ia.getHostAddress(); break; } - continue; } } } catch (SocketException e) { @@ -96,45 +96,54 @@ public static String getHostIP() { * {@link Constants#NETWORK_CLASS_2_G} * {@link Constants#NETWORK_CLASS_3_G} * {@link Constants#NETWORK_CLASS_4_G} - * ... + * {@link Constants#NETWORK_CLASS_5_G} + * {@link Constants#NETWORK_CLASS_MOBILE} * * @param context context * @return 网络类型 */ public static String networkType(Context context) { try { - return networkTypeWithException(context); + return getNetWorkClass(context); } catch (Exception e) { e.printStackTrace(); return null; } } - private static String networkTypeWithException(Context context) throws Exception { + private static String getNetWorkClass(Context context) { if (context == null) { return Constants.NETWORK_CLASS_UNKNOWN; } - ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - if (connectivity == null) { - return Constants.NETWORK_CLASS_UNKNOWN; + // API 29+ getNetworkType() 已废弃,直接用 NetworkCapabilities + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + return getNetworkClassByConnectivity(context); } - NetworkInfo networkInfo = connectivity.getActiveNetworkInfo(); - if (networkInfo == null || !networkInfo.isConnected()) { - return Constants.NETWORK_CLASS_UNKNOWN; + // API 1-28 优先用 TelephonyManager,结果为 unknown 时降级 + String networkType = getNetworkTypeByTelephony(context); + if (networkType != null && !Constants.NETWORK_CLASS_UNKNOWN.equals(networkType)) { + return networkType; } - int netWorkType = networkInfo.getType(); - if (netWorkType == ConnectivityManager.TYPE_WIFI) { - return Constants.NETWORK_WIFI; - } else if (netWorkType == ConnectivityManager.TYPE_MOBILE) { - return getNetWorkClass(context); + // 此接口需要 23+,但返回信息不详细,所以上面优先使用 getNetworkTypeByTelephony + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + return getNetworkClassByConnectivity(context); } + return Constants.NETWORK_CLASS_UNKNOWN; } - private static String getNetWorkClass(Context context) { + /** + * 通过 TelephonyManager 获取网络类型(2G/3G/4G/5G) + * API < 23 时无需权限,API 23-28 需要 READ_PHONE_STATE 权限 + * + * @param context context + * @return 网络类型 + */ + @SuppressLint("MissingPermission") + private static String getNetworkTypeByTelephony(Context context) { if (context.checkPermission(Manifest.permission.READ_PHONE_STATE, Process.myPid(), Process.myUid()) != PackageManager.PERMISSION_GRANTED) { return Constants.NETWORK_CLASS_UNKNOWN; } @@ -166,7 +175,6 @@ private static String getNetWorkClass(Context context) { case TelephonyManager.NETWORK_TYPE_LTE: return Constants.NETWORK_CLASS_4_G; - case TelephonyManager.NETWORK_TYPE_NR: return Constants.NETWORK_CLASS_5_G; @@ -174,4 +182,33 @@ private static String getNetWorkClass(Context context) { return Constants.NETWORK_CLASS_UNKNOWN; } } + + /** + * 使用 NetworkCapabilities 获取网络类型(无需 READ_PHONE_STATE 权限) + * API 23+ + * + * @param context context + * @return 网络类型 + */ + @RequiresApi(Build.VERSION_CODES.M) + private static String getNetworkClassByConnectivity(Context context) { + ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + if (cm == null) { + return Constants.NETWORK_CLASS_UNKNOWN; + } + + NetworkCapabilities caps = cm.getNetworkCapabilities(cm.getActiveNetwork()); + if (caps == null) { + return Constants.NETWORK_CLASS_UNKNOWN; + } + + if (caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { + return Constants.NETWORK_WIFI; + } + if (caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + // 无法细分 2G/3G/4G/5G,统一返回 mobile + return Constants.NETWORK_CLASS_MOBILE; + } + return Constants.NETWORK_CLASS_UNKNOWN; + } } diff --git a/library/src/main/java/com/qiniu/android/utils/Constants.java b/library/src/main/java/com/qiniu/android/utils/Constants.java index 40468b2bc..ebd109e80 100644 --- a/library/src/main/java/com/qiniu/android/utils/Constants.java +++ b/library/src/main/java/com/qiniu/android/utils/Constants.java @@ -15,6 +15,11 @@ public class Constants { */ public static final String NETWORK_WIFI = "wifi"; + /** + * mobile network (2G/3G/4G/5G, without precise classification) + */ + public static final String NETWORK_CLASS_MOBILE = "mobile"; + /** * "2G" networks */ From dfe20e02e424cd62b6a7b07f4ee506d83884212b Mon Sep 17 00:00:00 2001 From: YangSen-qn Date: Tue, 14 Apr 2026 15:27:21 +0800 Subject: [PATCH 2/2] version to v8.11.0 --- CHANGELOG.md | 8 +++++ README.md | 1 + .../com/qiniu/android/common/Constants.java | 2 +- .../com/qiniu/android/http/ResponseInfo.java | 2 +- .../qiniu/android/utils/AndroidNetwork.java | 34 +++++++++++++++++-- 5 files changed, 43 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df1fbe521..022807e33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,12 @@ #Changelog +## 8.11.0(2026-04-14) +* 调整 + * 重构网络类型判断逻辑,API 29+ 使用 NetworkCapabilities,API 1-28 使用 TelephonyManager 细分蜂窝代际 + * 优化权限声明,移除 ACCESS_WIFI_STATE、READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE,READ_PHONE_STATE 限制 maxSdkVersion 为 28 + * 增加 NETWORK_CLASS_MOBILE 常量,无法细分蜂窝代际时统一返回 mobile + * 增加 5G 网络类型识别 + * isNetWorkReady() 方法适配 NetworkCapabilities + ## 8.10.0(2026-03-17) * 调整 * 解耦 TransactionManager 定时器生命周期 diff --git a/README.md b/README.md index cabff33d9..5a200dff0 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ https://github.com/qiniudemo/qiniu-lab-android | Qiniu SDK 版本 | 最低 Android版本 | 依赖库版本 | |--------------|-----------------|------------------------| +| 8.11.x | Android 4.0+ | okhttp 4+ | | 8.10.x | Android 4.0+ | okhttp 4+ | | 8.9.x | Android 4.0+ | okhttp 4+ | | 8.8.x | Android 4.0+ | okhttp 4+ | 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 a9fa2402b..18e81d76c 100644 --- a/library/src/main/java/com/qiniu/android/common/Constants.java +++ b/library/src/main/java/com/qiniu/android/common/Constants.java @@ -9,7 +9,7 @@ public final class Constants { /** * SDK 版本号 */ - public static final String VERSION = "8.10.0"; + public static final String VERSION = "8.11.0"; /** * UTF-8 编码 diff --git a/library/src/main/java/com/qiniu/android/http/ResponseInfo.java b/library/src/main/java/com/qiniu/android/http/ResponseInfo.java index 5510d7c8d..1d4b29865 100644 --- a/library/src/main/java/com/qiniu/android/http/ResponseInfo.java +++ b/library/src/main/java/com/qiniu/android/http/ResponseInfo.java @@ -15,7 +15,7 @@ public final class ResponseInfo { /** - * StatusCode >= 100 见:https://developer.qiniu.com/kodo/3928/error-responses + * StatusCode 大于等于 100 见:https://developer.qiniu.com/kodo/3928/error-responses */ @Deprecated diff --git a/library/src/main/java/com/qiniu/android/utils/AndroidNetwork.java b/library/src/main/java/com/qiniu/android/utils/AndroidNetwork.java index 2728913db..6a54c98e1 100644 --- a/library/src/main/java/com/qiniu/android/utils/AndroidNetwork.java +++ b/library/src/main/java/com/qiniu/android/utils/AndroidNetwork.java @@ -127,12 +127,13 @@ private static String getNetWorkClass(Context context) { return networkType; } - // 此接口需要 23+,但返回信息不详细,所以上面优先使用 getNetworkTypeByTelephony + // API 23+ 使用 NetworkCapabilities(无需 READ_PHONE_STATE 权限) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return getNetworkClassByConnectivity(context); } - return Constants.NETWORK_CLASS_UNKNOWN; + // API < 23 使用旧版 ConnectivityManager 判断 WiFi / 移动网络 + return getNetworkClassByLegacyConnectivity(context); } /** @@ -183,6 +184,35 @@ private static String getNetworkTypeByTelephony(Context context) { } } + /** + * 使用旧版 ConnectivityManager 获取网络类型 + * 适用于 API < 23(NetworkCapabilities 不可用)的场景 + *./ + * @param context context + * @return 网络类型 + */ + @SuppressWarnings("deprecation") + private static String getNetworkClassByLegacyConnectivity(Context context) { + ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + if (cm == null) { + return Constants.NETWORK_CLASS_UNKNOWN; + } + + NetworkInfo info = cm.getActiveNetworkInfo(); + if (info == null || !info.isConnected()) { + return Constants.NETWORK_CLASS_UNKNOWN; + } + + switch (info.getType()) { + case ConnectivityManager.TYPE_WIFI: + return Constants.NETWORK_WIFI; + case ConnectivityManager.TYPE_MOBILE: + return Constants.NETWORK_CLASS_MOBILE; + default: + return Constants.NETWORK_CLASS_UNKNOWN; + } + } + /** * 使用 NetworkCapabilities 获取网络类型(无需 READ_PHONE_STATE 权限) * API 23+