凌峰创科服务平台

Android如何建立服务器连接?

目录

  1. 核心概念:Android 网络通信基础

    Android如何建立服务器连接?-图1
    (图片来源网络,侵删)
    • 主线程限制 (NetworkOnMainThreadException)
    • 网络权限
    • HTTPS 与安全
  2. 使用原生 HttpURLConnection (官方推荐,基础)

    • 特点
    • GET 请求示例
    • POST 请求示例
  3. 使用第三方库 OkHttp (强烈推荐,现代标准)

    • 特点
    • GET 请求示例
    • POST 请求示例 (发送 JSON)
  4. 使用第三方库 Retrofit (高级,面向接口)

    • 特点
    • 设置步骤
    • 完整示例
  5. 后台执行网络请求

    Android如何建立服务器连接?-图2
    (图片来源网络,侵删)
    • 使用 Coroutine (Kotlin, 现代)
    • 使用 AsyncTask (Java, 已废弃,但为了完整性提及)
  6. 解析服务器响应

    • 手动解析 (JSON)
    • 使用 Gson / Moshi 自动解析
  7. 最佳实践与总结


核心概念:Android 网络通信基础

在开始写代码前,必须了解几个关键点。

a. 主线程限制

Android 4.0 (API Level 11) 之后,禁止在主线程(UI线程)上进行任何网络操作,如果在主线程发起网络请求,会抛出 NetworkOnMainThreadException 异常,这是为了防止网络请求阻塞 UI,导致应用“无响应”(ANR)。

Android如何建立服务器连接?-图3
(图片来源网络,侵删)

解决方案:

  • Java: 使用 AsyncTask, Thread + Handler, 或 ExecutorService
  • Kotlin: 使用 协程,这是目前最推荐、最简洁的方式。

b. 网络权限

你的应用必须告诉系统它需要访问网络,在 app/src/main/AndroidManifest.xml 文件中添加以下权限:

<!-- 允许应用打开网络套接字 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 如果你的应用使用的是明文 HTTP 流量,从 Android 9 (API 28) 开始,
     必须在 manifest 中配置 cleartextTrafficPermitted="true"。
     强烈建议使用 HTTPS。 -->
<application
    ...
    android:usesCleartextTraffic="true"
    ...>
    ...
</application>

c. HTTPS 与安全

现代应用必须使用 HTTPS 协议进行通信,以确保数据传输的加密和安全性,如果你使用自签名证书或开发环境的证书,需要在代码中进行信任处理(生产环境请谨慎)。


方法一:使用原生 HttpURLConnection

这是 Android SDK 自带的工具,无需额外依赖,适合简单的网络请求。

特点

  • 优点: 无需依赖,轻量级,官方维护。
  • 缺点: API 较为繁琐,需要手动管理线程和解析。

GET 请求示例 (Kotlin)

import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import java.io.BufferedReader
import java.io.InputStreamReader
import java.net.HttpURLConnection
import java.net.URL
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val textView: TextView = findViewById(R.id.textView)
        val button: Button = findViewById(R.id.button)
        button.setOnClickListener {
            // 在 Kotlin 中,我们通常使用协程来处理网络请求
            // 这里为了展示 HttpURLConnection,我们创建一个新的线程
            Thread(Runnable {
                try {
                    val apiUrl = "https://api.github.com/users/octocat"
                    val url = URL(apiUrl)
                    val urlConnection = url.openConnection() as HttpURLConnection
                    // 设置请求方法
                    urlConnection.requestMethod = "GET"
                    // 设置连接超时和读取超时
                    urlConnection.connectTimeout = 5000
                    urlConnection.readTimeout = 5000
                    // 检查响应码
                    if (urlConnection.responseCode == HttpURLConnection.HTTP_OK) {
                        val inputStream = urlConnection.inputStream
                        val reader = BufferedReader(InputStreamReader(inputStream))
                        val response = StringBuilder()
                        var line: String?
                        while (reader.readLine().also { line = it } != null) {
                            response.append(line)
                        }
                        reader.close()
                        inputStream.close()
                        // 在主线程更新 UI
                        runOnUiThread {
                            textView.text = response.toString()
                        }
                    } else {
                        // 在主线程更新 UI
                        runOnUiThread {
                            textView.text = "Error: ${urlConnection.responseCode}"
                        }
                    }
                } catch (e: Exception) {
                    e.printStackTrace()
                    // 在主线程更新 UI
                    runOnUiThread {
                        textView.text = "Exception: ${e.message}"
                    }
                }
            }).start()
        }
    }
}

方法二:使用 OkHttp (强烈推荐)

OkHttp 是目前 Android 开发中最流行的网络库之一,它高效、易用,并内置了连接池、拦截器等强大功能。

添加依赖

app/build.gradle.kts (或 app/build.gradle) 文件中添加:

// build.gradle.kts (Kotlin DSL)
dependencies {
    implementation("com.squareup.okhttp3:okhttp:4.12.0") // 使用最新版本
}
// build.gradle (Groovy DSL)
dependencies {
    implementation 'com.squareup.okhttp3:okhttp:4.12.0'
}

GET 请求示例 (Kotlin + 协程)

import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*
import okhttp3.OkHttpClient
import okhttp3.Request
import java.io.IOException
class OkHttpActivity : AppCompatActivity() {
    private val client = OkHttpClient()
    private val scope = MainScope() // 创建一个主作用域
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val textView: TextView = findViewById(R.id.textView)
        val button: Button = findViewById(R.id.button)
        button.setOnClickListener {
            // 在协程作用域内发起网络请求
            scope.launch {
                try {
                    val response = get("https://api.github.com/users/octocat")
                    // 在主线程更新 UI
                    textView.text = response
                } catch (e: Exception) {
                    textView.text = "Error: ${e.message}"
                }
            }
        }
    }
    private suspend fun get(url: String): String = withContext(Dispatchers.IO) {
        val request = Request.Builder()
            .url(url)
            .build()
        client.newCall(request).execute().use { response ->
            if (!response.isSuccessful) throw IOException("Unexpected code $response")
            response.body!!.string()
        }
    }
    override fun onDestroy() {
        super.onDestroy()
        scope.cancel() // 在 Activity 销毁时取消协程,防止内存泄漏
    }
}

POST 请求示例 (发送 JSON)

// 在 OkHttpActivity 中添加这个方法
private suspend fun post(url: String, json: String): String = withContext(Dispatchers.IO) {
    val mediaType = "application/json; charset=utf-8".toMediaType()
    val body = json.toRequestBody(mediaType)
    val request = Request.Builder()
        .url(url)
        .post(body)
        .build()
    client.newCall(request).execute().use { response ->
        if (!response.isSuccessful) throw IOException("Unexpected code $response")
        response.body!!.string()
    }
}
// 调用示例
// val json = """{"name": "John", "role": "Developer"}"""
// val response = post("https://your-api-endpoint.com/users", json)

方法三:使用 Retrofit (高级)

Retrofit 是一个类型安全的 HTTP 客户端,它将 REST API 的端点定义为 Java/Kotlin 接口,它底层通常使用 OkHttp,并专注于将 JSON/XML 响应自动解析成你定义的数据模型(POJO/DTO)。

特点

  • 优点: 代码非常简洁,类型安全,自动解析,易于维护和测试。
  • 缺点: 引入了额外的依赖(Retrofit + OkHttp + 解析器),学习曲线稍高。

设置步骤

  1. 添加依赖

    // build.gradle.kts
    dependencies {
        implementation("com.squareup.retrofit2:retrofit:2.9.0")
        implementation("com.squareup.retrofit2:converter-gson:2.9.0") // Gson 解析器
        implementation("com.squareup.okhttp3:logging-interceptor:4.12.0") // 日志拦截器 (可选)
    }
  2. 定义数据模型

    // User.kt
    data class User(
        val login: String,
        val id: Int,
        val avatar_url: String,
        val name: String?
    )
  3. 创建 API 接口

    // ApiService.kt
    import retrofit2.http.GET
    import retrofit2.http.Path
    interface ApiService {
        @GET("users/{username}")
        suspend fun getUser(@Path("username") username: String): User
    }
  4. 创建 Retrofit 实例并进行网络请求

    import android.os.Bundle
    import android.widget.Button
    import android.widget.TextView
    import androidx.appcompat.app.AppCompatActivity
    import retrofit2.Retrofit
    import retrofit2.converter.gson.GsonConverterFactory
    import kotlinx.coroutines.*
    class RetrofitActivity : AppCompatActivity() {
        private lateinit var apiService: ApiService
        private val scope = MainScope()
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            val textView: TextView = findViewById(R.id.textView)
            val button: Button = findViewById(R.id.button)
            // 1. 创建 Retrofit 实例
            val retrofit = Retrofit.Builder()
                .baseUrl("https://api.github.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build()
            // 2. 创建 API 接口的实现
            apiService = retrofit.create(ApiService::class.java)
            button.setOnClickListener {
                scope.launch {
                    try {
                        // 3. 调用接口方法,发起网络请求
                        val user = apiService.getUser("octocat")
                        // 在主线程更新 UI
                        textView.text = "Name: ${user.name}\nLogin: ${user.login}"
                    } catch (e: Exception) {
                        textView.text = "Error: ${e.message}"
                    }
                }
            }
        }
        override fun onDestroy() {
            super.onDestroy()
            scope.cancel()
        }
    }

后台执行网络请求

使用 Coroutine (Kotlin)

这是目前 Android 官方推荐的并发处理方式,它非常轻量,可以简化异步代码,使其看起来像同步代码。

  • Dispatchers.Main: 主线程,用于更新 UI。
  • Dispatchers.IO: 专门用于执行磁盘或网络等 I/O 操作的线程池。
  • withContext(Dispatchers.IO) { ... }: 将代码块中的任务切换到 IO 线程执行,并等待结果返回。

在上面的 OkHttpRetrofit 示例中,我们已经展示了如何使用协程。


解析服务器响应

手动解析

对于简单的 JSON,可以使用 JSONObjectJSONArray 来手动解析,但非常繁琐且容易出错。

// 不推荐,仅作了解
try {
    JSONObject jsonObject = new JSONObject(responseString);
    String name = jsonObject.getString("name");
    int id = jsonObject.getInt("id");
    // ...
} catch (JSONException e) {
    e.printStackTrace();
}

使用 Gson / Moshi 自动解析

这是推荐的方式,你只需要创建一个与 JSON 结构匹配的数据类(Kotlin)或 POJO(Java),然后库会自动将 JSON 字符串转换成对象。

使用 Gson (配合 Retrofit 或 OkHttp)

  1. 添加依赖 (前面已添加)
  2. 定义数据类 (前面已定义 User.kt)
  3. 转换
    • Retrofit: 自动完成,只需在 Retrofit.Builder 中添加 addConverterFactory(GsonConverterFactory.create())
    • OkHttp: 手动调用
      val gson = Gson()
      val user = gson.fromJson(responseBody, User::class.java)

最佳实践与总结

特性 HttpURLConnection OkHttp Retrofit
易用性
功能 基础 强大 (拦截器, 缓存, WebSocket) 极强 (基于接口, 类型安全)
性能 一般 优秀 (连接池) 优秀 (底层 OkHttp)
依赖 1 个 (OkHttp) 2-3 个 (Retrofit, OkHttp, 解析器)
适用场景 简单 demo, 不想引入第三方库 大多数网络请求, 特别是需要高级功能时 复杂 API, 大型项目, 追求代码整洁和类型安全

最终建议

  • 对于初学者或简单项目: 可以从 HttpURLConnection 开始,了解基本原理,但实际项目中,强烈建议直接学习 OkHttp
  • 对于绝大多数 Android 项目: OkHttp + Kotlin 协程 是黄金组合,它提供了强大的功能和简洁的异步代码。
  • 对于企业级应用或复杂 API: Retrofit + OkHttp + Kotlin 协程 是行业标准,它能极大地提升代码的可读性、可维护性和健壮性。

其他重要考虑

  • 错误处理: 总是检查 HTTP 状态码 (如 200, 404, 500) 和网络异常(如 SocketTimeoutException, UnknownHostException)。
  • 数据解析: 对于复杂的 JSON,Moshi 通常比 Gson 性能更好,并且与 Kotlin 的集成更无缝。
  • 安全性: 始终使用 HTTPS,并妥善处理证书。
  • 日志: 使用 HttpLoggingInterceptor (OkHttp) 来调试你的网络请求和响应,非常方便。
分享:
扫描分享到社交APP
上一篇
下一篇