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

安卓应用复用Azure数据库连接代码失败,报Network error IOException: Could not create socket

解决安卓Azure数据库连接异常:Network error IOException: Could not create socket

嘿,这个问题我之前帮同事排查过几乎一模一样的情况——登录页正常、其他页面复用代码就炸,大概率不是连接字符串的锅,咱们从几个常见的坑入手:

1. 先排查主线程网络操作问题

安卓从API 11开始就禁止在主线程执行网络请求,登录页能正常工作,很大可能是你在登录页用了异步操作(比如AsyncTask、Coroutine或者RxJava),但其他页面直接把连接代码写在了Activity的onCreate/onResume这些主线程方法里了。

你可以先打开Logcat搜一下NetworkOnMainThreadException,如果能搜到,那就是这个问题没跑了。解决方法很简单,把数据库连接代码移到后台线程:

Kotlin 示例(用Coroutine)

// 在Activity/Fragment里用lifecycleScope确保和生命周期绑定
lifecycleScope.launch(Dispatchers.IO) {
    val username = "你的用户名"
    val password = "你的密码"
    val connectionString = "jdbc:sqlserver://your-server.database.windows.net:1433;databaseName=your-db;user=$username;password=$password;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;"
    
    try {
        DriverManager.getConnection(connectionString).use { conn ->
            // 这里执行数据库操作,比如查询、插入
            withContext(Dispatchers.Main) {
                Toast.makeText(applicationContext, "连接成功!", Toast.LENGTH_SHORT).show()
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
        withContext(Dispatchers.Main) {
            Toast.makeText(applicationContext, "连接失败:${e.message}", Toast.LENGTH_SHORT).show()
        }
    }
}

Java 示例(用AsyncTask)

private class AzureDbConnectTask extends AsyncTask<Void, Void, Boolean> {
    @Override
    protected Boolean doInBackground(Void... voids) {
        String username = "你的用户名";
        String password = "你的密码";
        String connectionString = "jdbc:sqlserver://your-server.database.windows.net:1433;databaseName=your-db;user=" + username + ";password=" + password + ";encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;";
        
        try (Connection conn = DriverManager.getConnection(connectionString)) {
            // 数据库操作逻辑
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    protected void onPostExecute(Boolean success) {
        if (success) {
            Toast.makeText(getApplicationContext(), "连接成功", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(getApplicationContext(), "连接失败", Toast.LENGTH_SHORT).show();
        }
    }
}

// 调用任务
new AzureDbConnectTask().execute();

2. 检查网络权限与明文流量配置

虽然登录页能连,但还是要确认几个点:

  • 你的AndroidManifest.xml里有没有加网络权限?
    <uses-permission android:name="android.permission.INTERNET" />
    
  • 如果你的Azure数据库用的是HTTP(而非HTTPS),Android 9+默认禁止明文流量,需要在application标签里添加:
    android:usesCleartextTraffic="true"
    
    或者更安全的方式,创建res/xml/network_security_config.xml:
    <?xml version="1.0" encoding="utf-8"?>
    <network-security-config>
        <domain-config cleartextTrafficPermitted="true">
            <domain includeSubdomains="true">your-server.database.windows.net</domain>
        </domain-config>
    </network-security-config>
    
    然后在AndroidManifest.xml的application标签关联:
    android:networkSecurityConfig="@xml/network_security_config"
    

3. 确认连接对象的复用逻辑

如果你的登录页创建了数据库连接对象后没有正确关闭,或者其他页面复用的是一个已经失效的连接实例,也会导致创建socket失败。建议每次需要连接数据库时,都重新初始化连接对象,而不是复用旧的(除非你用了连接池)。

比如不要把Connection对象做成全局静态变量,而是每次在后台线程里重新获取:

// 错误示例:全局静态连接,容易失效
public static Connection globalConn;

// 正确示例:每次使用时创建新连接
try (Connection conn = DriverManager.getConnection(connectionString)) {
    // 使用连接
} catch (SQLException e) {
    // 处理异常
}

4. 排除环境/防火墙限制

虽然登录页能连,但也要确认其他页面测试时的网络环境和登录页是否一致:

  • 比如登录页是在Wi-Fi下测试,其他页面用了手机流量?有些公司网络会限制外部数据库连接,换手机热点试试。
  • 检查Azure数据库的防火墙规则,是否允许当前设备的IP访问(不过登录页能连的话,这个概率较低)。

先从线程问题开始排查,这是最常见的原因,大概率能解决你的问题!

内容的提问来源于stack exchange,提问作者George C.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:12:21