add network info

This commit is contained in:
xsean 2025-12-23 12:13:38 +08:00
parent 5239088041
commit 9f49a19530
2 changed files with 510 additions and 2 deletions

View File

@ -1,5 +1,6 @@
package com.xyzshell.andinfo.libs package com.xyzshell.andinfo.libs
import android.content.Context
import java.io.File import java.io.File
import java.io.RandomAccessFile import java.io.RandomAccessFile
@ -13,7 +14,7 @@ data class MemoryInfo(
val zramUsed: Long // zram 已使用 (字节) val zramUsed: Long // zram 已使用 (字节)
) )
class MemInfo { class MemInfo(private val context: Context){
fun getMemoryInfo(): MemoryInfo { fun getMemoryInfo(): MemoryInfo {
val totalRam = getTotalMemory() val totalRam = getTotalMemory()

View File

@ -1,4 +1,511 @@
package com.xyzshell.andinfo.libs package com.xyzshell.andinfo.libs
class NetworkInfo { import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.net.*
import android.net.wifi.ScanResult
import android.net.wifi.WifiManager
import android.net.wifi.WifiInfo
import android.os.Build
import android.telephony.*
import androidx.annotation.RequiresPermission
import androidx.core.app.ActivityCompat
import kotlin.text.compareTo
/**
* 网络信息工具类提供当前网络类型Wi-Fi详情移动数据详情等获取方法
*/
class NetworkInfo(private val context: Context) {
/**
* 当前网络类型枚举
*/
enum class NetworkType {
WIFI, MOBILE, NONE
}
/**
* Wi-Fi详细信息数据结构
*/
data class WifiDetails(
val connected: Boolean, // 是否已连接
val ssid: String?, // SSID名称
val bssid: String?, // BSSID
val capabilities: String?, // 加密/功能信息
val linkSpeedMbps: Int?, // 连接速率
val rssi: Int?, // dBm信号强度
val signalLevelPercent: Int?, // 信号强度百分比
val frequency: Int?, // 频率(MHz)
val channel: Int?, // 信道
val standard: String?, // 当前连接的标准
val dhcpServer: String?, // DHCP服务器
val leaseDuration: Int?, // DHCP租约期限(秒)
val gateway: String?, // 网关
val subnetMask: String?, // 子网掩码
val dns1: String?, // DNS1
val dns2: String?, // DNS2
val ip: String?, // IPv4地址
val ipv6: List<String>?, // IPv6地址列表
val supportedStandards: List<String>?, // 硬件支持的Wi-Fi标准
val wifiDirect: Boolean?, // 是否支持Wi-Fi Direct
val wifiAware: Boolean?, // 是否支持Wi-Fi Aware
val wifiPasspoint: Boolean?, // 是否支持Passpoint
val support5G: Boolean?, // 是否支持5GHz Wi-Fi
val support6G: Boolean?, // 是否支持6GHz Wi-Fi
//val support60G: Boolean? // 是否支持60GHz Wi-Fi
)
/**
* SIM卡信息数据结构
*/
data class SimInfo(
val slotIndex: Int, // 卡槽索引
val carrierName: String?, // 运营商名称
val operator: String?, // 运营商代码(MCC+MNC)
val countryIso: String?, // 国家代码
val roaming: Boolean, // 是否漫游
val simState: Int, // SIM卡状态
val simStateText: String, // SIM卡状态文本
val phoneType: Int, // 手机类型
val phoneTypeText: String, // 手机类型文本
val networkType: Int, // 网络类型
val networkTypeText: String, // 网络类型文本
val isEsim: Boolean // 是否eSIM
)
/**
* 移动数据详细信息数据结构
*/
data class MobileDetails(
val dualSim: Boolean, // 是否双卡
val phoneCount: Int, // 卡槽数量
val phoneType: Int, // 手机类型
val esimSupported: Boolean, // 是否支持eSIM
val dataEnabled: Boolean, // 移动数据是否开启
val dataSim: Int?, // 默认数据网络类型
val voiceSim: Int?, // 默认语音网络类型
val smsSim: Int?, // 默认短信卡(Android无直接API)
val simInfos: List<SimInfo> // SIM卡信息列表
)
/**
* 获取当前网络类型Wi-Fi/移动数据/无网络
*/
fun getCurrentNetworkType(): NetworkType {
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
?: return NetworkType.NONE
return try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val active = cm.activeNetwork ?: return NetworkType.NONE
val caps = cm.getNetworkCapabilities(active) ?: return NetworkType.NONE
when {
caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> NetworkType.WIFI
caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> NetworkType.MOBILE
else -> NetworkType.NONE
}
} else {
@Suppress("DEPRECATION")
when (cm.activeNetworkInfo?.type) {
ConnectivityManager.TYPE_WIFI -> NetworkType.WIFI
ConnectivityManager.TYPE_MOBILE -> NetworkType.MOBILE
else -> NetworkType.NONE
}
}
} catch (e: Exception) {
NetworkType.NONE
}
}
/**
* 获取当前Wi-Fi详细信息
* 需要权限: ACCESS_WIFI_STATE, ACCESS_FINE_LOCATION (Android 10+)
*/
fun getWifiDetails(): WifiDetails? {
val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as? WifiManager
?: return null
// 检查权限
if (!checkWifiPermissions()) {
return null
}
return try {
val wifiInfo = wifiManager.connectionInfo ?: return createEmptyWifiDetails()
val connected = wifiInfo.networkId != -1
if (!connected) return createEmptyWifiDetails()
val dhcp = wifiManager.dhcpInfo
val ssid = wifiInfo.ssid?.removePrefix("\"")?.removeSuffix("\"")
val bssid = wifiInfo.bssid
val linkSpeed = wifiInfo.linkSpeed
val rssi = wifiInfo.rssi
val freq = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
wifiInfo.frequency
} else null
val channel = freq?.let { calculateChannel(it) }
val level = if (rssi != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
WifiManager.calculateSignalLevel(rssi, 100)
} else {
@Suppress("DEPRECATION")
WifiManager.calculateSignalLevel(rssi, 100)
}
} else null
// 获取加密能力信息
val capabilities = try {
wifiManager.scanResults.find { it.BSSID == bssid }?.capabilities
} catch (e: SecurityException) {
null
}
// 获取当前Wi-Fi标准
val standard = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
when (wifiInfo.wifiStandard) {
ScanResult.WIFI_STANDARD_LEGACY -> "802.11a/b/g"
ScanResult.WIFI_STANDARD_11N -> "802.11n (Wi-Fi 4)"
ScanResult.WIFI_STANDARD_11AC -> "802.11ac (Wi-Fi 5)"
ScanResult.WIFI_STANDARD_11AX -> "802.11ax (Wi-Fi 6/6E)"
else -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
when (wifiInfo.wifiStandard) {
ScanResult.WIFI_STANDARD_11AD -> "802.11ad (WiGig)"
else -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
when (wifiInfo.wifiStandard) {
ScanResult.WIFI_STANDARD_11BE -> "802.11be (Wi-Fi 7)"
else -> "Unknown"
}
} else "Unknown"
}
} else "Unknown"
}
} else null
val dhcpServer = dhcp?.serverAddress?.let { intToIp(it) }
val leaseDuration = dhcp?.leaseDuration
val gateway = dhcp?.gateway?.let { intToIp(it) }
val subnetMask = dhcp?.netmask?.let { intToIp(it) }
val dns1 = dhcp?.dns1?.let { intToIp(it) }
val dns2 = dhcp?.dns2?.let { intToIp(it) }
val ip = dhcp?.ipAddress?.let { intToIp(it) }
val ipv6 = getIpv6Addresses()
val supportedStandards = getSupportedWifiStandards(wifiManager)
// Wi-Fi Direct (P2P) 支持
val wifiDirect = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)
} else null
// Wi-Fi Aware (NAN) 支持
val wifiAware = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)
} else null
// Passpoint (Hotspot 2.0) 支持
val wifiPasspoint = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
try {
wifiManager.isWifiPasspointEnabled
} catch (e: NoSuchMethodError) {
// 某些设备可能不支持此方法
null
} catch (e: Exception) {
null
}
} else null
val support5G = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
wifiManager.is5GHzBandSupported
} else null
val support6G = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
wifiManager.is6GHzBandSupported
} else null
val support60G = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
wifiManager.is60GHzBandSupported
} else null
WifiDetails(
connected, ssid, bssid, capabilities, linkSpeed, rssi, level, freq, channel, standard,
dhcpServer, leaseDuration, gateway, subnetMask, dns1, dns2, ip, ipv6,
supportedStandards, wifiDirect, wifiAware, wifiPasspoint, support5G, support6G
)
} catch (e: Exception) {
null
}
}
/**
* 获取移动数据详细信息包括双卡eSIMSIM卡状态等
* 需要权限: READ_PHONE_STATE
*/
@RequiresPermission(Manifest.permission.READ_PHONE_STATE)
fun getMobileDetails(): MobileDetails? {
if (!checkPhonePermissions()) {
return null
}
val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as? TelephonyManager
?: return null
return try {
val subscriptionManager = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as? SubscriptionManager
} else null
val sims = mutableListOf<SimInfo>()
val esimSupported = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
tm.isMultiSimSupported == TelephonyManager.MULTISIM_ALLOWED &&
context.packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_EUICC)
} else false
val phoneType = tm.phoneType
val phoneCount = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
tm.phoneCount
} else 1
val dualSim = phoneCount > 1
val dataEnabled = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
tm.isDataEnabled
} else {
@Suppress("DEPRECATION")
tm.dataState == TelephonyManager.DATA_CONNECTED
}
val dataSim = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
tm.dataNetworkType
} else null
val voiceSim = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
tm.voiceNetworkType
} else null
val smsSim = null // Android没有直接获取默认短信卡的API
// 获取每个SIM卡的详细信息
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1 && subscriptionManager != null) {
val subInfoList = subscriptionManager.activeSubscriptionInfoList ?: emptyList()
for (info in subInfoList) {
val subTm = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
tm.createForSubscriptionId(info.subscriptionId)
} else tm
sims.add(
SimInfo(
slotIndex = info.simSlotIndex,
carrierName = info.carrierName?.toString(),
operator = subTm.simOperator,
countryIso = subTm.simCountryIso,
roaming = subTm.isNetworkRoaming,
simState = subTm.simState,
simStateText = getSimStateText(subTm.simState),
phoneType = subTm.phoneType,
phoneTypeText = getPhoneTypeText(subTm.phoneType),
networkType = subTm.networkType,
networkTypeText = getNetworkTypeText(subTm.networkType),
isEsim = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
info.isEmbedded
} else false
)
)
}
} else {
// 旧版本系统,只能获取单卡信息
sims.add(
SimInfo(
slotIndex = 0,
carrierName = tm.simOperatorName,
operator = tm.simOperator,
countryIso = tm.simCountryIso,
roaming = tm.isNetworkRoaming,
simState = tm.simState,
simStateText = getSimStateText(tm.simState),
phoneType = tm.phoneType,
phoneTypeText = getPhoneTypeText(tm.phoneType),
networkType = tm.networkType,
networkTypeText = getNetworkTypeText(tm.networkType),
isEsim = esimSupported
)
)
}
MobileDetails(
dualSim = dualSim,
phoneCount = phoneCount,
phoneType = phoneType,
esimSupported = esimSupported,
dataEnabled = dataEnabled,
dataSim = dataSim,
voiceSim = voiceSim,
smsSim = smsSim,
simInfos = sims
)
} catch (e: Exception) {
null
}
}
/**
* int型IP转为字符串
*/
private fun intToIp(ip: Int): String =
"${ip and 0xFF}.${ip shr 8 and 0xFF}.${ip shr 16 and 0xFF}.${ip shr 24 and 0xFF}"
/**
* 获取所有IPv6地址
*/
private fun getIpv6Addresses(): List<String> {
val result = mutableListOf<String>()
try {
val interfaces = java.net.NetworkInterface.getNetworkInterfaces()
for (iface in interfaces) {
if (!iface.isUp || iface.isLoopback) continue
for (addr in iface.inetAddresses) {
if (addr is java.net.Inet6Address && !addr.isLoopbackAddress && !addr.isLinkLocalAddress) {
result.add(addr.hostAddress ?: continue)
}
}
}
} catch (_: Exception) {}
return result
}
/**
* 获取设备支持的Wi-Fi标准
*/
private fun getSupportedWifiStandards(wifiManager: WifiManager): List<String> {
val list = mutableListOf<String>()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (wifiManager.isWifiStandardSupported(android.net.wifi.ScanResult.WIFI_STANDARD_LEGACY)) {
list.add("802.11a/b/g")
}
if (wifiManager.isWifiStandardSupported(android.net.wifi.ScanResult.WIFI_STANDARD_11N)) {
list.add("802.11n (Wi-Fi 4)")
}
if (wifiManager.isWifiStandardSupported(android.net.wifi.ScanResult.WIFI_STANDARD_11AC)) {
list.add("802.11ac (Wi-Fi 5)")
}
if (wifiManager.isWifiStandardSupported(android.net.wifi.ScanResult.WIFI_STANDARD_11AX)) {
list.add("802.11ax (Wi-Fi 6/6E)")
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
if (wifiManager.isWifiStandardSupported(android.net.wifi.ScanResult.WIFI_STANDARD_11AD)) {
list.add("802.11ad (WiGig)")
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (wifiManager.isWifiStandardSupported(android.net.wifi.ScanResult.WIFI_STANDARD_11BE)) {
list.add("802.11be (Wi-Fi 7)")
}
}
}
return list
}
/**
* 根据频率计算信道
*/
private fun calculateChannel(frequency: Int): Int {
return when {
frequency in 2412..2484 -> (frequency - 2407) / 5 // 2.4GHz
frequency in 5170..5825 -> (frequency - 5000) / 5 // 5GHz
frequency in 5955..7115 -> (frequency - 5950) / 5 // 6GHz
else -> -1
}
}
/**
* 创建空的Wi-Fi详情对象
*/
private fun createEmptyWifiDetails() = WifiDetails(
false, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null,
null
)
/**
* 检查Wi-Fi相关权限
*/
private fun checkWifiPermissions(): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
return ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
}
return ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_WIFI_STATE
) == PackageManager.PERMISSION_GRANTED
}
/**
* 检查电话相关权限
*/
private fun checkPhonePermissions(): Boolean {
return ActivityCompat.checkSelfPermission(
context,
Manifest.permission.READ_PHONE_STATE
) == PackageManager.PERMISSION_GRANTED
}
/**
* 获取SIM卡状态文本
*/
private fun getSimStateText(state: Int): String = when (state) {
TelephonyManager.SIM_STATE_ABSENT -> "无卡"
TelephonyManager.SIM_STATE_PIN_REQUIRED -> "需要PIN"
TelephonyManager.SIM_STATE_PUK_REQUIRED -> "需要PUK"
TelephonyManager.SIM_STATE_NETWORK_LOCKED -> "网络锁定"
TelephonyManager.SIM_STATE_READY -> "就绪"
TelephonyManager.SIM_STATE_NOT_READY -> "未就绪"
TelephonyManager.SIM_STATE_PERM_DISABLED -> "永久禁用"
TelephonyManager.SIM_STATE_CARD_IO_ERROR -> "卡IO错误"
TelephonyManager.SIM_STATE_CARD_RESTRICTED -> "卡受限"
else -> "未知"
}
/**
* 获取手机类型文本
*/
private fun getPhoneTypeText(type: Int): String = when (type) {
TelephonyManager.PHONE_TYPE_NONE -> ""
TelephonyManager.PHONE_TYPE_GSM -> "GSM"
TelephonyManager.PHONE_TYPE_CDMA -> "CDMA"
TelephonyManager.PHONE_TYPE_SIP -> "SIP"
else -> "未知"
}
/**
* 获取网络类型文本
*/
private fun getNetworkTypeText(type: Int): String = when (type) {
TelephonyManager.NETWORK_TYPE_GPRS -> "GPRS"
TelephonyManager.NETWORK_TYPE_EDGE -> "EDGE"
TelephonyManager.NETWORK_TYPE_UMTS -> "UMTS (3G)"
TelephonyManager.NETWORK_TYPE_CDMA -> "CDMA"
TelephonyManager.NETWORK_TYPE_EVDO_0 -> "EVDO 0"
TelephonyManager.NETWORK_TYPE_EVDO_A -> "EVDO A"
TelephonyManager.NETWORK_TYPE_1xRTT -> "1xRTT"
TelephonyManager.NETWORK_TYPE_HSDPA -> "HSDPA"
TelephonyManager.NETWORK_TYPE_HSUPA -> "HSUPA"
TelephonyManager.NETWORK_TYPE_HSPA -> "HSPA"
TelephonyManager.NETWORK_TYPE_IDEN -> "iDEN"
TelephonyManager.NETWORK_TYPE_EVDO_B -> "EVDO B"
TelephonyManager.NETWORK_TYPE_LTE -> "LTE (4G)"
TelephonyManager.NETWORK_TYPE_EHRPD -> "eHRPD"
TelephonyManager.NETWORK_TYPE_HSPAP -> "HSPA+"
TelephonyManager.NETWORK_TYPE_GSM -> "GSM"
TelephonyManager.NETWORK_TYPE_TD_SCDMA -> "TD-SCDMA"
TelephonyManager.NETWORK_TYPE_IWLAN -> "IWLAN"
else -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
when (type) {
TelephonyManager.NETWORK_TYPE_NR -> "5G NR"
else -> "未知"
}
} else "未知"
}
} }