You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android中通过编程获取设备的公网IP地址?

在Android中获取公网IP地址的方法

嘿,我懂你要在Android里用代码拿公网IP的需求——和用WifiManager或者InetAddress获取本地局域网IP完全不一样,公网IP是你的设备在互联网上的标识,本地设备自己是不知道的,得靠调用外部的公开API来获取。下面给你两种实用的实现方式,都是经过验证的:

前置准备:添加必要权限

首先得在你的AndroidManifest.xml里添加网络权限,不然连不上网:

<uses-permission android:name="android.permission.INTERNET" />
<!-- 可选权限,用来先检查网络状态,避免无网时白跑请求 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

方法一:使用原生HttpURLConnection(无需额外依赖)

Android自带的HttpURLConnection就能搞定,不过要注意网络请求绝对不能在主线程执行,这里用Kotlin协程来处理(比已弃用的AsyncTask更优雅):

完整代码实现

import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.BufferedReader
import java.io.InputStreamReader
import java.net.HttpURLConnection
import java.net.URL

// 挂起函数,用于获取公网IP
suspend fun getPublicIp(context: Context): String? {
    // 先检查网络是否可用,避免浪费资源
    if (!isNetworkAvailable(context)) {
        return null
    }

    return withContext(Dispatchers.IO) {
        // 用ipify的API,返回纯文本格式的公网IP,简单易处理
        val apiUrl = URL("https://api.ipify.org")
        val connection = apiUrl.openConnection() as HttpURLConnection

        try {
            // 设置超时时间,避免一直等待
            connection.connectTimeout = 5000
            connection.readTimeout = 5000

            if (connection.responseCode == HttpURLConnection.HTTP_OK) {
                // 读取返回的IP文本
                BufferedReader(InputStreamReader(connection.inputStream)).use { reader ->
                    reader.readLine()
                }
            } else {
                // 请求失败,返回null
                null
            }
        } catch (e: Exception) {
            // 捕获异常,比如网络波动、API不可用等
            e.printStackTrace()
            null
        } finally {
            // 记得关闭连接
            connection.disconnect()
        }
    }
}

// 辅助方法:检查当前网络是否可用
private fun isNetworkAvailable(context: Context): Boolean {
    val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val activeNetwork = connectivityManager.activeNetwork ?: return false
    val networkCapabilities = connectivityManager.getNetworkCapabilities(activeNetwork) ?: return false
    // 判断是否有互联网访问权限
    return networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
}

调用示例(在Activity中)

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 在生命周期协程里调用,避免内存泄漏
        lifecycleScope.launch {
            val publicIp = getPublicIp(this@MainActivity)
            publicIp?.let {
                // 成功获取到公网IP,这里可以做你需要的操作
                println("当前公网IP: $it")
            } ?: run {
                // 获取失败,处理错误情况
                println("获取公网IP失败,请检查网络")
            }
        }
    }
}

方法二:使用OkHttp(更简洁,适合已有依赖的项目)

如果你的项目已经在用OkHttp做网络请求,用它来获取公网IP会更简洁:

第一步:添加OkHttp依赖

在Module级别的build.gradle(或build.gradle.kts)里添加依赖:

implementation("com.squareup.okhttp3:okhttp:4.12.0")

完整代码实现

import android.content.Context
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import okhttp3.Request

// 初始化OkHttp客户端,全局单例即可
private val okHttpClient = OkHttpClient.Builder()
    .connectTimeout(5, java.util.concurrent.TimeUnit.SECONDS)
    .readTimeout(5, java.util.concurrent.TimeUnit.SECONDS)
    .build()

suspend fun getPublicIpWithOkHttp(context: Context): String? {
    // 同样先检查网络状态
    if (!isNetworkAvailable(context)) {
        return null
    }

    return withContext(Dispatchers.IO) {
        val request = Request.Builder()
            .url("https://api.ipify.org")
            .build()

        try {
            okHttpClient.newCall(request).execute().use { response ->
                // 请求成功则返回IP文本
                if (response.isSuccessful) {
                    response.body?.string()
                } else {
                    null
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }
}

// 复用之前的isNetworkAvailable方法
private fun isNetworkAvailable(context: Context): Boolean {
    val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val activeNetwork = connectivityManager.activeNetwork ?: return false
    val networkCapabilities = connectivityManager.getNetworkCapabilities(activeNetwork) ?: return false
    return networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
}

调用示例和方法一类似,直接在协程里调用即可

额外小贴士

  • 除了api.ipify.org,你还可以用其他免费的公网IP API,比如https://icanhazip.com、https://ifconfig.me/ip,这些都是返回纯文本IP的,用法完全一致
  • 尽量用HTTPS的API,避免明文传输,而且Android 10及以上默认禁止明文HTTP请求,用HTTPS就不用额外配置android:usesCleartextTraffic="true"
  • 记得处理异常情况,比如网络超时、API不可用、没有网络权限等,给用户友好的提示

内容的提问来源于stack exchange,提问作者Gaurav Mistry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:33:45