Android应用连接MySQL数据库失败:通信链路故障排查求助
Android Studio连接MySQL数据库出现连接拒绝错误的解决方案
错误日志
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. W com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure W W The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. W at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174) W at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64) W at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:815) W at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:438) W at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:241) W at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:189) W at java.sql.DriverManager.getConnection(DriverManager.java:580) W at java.sql.DriverManager.getConnection(DriverManager.java:218) W at com.example.drivingschool.DatabaseHandler.getDbConnection(DatabaseHandler.java:18) W at com.example.drivingschool.DatabaseHandler.getUser(DatabaseHandler.java:35) W at com.example.drivingschool.MainActivity$LoginTask.doInBackground(MainActivity.java:98) W at com.example.drivingschool.MainActivity$LoginTask.doInBackground(MainActivity.java:87) W at android.os.AsyncTask$3.call(AsyncTask.java:394) W at java.util.concurrent.FutureTask.run(FutureTask.java:264) W at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305) W at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) W at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644) W at java.lang.Thread.run(Thread.java:1012) W Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure W W The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. W at java.lang.reflect.Constructor.newInstance0(Native Method) W at java.lang.reflect.Constructor.newInstance(Constructor.java:343) W at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61) W at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:104) W at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:149) W at com.mysql.cj.exceptions.ExceptionFactory.createCommunicationsException(ExceptionFactory.java:165) W at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:88) W at com.mysql.cj.NativeSession.connect(NativeSession.java:120) W at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:935) W at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:805) W ... 15 more W Caused by: java.net.ConnectException: failed to connect to localhost/127.0.0.1 (port 3306) from /:: (port 51300): connect failed: ECONNREFUSED (Connection refused) W at libcore.io.IoBridge.connect(IoBridge.java:187) W at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:142) W at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:390) W at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230) W at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212) W at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436) W at java.net.Socket.connect(Socket.java:646) W at com.mysql.cj.protocol.StandardSocketFactory.connect(StandardSocketFactory.java:153) W at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:62) W ... 18 more W Caused by: android.system.ErrnoException: connect failed: ECONNREFUSED (Connection refused) W at libcore.io.Linux.connect(Native Method) W at libcore.io.ForwardingOs.connect(ForwardingOs.java:201) W at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:158) W at libcore.io.ForwardingOs.connect(ForwardingOs.java:201) W at libcore.io.IoBridge.connectErrno(IoBridge.java:201) W at libcore.io.IoBridge.connect(IoBridge.java:179) W ... 26 more
连接配置类
public class config { protected String dbHost = "localhost"; protected String dbPort = "3306"; protected String dbUser = "root"; protected String dbPass = "****"; protected String dbName = "drivingschooldb"; }
DatabaseHandler类
package com.example.drivingschool; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.ResultSet; public class DatabaseHandler extends config{ Connection dbConnection; public Connection getDbConnection() throws ClassNotFoundException, SQLException { String connectionString = "jdbc:mysql://" + dbHost + ":" + dbPort + "/" + dbName; Class.forName("com.mysql.cj.jdbc.Driver"); try { dbConnection = DriverManager.getConnection(connectionString, dbUser, dbPass); System.out.println("Подключение к базе данных успешно установлено"); } catch (SQLException e) { System.out.println("Ошибка при подключении к базе данных: " + e.getMessage()); throw e; } return dbConnection; } //登录应用 public ResultSet getUser(User user) { ResultSet resSet = null; String select = "SELECT * FROM " + constant.USER_TABLE + " WHERE " + constant.USERS_LOGIN + "=? AND " + constant.USERS_PASSWORD + "=?"; try { PreparedStatement prSt = getDbConnection().prepareStatement(select); prSt.setString(1, user.getLogin()); prSt.setString(2, user.getPassword()); resSet = prSt.executeQuery(); } catch (SQLException | ClassNotFoundException e) { e.printStackTrace(); } finally { if (dbConnection != null) { try { dbConnection.close(); } catch (SQLException e) { e.printStackTrace(); } } } return resSet; } }
MainActivity中的LoginTask代码
// 用于在后台执行网络操作的类 class LoginTask extends AsyncTask<String, Void, Boolean> { private Exception exception; protected Boolean doInBackground(String... params) { // 从参数中获取用户名和密码 String username = params[0]; String password = params[1]; // 尝试通过数据库验证登录 try { DatabaseHandler dbHandler = new DatabaseHandler(); // 创建DatabaseHandler实例 ResultSet resSet = dbHandler.getUser(new User(username, password)); // 调用getUser方法验证 if (resSet != null && resSet.next()) { // 登录成功 return true; } else { // 凭据无效 return false; } } catch (SQLException e) { this.exception = e; return false; } } protected void onPostExecute(Boolean result) { // 后台任务完成后在主线程执行 if (result) { // 登录成功 Toast.makeText(MainActivity.this, "Авторизация успешна!", Toast.LENGTH_SHORT).show(); // 创建跳转至新页面的Intent Intent intent = new Intent(MainActivity.this, SecondActivity.class); // 启动Intent startActivity(intent); finish(); // 结束当前Activity } else { if (this.exception != null) { // 数据库异常 Toast.makeText(MainActivity.this, "Ошибка базы данных: " + this.exception.getMessage(), Toast.LENGTH_SHORT).show(); } else { // 登录凭据错误 Toast.makeText(MainActivity.this, "Неверный логин или пароль" , Toast.LENGTH_SHORT).show(); } } } }
已尝试操作
- 修改my.ini中的bind-address为本地IPv4地址和0.0.0.0
- 关闭防火墙
- 使用DB Navigator插件通过相同链接可正常连接数据库
问题根源
核心问题是Android设备/模拟器中的localhost指向设备自身,而非运行MySQL的电脑。电脑上的DB Navigator能连接是因为localhost指代电脑本身,但Android应用里的localhost指向手机/模拟器,而设备上没有运行MySQL服务,因此触发连接拒绝错误。
解决方法
1. 替换localhost为电脑的局域网IP地址
- 查找电脑的IPv4地址:
- Windows:执行
ipconfig命令,找到对应网络接口下的IPv4地址 - Linux/macOS:执行
ifconfig或ip addr命令,找到对应网络接口的IPv4地址
- Windows:执行
- 修改
config类中的dbHost:protected String dbHost = "192.168.x.x"; // 替换为你的电脑局域网IP
2. 授权MySQL用户远程访问
默认root用户通常仅允许本地登录,需授权远程连接权限:
在MySQL终端执行以下命令:
CREATE USER 'root'@'%' IDENTIFIED BY '你的数据库密码'; GRANT ALL PRIVILEGES ON drivingschooldb.* TO 'root'@'%'; FLUSH PRIVILEGES;
注:
%表示允许所有IP连接,生产环境建议限制为指定IP,测试环境可临时使用。
3. 模拟器特殊映射(仅适用于Android Studio自带模拟器)
若使用Android Studio模拟器,可使用10.0.2.2作为电脑localhost的映射地址,修改dbHost为该地址即可:
protected String dbHost = "10.0.2.2";
4. 验证网络环境
- 确保Android设备与电脑处于同一局域网(如连接同一WiFi)
- 确认MySQL服务在电脑上正常运行,端口3306未被占用
内容的提问来源于stack exchange,提问作者The Nody
相关产品推荐
相关产品推荐

