Android+XAMPP+MySQL家校互动平台:环境搭建与联调实战
发布时间:2026/9/25 5:59:14来源:尧图网络
简介这是一份面向Android开发学习者与毕业设计/课程设计人员的家校互动平台项目资料基于Android客户端、XAMPP服务端与MySQL数据库实现采用CS架构完成家校通知、成绩查询、互动留言等核心功能适用于相关项目设计及Android与服务端联调场景。压缩包约151.66MB包含Android客户端源代码、XAMPP服务端部署文件、MySQL数据库脚本以及完整设计文档可支撑从环境部署到功能调试的全过程。已有293人学习下载适合正在开展相关项目设计或希望掌握AndroidPHPMySQL技术栈的读者。其中项目源码经测试校正、运行可靠配套文档覆盖需求分析、数据库设计及模块实现思路能帮助读者快速上手项目降低从零搭建与排错的成本。1. 基于AndroidXAMPPMySQL的家校互动平台源码资源到底能不能跑做Android课程设计或者毕业设计很多人卡在同一个地方App界面画出来了但数据从哪来老师的通知怎么推给学生家长怎么查作业这套基于AndroidXAMPPMySQL的家校互动平台正好解决这个数据链路问题。它采用CS架构手机端是独立的Android应用服务端跑在XAMPP的ApachePHP环境里数据落在MySQLAndroid端通过HTTP请求调用PHP接口读写数据库。说白了这就是一个前后端分离的移动应用骨架把登录、消息、作业、通知这类家校场景串成了一条能跑通的业务线。这套资源适合三类人一是做课程设计需要完整可演示项目的学生二是想搞明白Android怎么跟PHP服务端联调的人三是想拿现成源码改造成自己项目的开发者。它最大的价值不是某个算法多高明而是把Android客户端、PHP中间层、MySQL存储三层全部打通附带的文档还能直接当设计说明书的底稿。在下手之前我建议你先把我后面讲的环境搭建、联调顺序、踩坑记录过一遍能省很多时间。2. 先把服务端跑起来XAMPP环境搭建与PHP接口设计这套平台的根基在服务端Android端只是个“壳”数据全靠PHP接口从MySQL里取。所以动手第一步不是打开Android Studio而是先把XAMPP这套环境装好、跑通。2.1 XAMPP安装与Apache端口冲突排查XAMPP这东西就是把Apache、PHP、MySQL、phpMyAdmin打成一个包装完就能在本地拉起一个完整的Web服务环境。到官网下载对应你操作系统的版本Windows装完一般在C:\xamppLinux装完在/opt/lampp。装完启动XAMPP Control Panel按顺序启动Apache和MySQL两个服务。这里有一个超高频的翻车点Apache的80端口被系统或其他程序占用了。最常见的是IIS、Nginx或者某些软件自己带了Web服务。提示启动失败时先点击Apache行的“Logs”打开error.log查看具体端口冲突信息。确认是端口问题后可以改Apache的监听端口。改端口的方式打开C:\xampp\apache\conf\httpd.conf找到Listen 80改成Listen 8080。同时要把httpd-ssl.conf里的Listen 443一并改掉避免HTTPS端口也冲突。这样改完你访问服务端的地址就要带上端口号比如http://192.168.1.100:8080。Android端在模拟器里访问宿主机时地址里也要带上这个改过的端口。MySQL端口默认3306一般不会被占但如果你本机装了独立的MySQL服务XAMPP里的MySQL会启动失败。这种情况下要么停掉本机MySQL服务要么把XAMPP的MySQL改成3307端口在C:\xampp\mysql\bin\my.ini里改port3307。2.2 PHP接口的三层设计入口、业务、返回格式这套资源的PHP接口文件结构上大致分为三类数据库连接文件、业务处理文件、公共返回封装。建议拿到源码后先按这个思路把目录理一遍不要着急去读每一个文件。先说数据库连接典型的写法是一个db.php用mysqli做连接?php // 数据库连接配置 $host localhost; $user root; $pass ; $dbname school_platform; // 连接MySQL $conn new mysqli($host, $user, $pass, $dbname); if ($conn-connect_error) { die(json_encode([code500, msg数据库连接失败])); } // 统一UTF-8防止中文乱码 $conn-set_charset(utf8mb4); ?这段代码里有几个关键点。host用localhost是因为PHP和MySQL跑在同一台机器上属于本地回环连接不走网络协议栈。user和pass默认是root和空密码这是XAMPP安装后的默认值。set_charset(utf8mb4)这行极其关键如果你在Android端查出来的中文是乱码八成是这里没设置字符集或者数据库表的字符集不是utf8mb4。再看一个登录接口的典型实现?php require_once db.php; // 接收Android端POST过来的参数 $username $_POST[username] ?? ; $password $_POST[password] ?? ; if (empty($username) || empty($password)) { echo json_encode([code400, msg参数不能为空]); exit; } // 查询用户 $sql SELECT id, username, role FROM users WHERE username? AND password?; $stmt $conn-prepare($sql); $stmt-bind_param(ss, $username, $password); $stmt-execute(); $result $stmt-get_result(); if ($row $result-fetch_assoc()) { echo json_encode([code200, msg登录成功, data$row]); } else { echo json_encode([code401, msg用户名或密码错误]); } $conn-close(); ?这里必须说明两点。第一prepare预处理是必须的不要用字符串拼接SQL否则SQL注入风险很高。第二password直接存明文是课程设计常见的简化做法但如果你要拿这套东西做真实项目建议改成password_hash和password_verify否则数据库一旦泄露所有账号密码全暴露。返回格式统一是code msg data三段式。code200表示成功400是参数错误401是认证失败500是服务端异常。Android端解析JSON时只需要判断code字段就可以决定弹Toast还是跳转页面不用每个接口单独写一套解析逻辑。2.3 用Postman或浏览器先验证接口写完接口不要急着联调Android端先用浏览器或Postman把接口自测一遍。打开浏览器访问http://localhost:8080/api/login.php如果能返回参数为空的JSON说明Apache和PHP已经正常工作了。然后用Postman模拟POST请求在Body里填usernameteacher01password123456点击Send。看返回结果是不是预期的JSON。这一步的价值在于把网络层问题和服务端逻辑问题隔离开。如果Postman里能通说明服务端没问题后面Android端连不上问题一定在Android端或者网络配置上。注意在Windows的Apache和Linux的Apache下PHP对POST数据的解析没有区别。但如果你用GET方式传参URL里不要出现中文浏览器和App对中文URL的编码方式不一致会出现参数丢失或乱码。3. Android端怎么对接从网络权限到JSON解析服务端接口跑通之后真正的战斗才刚开始。Android端这边需要处理网络权限、子线程访问网络、JSON解析、UI更新这几件事。很多课程设计翻车就翻在这一步HTTP请求写在了主线程一执行就闪退。3.1 网络权限与HTTP明文流量配置Android 6.0API 23以后访问网络需要动态权限Android 9.0API 28以后默认禁止明文HTTP流量。这套家校互动平台用的是http://协议访问XAMPP服务端所以必须做两件事。先在AndroidManifest.xml里加权限声明uses-permission android:nameandroid.permission.INTERNET / uses-permission android:nameandroid.permission.ACCESS_NETWORK_STATE /然后在res/xml/目录下创建一个network_security_config.xml?xml version1.0 encodingutf-8? network-security-config domain-config cleartextTrafficPermittedtrue domain includeSubdomainstrue192.168.1.100/domain domain includeSubdomainstrue10.0.2.2/domain domain includeSubdomainstruelocalhost/domain /domain-config /network-security-config再回到AndroidManifest.xml的application节点里引用它application android:networkSecurityConfigxml/network_security_config android:usesCleartextTraffictrue /application这段配置解决的是一个问题App允许访问非HTTPS的明文地址。domain-config里放的是你服务器IP10.0.2.2是Android模拟器访问宿主机的专用IP192.168.1.100是真机调试时你电脑的局域网IP。如果你只用模拟器调试只需要10.0.2.2就够了如果真机调试必须是你电脑在局域网里的实际IP。3.2 封装一个HttpUtils工具类Android端我不建议每个Activity里都写网络请求代码太散。按这个资源的场景拿一个工具类来做集中封装就够用。下面是基于HttpURLConnection的POST请求封装不依赖第三方库public class HttpUtils { private static final int CONNECT_TIMEOUT 5000; private static final int READ_TIMEOUT 5000; public static String postJson(String urlStr, String jsonBody) { HttpURLConnection conn null; try { URL url new URL(urlStr); conn (HttpURLConnection) url.openConnection(); conn.setRequestMethod(POST); conn.setConnectTimeout(CONNECT_TIMEOUT); conn.setReadTimeout(READ_TIMEOUT); conn.setDoOutput(true); conn.setRequestProperty(Content-Type, application/json;charsetUTF-8); // 写入请求体 OutputStream os conn.getOutputStream(); os.write(jsonBody.getBytes(UTF-8)); os.flush(); os.close(); int responseCode conn.getResponseCode(); if (responseCode 200) { InputStream is conn.getInputStream(); BufferedReader reader new BufferedReader(new InputStreamReader(is, UTF-8)); StringBuilder sb new StringBuilder(); String line; while ((line reader.readLine()) ! null) { sb.append(line); } return sb.toString(); } else { return {\code\: responseCode ,\msg\:\HTTP错误\}; } } catch (Exception e) { e.printStackTrace(); return {\code\:500,\msg\:\网络异常: e.getMessage() \}; } finally { if (conn ! null) { conn.disconnect(); } } } }这个封装里有几个细节值得注意。setConnectTimeout和setReadTimeout都是5秒课程设计场景这个值够用。Content-Type设置为application/json;charsetUTF-8保证中文参数能正确传输。这里我默认传JSON字符串如果你的PHP接口是用$_POST[username]接收参数的就要做改造PHP端用file_get_contents(php://input)读原始请求体再json_decode或者Android端用application/x-www-form-urlencoded传键值对。两个技术方案按源码里写的来选择。注意如果你发现PHP端$_POST拿到的是空数组基本上是Content-Type不匹配。PHP的$_POST只认表单格式的请求体不认JSON字符串。这是新手最容易踩的深坑。3.3 子线程请求与UI刷新Android不允许在主线程执行网络请求否则会抛NetworkOnMainThreadException。所以网络请求必须放到子线程拿回结果后再切回主线程更新UI。new Thread(new Runnable() { Override public void run() { String url http://10.0.2.2:8080/api/login.php; String json {\username\:\teacher01\,\password\:\123456\}; String result HttpUtils.postJson(url, json); runOnUiThread(new Runnable() { Override public void run() { try { JSONObject obj new JSONObject(result); int code obj.getInt(code); if (code 200) { // 登录成功跳转主界面 Toast.makeText(MainActivity.this, 登录成功, Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, obj.getString(msg), Toast.LENGTH_SHORT).show(); } } catch (JSONException e) { e.printStackTrace(); } } }); } }).start();这种写法在课程设计里很常见但有个致命问题Activity销毁后如果线程还在跑runOnUiThread里的代码操作了一个不存在的界面就会崩溃。更严谨的做法是用AsyncTask、Handler或者现在主流的ViewModel LiveData做生命周期感知。但如果你是拿这套源码交作业保持原有封装结构只在界面退出时用一个标志位控制UI更新就可以。private boolean isDestroyed false; Override protected void onDestroy() { super.onDestroy(); isDestroyed true; } // 在runOnUiThread的回调里先行判断 runOnUiThread(new Runnable() { Override public void run() { if (!isDestroyed) { // 更新UI操作 } } });这个isDestroyed标志位是线程安全问题的妥协方案不算完美但足够应对课程设计场景。它解决了Activity销毁后回调还在执行的问题也是我见过很多项目里实际在用的处理方式。3.4 解析JSON时注意嵌套结构服务端返回的JSON结构是{code, msg, data}三层。有的接口data是一个对象比如用户信息有的接口data是一个数组比如通知列表。解析方式要区分开// data为对象的解析 JSONObject data obj.getJSONObject(data); String username data.getString(username); String role data.getString(role); // data为数组的解析 JSONArray array obj.getJSONArray(data); for (int i 0; i array.length(); i) { JSONObject item array.getJSONObject(i); String title item.getString(title); String time item.getString(create_time); }这里最容易出的问题是在getString的时候抛JSONException原因是PHP端某个字段返回了null而Android端这里按字符串处理。PHP端返回数据前统一做一次空值处理比较稳妥比如$row[title] ?? 保证每个字段至少是空字符串而不是null。4. 家校业务核心数据库表设计与数据流梳理要说这套家校互动平台的核心价值不在于Android端代码写得多花哨而在于数据库表设计是否匹配真实家校场景。拿到源码后先别急着跑把数据库的表结构和关联关系理清楚后面改功能、加模块就顺手了。4.1 用户角色与权限设计家校互动平台至少有三种角色管理员、教师、家长或学生。在数据库设计里最常见的方式是单表加角色字段而不是拆成三张用户表。这样做的好处是登录逻辑简单坏处是可扩展性差。这个源码的场景单表是合理的选择。CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL, real_name VARCHAR(50) NOT NULL, role TINYINT NOT NULL DEFAULT 2 COMMENT 0管理员,1教师,2家长, phone VARCHAR(20), create_time DATETIME DEFAULT CURRENT_TIMESTAMP );role字段用TINYINT存数字比字符串更省空间查询效率也高。Android端拿到用户信息后根据role值切换主界面。比如教师端看到的是发布作业和发通知的入口家长端看到的是查看作业和接收通知的入口这是家校平台的基本逻辑。4.2 核心业务表作业、通知、消息一个完整可演示的家校平台作业、通知、消息这三张表是必备的。这三张表撑起了整个App的数据来源。-- 作业表 CREATE TABLE homework ( id INT AUTO_INCREMENT PRIMARY KEY, teacher_id INT NOT NULL, title VARCHAR(100) NOT NULL, content TEXT, deadline DATETIME, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (teacher_id) REFERENCES users(id) ); -- 通知表 CREATE TABLE notice ( id INT AUTO_INCREMENT PRIMARY KEY, publisher_id INT NOT NULL, title VARCHAR(100) NOT NULL, content TEXT, notice_type TINYINT DEFAULT 0 COMMENT 0班级通知,1学校通知, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (publisher_id) REFERENCES users(id) ); -- 消息表 CREATE TABLE message ( id INT AUTO_INCREMENT PRIMARY KEY, from_id INT NOT NULL, to_id INT NOT NULL, content TEXT, is_read TINYINT DEFAULT 0 COMMENT 0未读,1已读, create_time DATETIME DEFAULT CURRENT_TIMESTAMP );三张表设计上的共性是都记录了操作者ID、内容、时间以及一个状态字段。FOREIGN KEY做外键约束保证了数据完整性。但这套源码在PHP删除用户时可能会因为外键约束导致失败所以你如果改到用户删除功能要先处理关联表的级联删除逻辑。作业表里有一个容易被忽略的设计点没有设计“提交作业”相关的表。也就是说教师可以发布作业但家长/学生能不能拍照上传提交要看源码里是否单独做了提交表。如果没有这个平台的重点更偏向通知和信息展示作业提交只是单向发布。4.3 从数据库到Android端的完整数据流本位来把一次数据请求的全链路串一遍。教师在Android端填写作业标题、内容、截止时间点“发布”。这条请求走的路径是Android端的Activity收集表单数据打包成JSON通过HttpUtils发送POST请求到PHP的homework_add.phpPHP脚本接收JSONjson_decode后拼接参数通过预处理方式insert到homework表成功后返回code200Android端Toast显示“发布成功”。家长端拉取作业列表时流程刚好反过来Android端发起GET请求到homework_list.phpPHP查询homework表中最新的20条记录把结果集转成JSON数组塞进data字段返回Android端解析JSON数组填充到RecyclerView里。在联调阶段我会用一个土办法验证完整链路先手动往MySQL里插一条记录然后用浏览器直接访问PHP接口看返回JSON最后Android端再请求同一个接口。三步下来哪一环出问题一目了然。建议拿到源码后先重置数据库结构再改密码。XAMPP默认的MySQL密码为空如果你之前设过密码要在db.php里同步修改否则所有接口返回数据库连接失败。5. 联调血泪史六个必踩的坑与解决记录我拿到这套源码环境的时候本以为装个XAMPP、拉个Android Studio就能跑结果陆陆续续折腾了大半天。下面这些坑每一个都是我实际踩过的按“现象、原因、解决”写清楚你照着排雷就行。5.1 模拟器连不上宿主机10.0.2.2变成连接失败现象Android模拟器里访问http://localhost:8080/api/login.php一直报连接超时或拒绝连接。原因模拟器里的localhost是模拟器自己不是你的电脑。模拟器访问宿主机有专有IPlocalhost指代整个模拟器系统10.0.2.2才是宿主机的一个别名。解决把Android端所有请求地址里的localhost改成10.0.2.2。例如http://10.0.2.2:8080/api/login.php。同时在network_security_config.xml里要放行10.0.2.2这个域名的明文流量。改完记得清掉App的缓存再重新运行不然旧的连接缓存还会干扰。5.2 真机调试连接不上地址和WIFI环境双重限制现象手机和电脑连同一个WiFiAndroid端请求http://192.168.1.100:8080超时或者偶尔能通偶尔超时。原因这有两层问题。第一层IP地址必须是电脑在当前局域网的实际IP可以在CMD里输ipconfigWindows或ifconfigMac/Linux查。第二层XAMPP的Apache默认可能只监听了localhost没有监听局域网IP。解决在C:\xampp\apache\conf\httpd.conf里找到Listen相关配置确认Apache监听的是0.0.0.0:8080或80而不是127.0.0.1。同时Windows防火墙会拦截入站请求需要在“允许应用通过防火墙”里放行Apache进程或者临时关闭防火墙测试。5.3 Android 9及以上HTTP明文被拦截现象App请求不报错但Logcat里能看到CLEARTEXT communication to ... not permitted by network security policy之类异常返回结果是null或异常。原因Android 9API 28开始默认禁止应用使用明文HTTP流量这是系统级安全策略不配置就直接拦截。解决按我第3章写的方式在AndroidManifest.xml里声明usesCleartextTraffictrue或者配置networkSecurityConfig定向放行。两者取其一即可不建议两个都放保持最小配置。5.4 PHP端收不到POST参数现象Android端明明传了JSON字符串PHP端$_POST打印出来是空数组。原因PHP的$_POST只识别application/x-www-form-urlencoded或multipart/form-data格式的请求体。Android端设置Content-Type: application/json传JSON字符串PHP自然取不到。解决两个方案择一。方案APHP端不用$_POST改用$data json_decode(file_get_contents(php://input), true);读原始请求体。方案BAndroid端把Content-Type改回application/x-www-form-urlencoded用usernameteacher01password123456这种键值对格式传参。看源码用的是哪种保持一致。这也是最容易被忽视的“前后端不联通”原因。5.5 中文乱码从MySQL到Android端全线排查现象数据库里中文是正常的但App ListView/RecyclerView里显示的是一串问号或者PHP返回的JSON中文变成了乱码。原因字符集不一致的链路传递问题。MySQL表字符集不是utf8mb4或PHP连接没设UTF-8或Android读取InputStream时没用UTF-8解码三处只要有一处不对中文就乱。解决逐层排查。MySQL建表时执行CREATE TABLE ... DEFAULT CHARSETutf8mb4PHP连接后立即$conn-set_charset(utf8mb4)Android端在new InputStreamReader(is, UTF-8)里显式指定UTF-8。三处全对了中文就不会乱。5.6 RecyclerView列表不显示数据但接口返回正常现象用Postman请求接口有JSON返回App里列表却是空的Logcat也没异常。原因大多数情况是解析data字段时类型判断错了。服务端返回的data是数组Android端用getJSONObject去取抛了异常被catch吞掉界面停留在初始状态。解决先在代码里加自定义Log在catch处打一份e.toString()把异常暴露出来。然后确认JSON结构{code:200,data:[...]}对应getJSONArray{code:200,data:{...}}对应getJSONObject。还有就是注意data是null的情况PHP端查不到记录时不要json_encode(null)要返回空数组json_encode([])。注意把这些坑全部踩过一遍之后我才意识到联调顺序的重要性。先浏览器后App先本机后真机先单个接口后全流程这个顺序能帮你过滤掉大部分低级错误。6. 验证、改造与上线前的进阶习惯项目能跑通不等于可以交差。如果说前面几章解决的是“从零到一”这一章就是把“能跑”提升到“能演示、能答辩、能上线”的思路和方法。先说验证方法。整个平台跑通以后不要只看“登录成功”就完事系统性地把核心链路走一遍用不同角色登录确认权限裁剪生效教师发布一条作业家长端刷新能看到发一条通知确认消息列表时间排序正确尝试提交一个空的表单看服务端是否正确返回参数错误。每次操作完看一眼MySQL里的记录确认状态字段正确。这套验证流程做完你才能说这个项目是真正可使用的。再谈改造方向。如果你想把这套源码做出差异化最简单的切入点是加一个“作业提交”功能。在homework表旁边加一张homework_submit表字段设计为CREATE TABLE homework_submit ( id INT AUTO_INCREMENT PRIMARY KEY, homework_id INT NOT NULL, student_id INT NOT NULL, submit_time DATETIME DEFAULT CURRENT_TIMESTAMP, image_path VARCHAR(255) COMMENT 提交图片地址, status TINYINT DEFAULT 0 COMMENT 0未批改,1已批改, score DECIMAL(5,2), comment TEXT, FOREIGN KEY (homework_id) REFERENCES homework(id), FOREIGN KEY (student_id) REFERENCES users(id) );然后写一个submit_add.php接收图片上传一个submit_list.php供教师端查看。这样就补齐了家校互动里家长最在意的“作业闭环”场景功能上比原来的单向通知完善很多。最后一个进阶习惯是关于数据上报和构建的。我发现课程设计项目里最容易被忽略的就是签名和网络配置。无论你后面用APK打包还是别的分发方式用正式签名打包是基本要求不要用debug签名直接交演示包。签名生成的命令在Android Studio里操作是 Build → Generate Signed App Bundle/APK按向导选Create New填好证书路径、密码、别名后面打包都统一用这一个keystore。如果你要走命令行打包可以用keytool -genkey -v -keystore my-release.jks -keyalg RSA -keysize 2048 -validity 10000 -alias myalias这个命令生成一个有效期约27年的签名文件keyalg RSA和keysize 2048是当前默认安全等级。后面打包的时候命令行里指定签名信息就行。从那以后我每次拿到一个源码项目都强制自己先过一遍“环境默认值、网络配置、字符集、签名状态”这四件事再开始改代码。这四件事决定了项目能不能在别人的电脑上复现、能不能演示、能不能过审。这套Android家校互动平台大概率也会遇到类似的问题你按这个顺序排查最早晚上之前就能把App跑起来。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网