凌峰创科服务平台

android php 服务器端

目录

  1. 核心概念:为什么需要服务器?
  2. 通信协议:HTTP/HTTPS
  3. 数据交换格式:JSON vs. XML
  4. Android 客户端实现
    • 原生 HttpURLConnection (Java)
    • 第三方库:Volley, Retrofit, OkHttp
  5. PHP 服务器端实现
    • 环境准备
    • 连接数据库
    • 编写 API 接口
    • 安全性考虑
  6. 完整示例:用户登录
  7. 高级主题与最佳实践

核心概念:为什么需要服务器?

Android 应用(客户端)通常不能直接操作数据库,服务器扮演了中间人的角色,主要职责包括:

android php 服务器端-图1
(图片来源网络,侵删)
  • 数据持久化:将数据存储在服务器端的数据库中。
  • 业务逻辑处理:执行复杂的计算、验证规则等,而不是放在客户端。
  • 安全性:保护敏感数据(如数据库密码、API 密钥),防止客户端直接访问数据库。
  • 跨平台:同一个 API 可以被 Android、iOS、Web 等多个客户端使用。

架构流程: Android App <--(HTTP请求/JSON数据)--> PHP Server <--(SQL查询)--> MySQL Database <--(SQL结果)--> PHP Server <--(HTTP响应/JSON数据)--> Android App


通信协议:HTTP/HTTPS

客户端和服务器之间通过 HTTP (或更安全的 HTTPS) 协议进行通信。

  • HTTP 请求方法

    • GET:请求数据,获取用户列表、获取文章详情,数据通常在 URL 的 Query String 中。
    • POST:提交数据,用户注册、发布新文章,数据通常放在请求体中,更安全,且能传输更大量的数据。
    • PUT / PATCH:更新数据。
    • DELETE:删除数据。
  • HTTPS:强烈建议在生产环境中使用 HTTPS,它通过 SSL/TLS 加密了通信内容,可以防止数据在传输过程中被窃听或篡改。

    android php 服务器端-图2
    (图片来源网络,侵删)

数据交换格式:JSON vs. XML

客户端和服务器交换数据时,需要一种通用的格式。JSON 是绝对的主流

  • JSON (JavaScript Object Notation)

    • 优点:轻量级、易于人阅读和编写、易于机器解析和生成,与 JavaScript 语法天然兼容,在 Android 中可以轻松转换为 JSONObjectJSONArray
    • 示例
      {
        "status": "success",
        "user_id": 123,
        "message": "Login successful"
      }
  • XML (eXtensible Markup Language)

    • 优点:结构严谨,有规范的 DTD 或 Schema。
    • 缺点:冗长、解析比 JSON 复杂,现在已较少用于移动端 API。

除非有特殊遗留系统要求,否则请毫不犹豫地选择 JSON

android php 服务器端-图3
(图片来源网络,侵删)

Android 客户端实现

在 Android 中进行网络请求,不能在主线程(UI线程)中执行,否则会抛出 NetworkOnMainThreadException 异常,必须使用异步任务(如 AsyncTask - 已废弃)、线程 + Handler,或者现代的协程/ExecutorService

原生 HttpURLConnection (不推荐用于新项目,但有助于理解原理)

// 在 Kotlin 中使用协程是现代 Android 开发的最佳实践
// 假设在 ViewModel 或使用 lifecycleScope.launch
fun loginUser(username: String, password: String) {
    // 创建一个线程或使用协程来执行网络请求
    CoroutineScope(Dispatchers.IO).launch {
        val url = URL("https://yourdomain.com/api/login.php")
        val connection = url.openConnection() as HttpURLConnection
        connection.requestMethod = "POST"
        connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
        connection.doOutput = true
        // 构建请求体
        val postData = "username=$username&password=$password"
        // 发送请求
        val outputStream = connection.outputStream
        outputStream.write(postData.toByteArray())
        outputStream.flush()
        // 获取响应
        if (connection.responseCode == HttpURLConnection.HTTP_OK) {
            val inputStream = connection.inputStream
            val response = inputStream.bufferedReader().use { it.readText() }
            // 在主线程更新UI
            withContext(Dispatchers.Main) {
                Log.d("API Response", response)
                // 解析 JSON 并更新UI
            }
        } else {
            // 处理错误
            Log.e("API Error", "HTTP Error: ${connection.responseCode}")
        }
    }
}

第三方库 (强烈推荐)

Retrofit (最流行)

Retrofit 是一个类型安全的 HTTP 客户端,它将 REST API 的调用转换为简单的 Java/Kotlin 接口。

第一步:添加依赖

// build.gradle (Module :app)
dependencies {
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // 用于JSON转换
}

第二步:定义 API 接口

import retrofit2.Call
import retrofit2.http.Field
import retrofit2.http.FormUrlEncoded
import retrofit2.http.POST
interface ApiService {
    @FormUrlEncoded
    @POST("api/login.php")
    fun loginUser(
        @Field("username") username: String,
        @Field("password") password: String
    ): Call<LoginResponse> // Call 是 Retrofit 的包装类
}
// 数据类 (data class) 用于解析 JSON 响应
data class LoginResponse(
    val status: String,
    val user_id: Int,
    val message: String
)

第三步:创建 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()) // 添加Gson转换器
            .build()
        retrofit.create(ApiService::class.java)
    }
}
// 在 Activity/ViewModel 中使用
fun performLogin() {
    val apiService = RetrofitClient.instance
    val call = apiService.loginUser("testuser", "password123")
    call.enqueue(object : Callback<LoginResponse> {
        override fun onResponse(call: Call<LoginResponse>, response: Response<LoginResponse>) {
            if (response.isSuccessful) {
                val loginResponse = response.body()
                if (loginResponse?.status == "success") {
                    // 登录成功,更新UI
                    Log.d("Login", "User ID: ${loginResponse.user_id}")
                }
            } else {
                // 服务器返回了错误码,如 404, 500
                Log.e("Login Error", "Code: ${response.code()}")
            }
        }
        override fun onFailure(call: Call<LoginResponse>, t: Throwable) {
            // 网络请求失败,如无网络、服务器宕机
            Log.e("Network Failure", t.message.toString())
        }
    })
}

优点:代码简洁、类型安全、易于维护,支持 RxJava 和协程。

Volley (适合小型、简单的请求)

Volley 是 Google 推荐的异步网络请求库,适合处理小量的、频繁的网络请求。


PHP 服务器端实现

环境准备

你需要一个支持 PHP 和 MySQL 的 Web 服务器环境,最简单的方式是安装 XAMPP (Windows, Linux, macOS) 或 MAMP (macOS),它们包含了 Apache、MySQL 和 PHP。

连接数据库

创建一个 db_config.php 文件来管理数据库连接信息,不要把密码直接写在代码里

<?php
// db_config.php
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'root');
define('DB_PASSWORD', ''); // XAMPP 默认为空
define('DB_NAME', 'my_app_db');
// 创建连接
$conn = new mysqli(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME);
// 检查连接
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}
?>

编写 API 接口

创建一个 api/login.php 文件,它将处理来自 Android 的请求。

<?php
// api/login.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");
// 包含数据库配置
include_once 'db_config.php';
// 获取 POST 数据
$data = json_decode(file_get_contents("php://input"));
// 检查数据是否存在
if (!empty($data->username) && !empty($data->password)) {
    $username = $data->username;
    $password = $data->password;
    // **重要:使用预处理语句防止 SQL 注入**
    $stmt = $conn->prepare("SELECT id FROM users WHERE username = ? AND password = ?");
    // 在实际应用中,密码应该被哈希存储,例如使用 password_hash()
    // 这里为了简单,直接比较,请勿在生产环境这样做!
    $hashed_password = md5($password); // 注意:md5 不安全,仅作示例
    $stmt->bind_param("ss", $username, $hashed_password);
    $stmt->execute();
    $stmt->store_result();
    if ($stmt->num_rows > 0) {
        // 登录成功
        $stmt->bind_result($user_id);
        $stmt->fetch();
        $response = array(
            "status" => "success",
            "user_id" => $user_id,
            "message" => "Login successful"
        );
    } else {
        // 登录失败
        $response = array(
            "status" => "error",
            "message" => "Invalid username or password"
        );
    }
    $stmt->close();
} else {
    // 数据为空
    $response = array(
        "status" => "error",
        "message" => "Data is incomplete."
    );
}
// 返回 JSON 响应
echo json_encode($response);
$conn->close();
?>

安全性考虑

  1. SQL 注入永远不要将用户输入直接拼接到 SQL 查询中。必须使用预处理语句(如上例所示)。
  2. 密码安全永远不要明文存储密码,使用 password_hash()password_verify() 函数来处理密码。
  3. HTTPS:在生产环境,强制使用 HTTPS。
  4. 输入验证:在 PHP 和 Android 端都要对用户输入进行验证和清理。
  5. CORSheader("Access-Control-Allow-Origin: *"); 方便开发,但生产环境应将其替换为你的 App 域名,如 header("Access-Control-Allow-Origin: https://your-android-app.com");

完整示例:用户登录

流程总结:

  1. Android (Retrofit):

    • 用户在输入框输入用户名和密码,点击登录按钮。
    • performLogin() 方法被调用,Retrofit 将 usernamepassword 作为 @Field 发送到 https://yourdomain.com/api/login.php
    • enqueue 方法异步发送请求,并在回调中处理响应。
    • status"success",就保存 user_id 并跳转到主页,如果是 "error",就显示错误提示。
  2. PHP (api/login.php):

    • 接收到 POST 请求,读取 usernamepassword
    • 使用预处理语句查询数据库。
    • 如果找到匹配的用户,返回 {"status": "success", "user_id": 123, ...}
    • 如果没找到,返回 {"status": "error", "message": "..."}

高级主题与最佳实践

  • 身份验证与授权:登录成功后,服务器应返回一个 Token (如 JWT - JSON Web Token),后续的 API 请求都需要在 Header 中携带这个 Token,以证明用户身份。
  • 分页:当数据量很大时(如新闻列表),使用 LIMITOFFSET 或基于游标的分页来避免一次性加载过多数据。
  • 文件上传:Android 使用 Multipart 请求,PHP 使用 $_FILES 超全局变量来接收上传的文件。
  • 错误处理:定义统一的错误码和错误信息格式,方便客户端统一处理。
  • 日志记录:在服务器端记录 API 请求和错误日志,便于排查问题。

组件 关键技术/概念 推荐工具/实践
Android 客户端 网络请求(不能在主线程)、JSON 解析 Retrofit (首选), OkHttp, Volley
通信协议 HTTP/HTTPS HTTPS (必须)
数据格式 JSON (绝对主流) JSON
PHP 服务器端 处理请求、连接数据库、返回 JSON 预处理语句 (防SQL注入), 密码哈希
数据库 MySQL 使用预处理语句与 PHP 交互

从 Android 调用 PHP API 是一个标准化的过程,掌握好 RetrofitPHP + MySQL + 预处理语句 这套组合,你就能构建出功能强大且安全的移动应用后端服务。

分享:
扫描分享到社交APP
上一篇
下一篇