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分钟内定位问题:

网络权限配置不当崩溃排查树 网络权限配置不当 缺少INTERNET权限 缺少网络状态权限 网络安全配置错误 权限声明位置错误 网络请求被拦截 (SocketException) 明文流量被阻止 (CLEARTEXT error) 权限声明异常 (获取失败) 应用启动初始化崩溃 正确配置权限声明 + 网络安全策略 💡 排查建议:先看日志关键词 再对应检查Manifest和网络安全配置

我的排查习惯:遇到崩溃先看logcat,搜"Permission"或"CLEARTEXT",定位到具体类型后,直接去AndroidManifest.xml和network_security_config.xml做对应检查。80%的问题5分钟内能解决。

4.4 归纳总结

说了这么多,其实核心就一句话:网络权限配置是OkHttp启动崩溃的头号杀手,但也是最容易避免的。只要你在项目初始化时做好下面三件事,基本就能彻底杜绝这类问题。

  1. 清单文件权限声明——INTERNET和ACCESS_NETWORK_STATE一个都不能少,而且必须放在<manifest>的直接子节点下。
  2. 网络安全策略配置——如果App需要访问HTTP明文站点,提前配好network_security_config.xml,别等到线上崩了才补。
  3. 权限检查兜底——在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都管用。