You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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地址
  • 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 21:39:52