目录
- 核心原理:HTTP 请求/响应模型
- 技术选型
- Android 端:网络库选择
- 服务器端:PHP 框架选择
- 交互流程详解
- 代码实战
- Android 端 (Kotlin + Retrofit)
- PHP 服务器端 (原生 PHP + PDO)
- 数据格式:JSON
- 安全最佳实践 (至关重要)
- 常见问题与解决方案
核心原理:HTTP 请求/响应模型
Android 和 PHP 服务器之间的所有通信都基于 HTTP (Hypertext Transfer Protocol) 协议,这个过程可以简化为以下几个步骤:

-
Android 客户端:当应用需要数据(获取用户信息)或执行操作(发布一条新动态)时,它会构建一个 HTTP 请求。
- 请求方法:
GET(获取数据),POST(提交数据),PUT(更新数据),DELETE(删除数据)。 - 请求头:包含元数据,如
Content-Type(告诉服务器发送的是什么格式的数据,如application/json)。 - 请求体:对于
POST或PUT请求,这里包含实际要发送的数据(如用户名、密码)。
- 请求方法:
-
网络传输:这个 HTTP 请求通过互联网(通常是 Wi-Fi 或移动数据)发送到你配置好的 PHP 服务器上的一个特定地址(URL)。
-
PHP 服务器端:
- 接收请求:PHP 脚本(
login.php)运行在服务器上,接收来自 Android 客户端的 HTTP 请求。 - 处理逻辑:PHP 脚本解析请求头和请求体,然后执行相应的业务逻辑,连接数据库,验证用户名和密码。
- 生成响应:根据处理结果,PHP 脚本构建一个 HTTP 响应。
- 响应状态码:如
200 OK(成功),404 Not Found(资源未找到),401 Unauthorized(未授权)。 - 响应头:如
Content-Type: application/json。 - 响应体:包含服务器返回给客户端的数据,通常是 JSON 格式的字符串。
- 响应状态码:如
- 接收请求:PHP 脚本(
-
Android 客户端:接收到 PHP 服务器的 HTTP 响应后,应用会解析响应体(JSON 数据),并根据内容更新 UI(登录成功则跳转到主界面,失败则显示错误提示)。
(图片来源网络,侵删)
简而言之:Android 发送请求 -> PHP 接收并处理 -> PHP 发送响应 -> Android 接收并解析。
技术选型
直接使用 HttpURLConnection 是可以的,但非常繁琐,现代开发中,我们更推荐使用封装好的库。
Android 端:网络库选择
| 库名 | 特点 | 推荐度 |
|---|---|---|
| Retrofit | 强烈推荐,由 Square 公司开发,它将 HTTP API 转换为 Java/Kotlin 接口,使用注解定义 API,支持 Gson/Moshi 等自动转换 JSON,代码极其简洁、类型安全、易于维护。 |
⭐⭐⭐⭐⭐ |
| OkHttp | Retrofit 的底层依赖,它是一个高效的 HTTP 客户端,负责处理连接、缓存、超时等,通常我们直接使用 Retrofit,它会自动使用 OkHttp。 | ⭐⭐⭐⭐⭐ |
| Volley | Google 推出的库,优点是请求队列管理、缓存机制简单,但对于复杂的网络请求和文件上传,Retrofit 更灵活。 | ⭐⭐⭐ |
HttpURLConnection |
Android SDK 自带,功能齐全,但代码冗长,需要手动处理线程和解析,不推荐用于新项目。 | ⭐⭐ |
对于新项目,首选 Retrofit + OkHttp + Kotlinx Serialization 或 Gson 的组合。
服务器端:PHP 框架选择
| 框架 | 特点 | 推荐度 |
|---|---|---|
| 原生 PHP | 灵活,轻量级,适合小型项目、学习或 API 开发,需要自己处理数据库连接、路由等。 | ⭐⭐⭐⭐ |
| Laravel | 强烈推荐,功能强大、优雅的 PHP 框架,拥有完善的路由系统、Eloquent ORM(数据库操作)、强大的安全防护机制(如 CSRF 防护),开发效率极高。 | ⭐⭐⭐⭐⭐ |
| Slim | 一个专注于快速开发 RESTful API 的微框架,非常轻量,配置简单,是构建 API 的理想选择。 | ⭐⭐⭐⭐ |
如果只是简单的 API,原生 PHP + PDO 就足够了,如果项目规模较大或追求开发效率,Laravel 是不二之选。

交互流程详解
以一个典型的 用户登录 功能为例:
-
Android 端:
- 用户在输入框中输入用户名和密码,点击“登录”按钮。
- Retrofit 将用户名和密码封装成一个 JSON 对象,如
{"username": "john", "password": "123456"}。 - Retrofit 发送一个
POST请求到https://yourdomain.com/api/login,并将 JSON 数据放在请求体中。
-
PHP 服务器端:
- 服务器接收到请求,路由将请求指向
login.php文件。 login.php读取请求体,解析出username和password。- 使用 PDO (PHP Data Objects) 连接 MySQL 数据库。
- 执行一条
SELECT查询,检查数据库中是否存在该用户名和密码(注意:密码应该是哈希值,而不是明文!)。 - 如果找到匹配的用户:
- 生成一个响应体,
{"status": "success", "user_id": 123, "message": "Login successful"}。 - 设置 HTTP 状态码为
200 OK。
- 生成一个响应体,
- 如果没有找到:
- 生成一个响应体,
{"status": "error", "message": "Invalid username or password"}。 - 设置 HTTP 状态码为
401 Unauthorized。
- 生成一个响应体,
- PHP 将这个 JSON 响应发送回 Android 客户端。
- 服务器接收到请求,路由将请求指向
-
Android 端:
- Retrofit 接收到响应。
- 它会自动将 JSON 字符串解析成一个 Kotlin 数据类(如
LoginResponse)。 - 在回调接口中,我们检查
LoginResponse.status的值。 - 如果是
"success",则跳转到主界面,并保存用户信息(如user_id)。 - 如果是
"error",则在屏幕上显示LoginResponse.message的内容。
代码实战
我们将使用 Android (Kotlin + Retrofit) 和 PHP (原生 + PDO) 来实现一个简单的用户注册功能。
Android 端 (Kotlin + Retrofit)
添加依赖 (build.gradle.kts 或 build.gradle)
// build.gradle (Module :app)
dependencies {
// Retrofit & OkHttp
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0") // 用于 JSON 转换
implementation("com.squareup.okhttp3:logging-interceptor:4.9.3") // 用于打印日志
// Kotlin Coroutines (用于异步处理)
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4")
}
添加网络权限 (AndroidManifest.xml)
<manifest ...>
<uses-permission android:name="android.permission.INTERNET" />
<application ...>
...
</application>
</manifest>
定义数据模型
// 请求的数据模型
data class RegisterRequest(
val username: String,
val email: String,
val password: String
)
// 响应的数据模型
data class RegisterResponse(
val status: String,
val message: String
)
创建 Retrofit 实例和 API 接口
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.Body
import retrofit2.http.POST
// 定义 API 接口
interface ApiService {
@POST("api/register.php") // 你的 PHP 文件路径
suspend fun register(@Body request: RegisterRequest): RegisterResponse
}
// 创建 Retrofit 单例
object RetrofitClient {
private const val BASE_URL = "https://yourdomain.com/" // 你的服务器地址
val instance: ApiService by lazy {
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
retrofit.create(ApiService::class.java)
}
}
在 ViewModel 或 Activity 中调用
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
class RegisterViewModel : ViewModel() {
fun registerUser(username: String, email: String, password: String) {
viewModelScope.launch {
try {
val request = RegisterRequest(username, email, password)
val response = RetrofitClient.instance.register(request)
if (response.status == "success") {
// 注册成功,处理UI逻辑
Log.d("Register", "Success: ${response.message}")
} else {
// 注册失败,处理UI逻辑
Log.e("Register", "Error: ${response.message}")
}
} catch (e: Exception) {
// 网络错误等异常
Log.e("Register", "Exception: ${e.message}")
}
}
}
}
PHP 服务器端 (原生 PHP + PDO)
数据库准备
假设你有一个 users 表:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
api/register.php
<?php
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Origin: *"); // 允许所有来源的请求,生产环境应限制为你的域名
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
// 1. 获取并解码请求体
$data = json_decode(file_get_contents("php://input"));
// 2. 验证数据
if (!isset($data->username) || !isset($data->email) || !isset($data->password)) {
http_response_code(400); // Bad Request
echo json_encode(["status" => "error", "message" => "Missing required fields."]);
exit();
}
$username = $data->username;
$email = $data->email;
$password = $data->password;
// 3. 密码哈希 (非常重要!)
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
// 4. 连接数据库 (使用 PDO)
$servername = "localhost";
$dbname = "your_database_name";
$dbusername = "your_db_username";
$dbpassword = "your_db_password";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $dbusername, $dbpassword);
// 设置 PDO 错误模式为异常
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 5. 准备 SQL 语句 (使用预处理语句防止 SQL 注入)
$sql = "INSERT INTO users (username, email, password) VALUES (:username, :email, :password)";
$stmt = $conn->prepare($sql);
// 绑定参数
$stmt->bindParam(':username', $username);
$stmt->bindParam(':email', $email);
$stmt->bindParam(':password', $hashed_password);
// 执行语句
if ($stmt->execute()) {
// 注册成功
http_response_code(201); // Created
echo json_encode(["status" => "success", "message" => "User registered successfully."]);
} else {
// 注册失败 (例如用户名或邮箱已存在)
http_response_code(500); // Internal Server Error
echo json_encode(["status" => "error", "message" => "Registration failed."]);
}
} catch(PDOException $e) {
// 数据库错误
http_response_code(500);
echo json_encode(["status" => "error", "message" => "Database error: " . $e->getMessage()]);
}
// 关闭连接
$conn = null;
?>
数据格式:JSON
JSON (JavaScript Object Notation) 是目前最主流的数据交换格式,它轻量、易于人阅读和编写,也易于机器解析和生成。
- 结构:键值对的集合,类似于 Java/Kotlin 的 Map 或对象。
- 示例:
{ "status": "success", "user_id": 101, "profile": { "username": "android_dev", "email": "dev@example.com" }, "posts": [ {"id": 1, "title": "Hello World"}, {"id": 2, "title": "My Second Post"} ] }
Retrofit 和 Gson/Moshi 可以完美地将 JSON 字符串自动映射到 Kotlin 的数据类,反之亦然,极大地简化了开发。
安全最佳实践 (至关重要)
不安全的通信会导致用户数据泄露、账户被盗等严重问题。
-
HTTPS (必须使用)
- 是什么:HTTP over SSL/TLS,它在 HTTP 和 TCP 之间加了一层加密,所有传输的数据都是加密的。
- 为什么:防止中间人攻击,防止用户名、密码、个人敏感信息在传输过程中被窃听。
- 怎么做:在你的服务器上配置 SSL 证书(如 Let's Encrypt 提供的免费证书),在 AndroidManifest.xml 中配置
networkSecurityConfig来允许 HTTPS。
-
防止 SQL 注入
- 是什么:攻击者通过在输入字段中注入恶意的 SQL 代码来操纵数据库。
- 怎么做:永远不要将用户输入直接拼接到 SQL 查询中。始终使用预处理语句,就像上面 PHP 代码示例中的
prepare()和bindParam()。
-
密码安全
- 是什么:绝不能以明文存储密码。
- 怎么做:在存储密码之前,使用
password_hash()函数进行哈希处理,在验证密码时,使用password_verify()函数。不要自己实现哈希算法。
-
输入验证
- 是什么:验证来自客户端的输入是否符合预期的格式和范围。
- 怎么做:在 Android 端和 PHP 服务器端都要进行验证,检查邮箱格式、用户名长度、密码强度等,客户端验证是为了提升用户体验,服务器端验证是安全性的最后一道防线。
-
API 密钥和认证
- 是什么:对于需要保护的 API,你需要一种方式来验证请求是否来自合法的 Android 应用。
- 怎么做:
- API Key:在 Android 应用中硬编码一个唯一的密钥,并在每个请求中发送,简单但容易被反编译获取。
- Token (如 JWT - JSON Web Token):更安全的方式,用户登录成功后,服务器生成一个包含用户信息的加密 Token 返回给客户端,客户端后续的请求都在请求头中携带这个 Token,服务器验证 Token 的有效性即可。
常见问题与解决方案
-
问题:Android 10+ (API 29+) 上 HTTP 请求失败。
- 原因:Android 9 开始默认禁止使用非加密的 HTTP 连接。
- 解决方案:强制使用 HTTPS,如果必须使用 HTTP(仅限本地开发),需要在
AndroidManifest.xml中配置usesCleartextTraffic为true,并配置networkSecurityConfig。
-
问题:
android.os.NetworkOnMainThreadException。- 原因:在主线程(UI 线程)上执行了网络操作,这会阻塞 UI 并可能导致应用“无响应”(ANR)。
- 解决方案:永远不要在主线程上进行网络请求,使用
AsyncTask(已过时)、Thread+Handler,或者更现代的 Kotlin Coroutines 或 RxJava,Retrofit 本身就支持在协程中调用,非常方便。
-
问题:PHP 服务器返回
404 Not Found。- 原因:URL 路径错误,或者 PHP 文件不在指定位置。
- 解决方案:仔细检查 Retrofit 中的
@POST("api/register.php")中的路径是否与服务器上的文件路径完全匹配。
-
问题:JSON 解析失败。
- 原因:服务器返回的 JSON 格式与 Kotlin 数据类的结构不匹配,或者服务器返回了 HTML 错误页面(如 500 错误时的 Nginx/Apache 默认页面)。
- 解决方案:
- 使用 OkHttp 的
Interceptor打印服务器返回的原始响应内容,看看到底是什么。 - 使用在线 JSON 校验工具检查你的 JSON 是否格式正确。
- 确保 Kotlin 数据类的字段名和 JSON 的键名完全一致(或使用
@SerializedName("json_key")注解)。
- 使用 OkHttp 的
希望这份详细的指南能帮助你顺利实现 Android 与 PHP 服务器的交互!祝你编码愉快!
