撥號碼 *#*#4636#*#* 顯示「IP addr not reachable」,無法直接查看移動數據介面的 IP。需在 App 中程式化獲取。
public String getMobileIpAddress() {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
NetworkInterface intf = en.nextElement();
// 過濾回環、下行、非移動介面
if (intf.isLoopback() || !intf.isUp() || intf.getName().contains("lo")) continue;
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (inetAddress.isLoopbackAddress()) continue;
if (inetAddress instanceof Inet4Address) { // 僅 IPv4
return inetAddress.getHostAddress();
}
}
}
} catch (SocketException ex) {
Log.e("GetIP", ex.toString());
}
return null;
}
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Android 10+ 讀取介面列表需額外權限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) // 僅移動數據
.build();
cm.requestNetwork(request, new ConnectivityManager.NetworkCallback() {
@Override public void onAvailable(Network network) {
// 綁定到該網絡後再枚舉介面,確保拿到移動數據 IP
network.bindToSocket(socket); // 或用 network.getNetworkInterfaces()
}
});
wlan0 和 rmnet0,需按介面名或 NetworkCapabilities 過濾。instanceof Inet4Address。getNetworkInterfaces() 可能返回空,需改用 ConnectivityManager 綁定網絡後獲取。https://api.ipify.org)。fun getMobileIpv4(): String? = NetworkInterface.getNetworkInterfaces()
.asSequence()
.filter { it.isUp && !it.isLoopback }
.flatMap { it.inetAddresses.asSequence() }
.filter { it !is Inet6Address && !it.isLoopbackAddress }
.map { it.hostAddress }
.firstOrNull()
結合權限配置、介面過濾、版本適配,即可穩定獲取移動數據下的本機 IP。