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/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/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"> - - - - + = 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 a46ed3df5..6a54c98e1 100644 --- a/library/src/main/java/com/qiniu/android/utils/AndroidNetwork.java +++ b/library/src/main/java/com/qiniu/android/utils/AndroidNetwork.java @@ -5,25 +5,18 @@ import android.content.Context; import android.content.pm.PackageManager; import android.net.ConnectivityManager; +import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.os.Build; import android.os.Process; -import android.telephony.CellInfo; -import android.telephony.CellInfoCdma; -import android.telephony.CellInfoGsm; -import android.telephony.CellInfoLte; -import android.telephony.CellInfoWcdma; -import android.telephony.CellSignalStrengthCdma; -import android.telephony.CellSignalStrengthGsm; -import android.telephony.CellSignalStrengthLte; -import android.telephony.CellSignalStrengthWcdma; import android.telephony.TelephonyManager; +import androidx.annotation.RequiresApi; + import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.util.Enumeration; -import java.util.List; /** * Created by bailong on 16/9/7. @@ -47,7 +40,15 @@ public static boolean isNetWorkReady() { } ConnectivityManager connMgr = (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE); + if (connMgr == null) { + return true; + } try { + if (Build.VERSION.SDK_INT >= 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,55 @@ 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); + // 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); } - 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 +176,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 +183,62 @@ private static String getNetWorkClass(Context context) { return Constants.NETWORK_CLASS_UNKNOWN; } } + + /** + * 使用旧版 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+ + * + * @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 */