Android Studio中使用SSLContext时出现NetworkOnMainThreadException
问题描述
我正在开发一款需连接WebService的安卓App,最初使用HTTP协议时运行正常。后为改用HTTPS,我为WebService生成了证书,在Postman中测试HTTPS请求无问题。我在Manifest中配置了networkSecurityConfig,添加了network_security_config.xml及server_certificate.crt证书,并在代码中为OkHttpClient添加了SSLSocketFactory和信任管理器。现在请求能正常调用WebService并获取结果,但在执行final String myResponse = response.body().string();时出现NetworkOnMainThreadException,使用HTTP时无此异常,恢复之前的配置后异常消失。目前我修改了StrictMode的线程策略,问题暂时解决,但认为这并非最佳实践。请问为何改用SSLContext后会出现该异常?为何HTTP请求时不会触发?
问题分析与解答
异常触发的核心原因
你始终在主线程执行网络请求,HTTP场景下没触发异常只是StrictMode的检测机制没捕捉到而已:
- StrictMode对主线程网络操作的检测并非100%覆盖所有场景,比如短平快的HTTP请求可能因为耗时极短,刚好躲过检测;
- HTTPS请求多了SSL握手、证书校验等额外耗时步骤,整体请求时长被拉长,StrictMode更容易检测到主线程的网络操作,从而抛出异常。
- 说白了,HTTP请求本身也违反了安卓线程规范,只是问题被隐藏了,HTTPS只是让这个潜在问题暴露出来,SSL配置本身没有直接导致线程异常。
正确的解决方式(替代修改StrictMode)
修改StrictMode属于饮鸩止渴,会埋下ANR(应用无响应)的隐患,正确做法是把所有网络操作移到子线程执行:
- 推荐用协程(Kotlin)、RxJava这类异步框架,或者Java的
AsyncTask、普通Thread,示例(Kotlin协程):// 在Activity/Fragment中绑定生命周期启动协程 lifecycleScope.launch { withContext(Dispatchers.IO) { // 此处执行所有网络相关逻辑,包括response.body().string() val okHttpClient = OkHttpClient.Builder() // 你的SSL配置代码 .build() val request = Request.Builder().url("你的HTTPS接口地址").build() val response = okHttpClient.newCall(request).execute() val myResponse = response.body()?.string() ?: "" // 拿到结果后切回主线程更新UI withContext(Dispatchers.Main) { // 处理UI更新逻辑 } } } - 如果是Java项目,可通过
new Thread()执行网络请求,完成后调用runOnUiThread()更新UI。
内容的提问来源于stack exchange,提问作者A Brink
相关产品推荐
相关产品推荐

