4、网络权限配置不当导致的崩溃归纳总结
网络权限配置不当,说实话,是我见过最频繁的OkHttp启动崩溃原因之一。你想想看,一个网络库连最基本的网络权限都没有,它能正常工作吗?我刚开始接触Android开发时,就犯过这个低级错误——清单文件里忘了加INTERNET权限,结果App一启动就崩,查了半天日志才发现问题。
为什么会这样?因为OkHttp在初始化时就会尝试创建Socket连接,如果系统发现缺少必要权限,会直接抛出异常。而且不同Android版本对权限的处理方式还不一样,稍不注意就会踩坑。这一章我就把这类问题掰开揉碎了讲清楚,帮你一次性避开所有雷区。
4.1 常见错误类型概览
根据我在多个项目中的排查经验,网络权限配置不当导致的崩溃,基本逃不出下面这四种类型:
| 错误类型 | 典型崩溃信息 | 影响版本 | 触发时机 |
|---|---|---|---|
| 缺少INTERNET权限 | Permission denied (missing INTERNET permission?) | 所有Android版本 | OkHttp创建连接时立即崩溃 |
| 缺少ACCESS_NETWORK_STATE权限 | NetworkCallback未注册 / 状态获取失败 | Android 6.0+ | 调用网络状态监测API时 |
| 网络安全配置错误 | CLEARTEXT communication to xxx not permitted | Android 9.0+ | 发起HTTP明文请求时 |
| 权限声明位置错误 | IllegalArgumentException: Unknown permission | 所有Android版本 | App启动解析Manifest时 |
4.2 各类型深度解析
类型一:缺少INTERNET权限
这是最基础也最容易犯的错误。我记得有个外包项目,对方把AndroidManifest.xml里的权限声明删了,说是"为了安全"。结果App一上线就开始崩溃,用户疯狂差评。说白了,INTERNET权限是Android应用联网的"入场券",没有它,OkHttp连DNS解析都做不了。
崩溃日志长这样:
java.net.SocketException: Permission denied (missing INTERNET permission?)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:142)
at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.java:68)
嗯,看到这个日志,直接去查Manifest就行。
类型二:缺少ACCESS_NETWORK_STATE权限
这个权限不是必须的,但如果你用了OkHttp的NetworkMonitor或者主动检测网络状态,少了它就会出问题。我在项目中遇到过,同事写了个网络状态监听器,忘了加这个权限,结果在Android 8.0上直接崩溃。为什么会这样?因为系统在回调网络状态变化时,会校验调用方是否有ACCESS_NETWORK_STATE权限。
类型三:网络安全配置错误
Android 9.0开始,系统默认禁止明文HTTP流量。如果你的后端用的是HTTP而不是HTTPS,OkHttp就会直接抛异常。我建议所有新项目都配一下网络安全策略,不然哪天后端切了HTTP你就懵了。
java.net.UnknownServiceException: CLEARTEXT communication to api.example.com not permitted by network security policy
at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:148)
解决方案就是在res/xml/下加一个network_security_config.xml,并在Manifest中引用。
类型四:权限声明位置错误
这种情况比较少见,但一旦遇到很坑。我曾经见过有人在<application>节点内部声明权限,结果Android系统直接忽略,运行时拿不到任何权限。权限声明必须放在<manifest>的直接子节点下,位置错了系统不报错,但权限就是无效。
4.3 系统化排查方案
遇到网络权限相关的崩溃,别慌。我一般按下面这个流程来查,基本5分钟内定位问题:
我的排查习惯:遇到崩溃先看logcat,搜"Permission"或"CLEARTEXT",定位到具体类型后,直接去AndroidManifest.xml和network_security_config.xml做对应检查。80%的问题5分钟内能解决。
4.4 归纳总结
说了这么多,其实核心就一句话:网络权限配置是OkHttp启动崩溃的头号杀手,但也是最容易避免的。只要你在项目初始化时做好下面三件事,基本就能彻底杜绝这类问题。
- 清单文件权限声明——INTERNET和ACCESS_NETWORK_STATE一个都不能少,而且必须放在<manifest>的直接子节点下。
- 网络安全策略配置——如果App需要访问HTTP明文站点,提前配好network_security_config.xml,别等到线上崩了才补。
- 权限检查兜底——在OkHttp初始化之前,用代码判断一下权限是否正常,异常时主动提示而不是直接崩溃。
下面是一个完整的、经过线上验证的AndroidManifest.xml配置模板,你可以直接拿去用:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">
<!-- 必须放在 manifest 的直接子节点下 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:networkSecurityConfig="@xml/network_security_config"
...>
...
</application>
</manifest>
对应的 res/xml/network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
⚠️ 曾经踩过的坑:我曾经在线上项目里把<uses-permission>不小心写到了<application>节点内部,结果所有Android 9.0以下的设备都正常,唯独Android 10以上疯狂崩溃。查了整整两天才发现是权限声明位置不对。这个坑,你们千万别再踩了。
最后说一句:网络权限问题说白了就是"配没配"和"配没配对"的事。每次新建项目或者升级targetSdkVersion时,都把上面这个模板拿出来核对一遍,比出任何Bug都管用。