Android Studio JDBC连接本地MySQL报连接失败异常解决方案
Android模拟器连接本地MySQL失败修复方案
问题现象
开发环境为Android Studio,尝试连接PC本地MySQL数据库时抛出如下错误:
W/System.err: java.sql.SQLNonTransientConnectionException: Could not create connection to database server.
初始JDBC连接代码如下:
conn = DriverManager.getConnection("jdbc:mysql://10.0.2.2:3306/gimnasio","root","");
其中10.0.2.2为Android官方模拟器映射的PC本地回环地址,配置后始终连接失败。尝试改用PHP WebService中转方案时,自定义URL常量配置如下,仍无法正常调用:
public class URLs { public static final String ROOT_URL = "http://webservice.local/index.php"; public static final String USER = "root"; public static final String PASSWORD = ""; }
登录逻辑通过按钮点击触发,相关代码如下:
// set on-click listener btnLogin.setOnClickListener { login(user_mail_text, user_password_text) } private fun login(email:String, password:String) { UserDao().login(email, password) }
UserDao类核心代码:
public boolean login(String email, String password) throws IOException { String sql = "select * from users where email = ? and password = ?"; Connection con = JDBCUtils.getConn(); try {
JDBCUtils类核心代码:
public static Connection getConn() { Connection conn = null; try { conn = DriverManager.getConnection("jdbc:mysql://10.0.2.2:3306/gimnasio","root",""); }catch (Exception exception){ exception.printStackTrace(); } return conn; }
核心问题原因
- 移动端不推荐直接JDBC直连MySQL:该方案需要将数据库账号密码硬编码到APK中,反编译即可直接获取,存在严重安全风险,仅适合本地临时调试。
- 主线程执行网络操作违规:Android 3.0及以上版本禁止在UI主线程发起任何网络请求,直接在点击回调里执行数据库连接/HTTP请求会被系统拦截。
- 基础配置缺失:包括网络权限未声明、MySQL未开放远程访问、防火墙拦截端口、JDBC驱动与MySQL版本不匹配、连接串缺少必要参数、明文HTTP请求被系统拦截、自定义域名无hosts映射等。
可行解决步骤
优先选择WebService中转方案,不要在生产环境使用JDBC直连。
方案1:临时调试用JDBC直连修复
- 声明网络权限:在
AndroidManifest.xml中<application>标签的同级位置添加权限:<uses-permission android:name="android.permission.INTERNET" /> - 配置MySQL远程访问权限:本地登录MySQL执行如下命令,创建允许远程访问的业务账号(不要直接用root账号开启远程访问):
临时关闭PC本地防火墙,或配置防火墙放行3306端口的入站连接。-- MySQL 8.0+版本适用 CREATE USER 'appdebug'@'%' IDENTIFIED BY '自定义调试密码'; GRANT ALL PRIVILEGES ON gimnasio.* TO 'appdebug'@'%'; FLUSH PRIVILEGES; - 匹配JDBC驱动版本:在模块级
build.gradle的dependencies节点添加和本地MySQL版本一致的驱动依赖,比如本地装MySQL 8.0.x就引入对应版本:implementation 'mysql:mysql-connector-java:8.0.33' - 修正JDBC连接串:MySQL 8.0+版本需要补充时区、SSL、公钥检索参数:
// 8.0+版本驱动类为com.mysql.cj.jdbc.Driver,不要用旧的com.mysql.jdbc.Driver conn = DriverManager.getConnection("jdbc:mysql://10.0.2.2:3306/gimnasio?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true","appdebug","自定义调试密码"); - 将所有数据库操作切到子线程执行,操作完成后再切回主线程更新UI,Kotlin中可以直接用内置thread方法:
private fun login(email:String, password:String) { thread { val loginResult = UserDao().login(email, password) runOnUiThread { // 处理登录结果,比如页面跳转、提示弹窗 } } }
方案2:PHP WebService中转方案修复(推荐)
- 先在PC本地验证PHP服务可用性:确保PC浏览器访问
http://127.0.0.1/index.php可以正常返回预期内容,修正URL常量,不要用无映射的自定义.local域名,直接用模拟器可访问的PC地址:public class URLs { public static final String ROOT_URL = "http://10.0.2.2/index.php"; // 不要把数据库账号密码写在移动端代码里,数据库连接逻辑全部放到PHP脚本中处理 } - 解决Android 9+ 明文HTTP请求拦截问题:在
AndroidManifest.xml的<application>标签添加如下属性:<application android:usesCleartextTraffic="true" <!-- 保留原有其他属性不变 --> > - 所有HTTP接口请求同样需要放到子线程执行,推荐用OkHttp、Retrofit等成熟网络框架发起请求,移动端仅负责传入邮箱、密码参数,接收PHP接口返回的登录结果即可,数据库的账号密码仅保存在PHP服务端,不会泄露。
内容的提问来源于stack exchange,提问作者scorpions78
相关产品推荐
相关产品推荐

