Android网络编程基础 #

一、网络权限 #

1.1 添加网络权限 #

xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">

    <!-- 网络访问权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    
    <!-- 网络状态权限 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    
    <!-- WiFi状态权限 -->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

</manifest>

1.2 检查网络状态 #

kotlin
fun isNetworkAvailable(context: Context): Boolean {
    val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        val network = connectivityManager.activeNetwork ?: return false
        val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
        
        return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
               capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
    } else {
        val networkInfo = connectivityManager.activeNetworkInfo
        return networkInfo?.isConnected == true
    }
}

fun isWifiConnected(context: Context): Boolean {
    val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        val network = connectivityManager.activeNetwork ?: return false
        val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
        return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
    } else {
        val networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
        return networkInfo?.isConnected == true
    }
}

二、HTTP协议 #

2.1 HTTP请求方法 #

方法 说明
GET 获取资源
POST 提交数据
PUT 更新资源
DELETE 删除资源
PATCH 部分更新
HEAD 获取响应头

2.2 HTTP状态码 #

状态码 说明
200 成功
201 创建成功
204 无内容
301 永久重定向
302 临时重定向
400 请求错误
401 未授权
403 禁止访问
404 资源不存在
500 服务器错误
502 网关错误
503 服务不可用

2.3 HTTP请求头 #

kotlin
val headers = mapOf(
    "Content-Type" to "application/json",
    "Accept" to "application/json",
    "Authorization" to "Bearer token",
    "User-Agent" to "MyApp/1.0",
    "Cache-Control" to "no-cache"
)

三、网络安全配置 #

3.1 创建网络安全配置文件 #

xml
<!-- res/xml/network_security_config.xml -->
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <!-- 允许明文传输(仅用于开发环境) -->
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system" />
        </trust-anchors>
    </base-config>
    
    <!-- 限制特定域名 -->
    <domain-config cleartextTrafficPermitted="false">
        <domain includeSubdomains="true">example.com</domain>
        <trust-anchors>
            <certificates src="system" />
        </trust-anchors>
    </domain-config>
    
    <!-- 自定义证书 -->
    <domain-config>
        <domain includeSubdomains="true">secure.example.com</domain>
        <trust-anchors>
            <certificates src="@raw/my_cert" />
        </trust-anchors>
    </domain-config>
</network-security-config>

3.2 在AndroidManifest中引用 #

xml
<application
    android:networkSecurityConfig="@xml/network_security_config"
    ...>
</application>

3.3 Android 9+ 明文传输 #

Android 9及以上默认禁止明文HTTP请求,需要配置:

xml
<network-security-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system" />
        </trust-anchors>
    </base-config>
</network-security-config>

四、使用HttpURLConnection #

4.1 GET请求 #

kotlin
fun httpGet(urlString: String): String {
    var connection: HttpURLConnection? = null
    try {
        val url = URL(urlString)
        connection = url.openConnection() as HttpURLConnection
        connection.requestMethod = "GET"
        connection.connectTimeout = 10000
        connection.readTimeout = 10000
        
        val responseCode = connection.responseCode
        if (responseCode == HttpURLConnection.HTTP_OK) {
            return connection.inputStream.bufferedReader().readText()
        } else {
            throw Exception("HTTP Error: $responseCode")
        }
    } finally {
        connection?.disconnect()
    }
}

4.2 POST请求 #

kotlin
fun httpPost(urlString: String, jsonBody: String): String {
    var connection: HttpURLConnection? = null
    try {
        val url = URL(urlString)
        connection = url.openConnection() as HttpURLConnection
        connection.requestMethod = "POST"
        connection.connectTimeout = 10000
        connection.readTimeout = 10000
        connection.doOutput = true
        connection.setRequestProperty("Content-Type", "application/json")
        
        connection.outputStream.use { output ->
            output.write(jsonBody.toByteArray())
        }
        
        val responseCode = connection.responseCode
        if (responseCode == HttpURLConnection.HTTP_OK) {
            return connection.inputStream.bufferedReader().readText()
        } else {
            throw Exception("HTTP Error: $responseCode")
        }
    } finally {
        connection?.disconnect()
    }
}

4.3 在协程中使用 #

kotlin
class NetworkRepository {
    
    suspend fun fetchData(url: String): String = withContext(Dispatchers.IO) {
        httpGet(url)
    }
    
    suspend fun postData(url: String, body: String): String = withContext(Dispatchers.IO) {
        httpPost(url, body)
    }
}

五、网络监听 #

5.1 注册网络回调 #

kotlin
class NetworkCallback : ConnectivityManager.NetworkCallback() {
    
    override fun onAvailable(network: Network) {
        Log.d("Network", "网络可用")
    }
    
    override fun onLost(network: Network) {
        Log.d("Network", "网络丢失")
    }
    
    override fun onCapabilitiesChanged(network: Network, capabilities: NetworkCapabilities) {
        val isWifi = capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
        val isCellular = capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
        Log.d("Network", "WiFi: $isWifi, Cellular: $isCellular")
    }
}

// 注册
val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkRequest = NetworkRequest.Builder()
    .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
    .build()
connectivityManager.registerNetworkCallback(networkRequest, NetworkCallback())

// 注销
connectivityManager.unregisterNetworkCallback(networkCallback)

5.2 使用LiveData监听网络 #

kotlin
class NetworkLiveData(private val context: Context) : LiveData<Boolean>() {
    
    private val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    
    private val networkCallback = object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) {
            postValue(true)
        }
        
        override fun onLost(network: Network) {
            postValue(false)
        }
    }
    
    override fun onActive() {
        super.onActive()
        val networkRequest = NetworkRequest.Builder()
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            .build()
        connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
        
        value = isNetworkAvailable(context)
    }
    
    override fun onInactive() {
        super.onInactive()
        connectivityManager.unregisterNetworkCallback(networkCallback)
    }
}

六、最佳实践 #

6.1 使用协程处理网络请求 #

kotlin
class MainViewModel : ViewModel() {
    
    private val repository = NetworkRepository()
    
    private val _result = MutableLiveData<Result<String>>()
    val result: LiveData<Result<String>> = _result
    
    fun fetchData(url: String) {
        viewModelScope.launch {
            _result.value = Result.loading()
            try {
                val data = repository.fetchData(url)
                _result.value = Result.success(data)
            } catch (e: Exception) {
                _result.value = Result.error(e.message ?: "Unknown error")
            }
        }
    }
}

6.2 处理超时和重试 #

kotlin
suspend fun <T> retryIO(times: Int = 3, block: suspend () -> T): T {
    var currentAttempt = 0
    var lastException: Exception? = null
    
    while (currentAttempt < times) {
        try {
            return block()
        } catch (e: IOException) {
            lastException = e
            currentAttempt++
            delay(1000L * currentAttempt)
        }
    }
    
    throw lastException ?: Exception("Unknown error")
}

// 使用
val result = retryIO {
    repository.fetchData(url)
}

6.3 缓存策略 #

kotlin
class CacheManager(private val context: Context) {
    
    private val cacheDir = File(context.cacheDir, "network_cache")
    
    fun saveCache(key: String, data: String) {
        File(cacheDir, key).writeText(data)
    }
    
    fun getCache(key: String): String? {
        val file = File(cacheDir, key)
        return if (file.exists()) file.readText() else null
    }
    
    fun clearCache() {
        cacheDir.deleteRecursively()
    }
}

七、总结 #

本章介绍了Android网络编程基础:

  1. 网络权限配置
  2. 网络状态检查
  3. HTTP协议基础
  4. 网络安全配置
  5. HttpURLConnection使用
  6. 网络状态监听
  7. 最佳实践

掌握网络编程基础是开发Android应用的重要技能,下一章将介绍更强大的网络库OkHttp和Retrofit。

最后更新:2026-03-26