AdnroidP OKHTTP3: CLEARTEXT communication to host not permitted by network security policy

文章解析了OKHTTP3在网络连接过程中对于明文流量请求的处理方式,并提供了三种解决方案:降低targetSdkVersion版本至27、切换为HTTPS请求及在AndroidManifest.xml中配置usesCleartextTraffic。

1)报错原因:

OKHTTP3 在网络连接时对明文流量的网络请求进行了判断.

在RealConntect类中的方法connect中有这样的判断代码:
 

if (!Platform.get().isCleartextTrafficPermitted(host)) {
  throw new RouteException(new UnknownServiceException(
      "CLEARTEXT communication to " + host + " not permitted by network security policy"));
}
该判断调用的是OKHTTP框架中的AndroidPlatform中的isCleartextTrafficPermitted()方法:

 @Override public boolean isCleartextTrafficPermitted(String hostname) {
  try {
    Class<?> networkPolicyClass = Class.forName("android.security.NetworkSecurityPolicy");
    Method getInstanceMethod = networkPolicyClass.getMethod("getInstance");
    Object networkSecurityPolicy = getInstanceMethod.invoke(null);
    return api24IsCleartextTrafficPermitted(hostname, networkPolicyClass, networkSecurityPolicy);
  } catch (ClassNotFoundException | NoSuchMethodException e) {
    return super.isCleartextTrafficPermitted(hostname);
  } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
    throw assertionError("unable to determine cleartext support", e);
  }
}

追踪发现:反射调用android系统NetworkSecurityPolicy的isCleartextTrafficPermitted(string host)来取值.
mCleartextTrafficPermitted 在 getDefaultBuilder()中可以看出大于等于Build.VERSION_CODES.P时为false
final boolean cleartextTrafficPermitted = info.targetSdkVersion < Build.VERSION_CODES.P && info.targetSandboxVersion < 2; builder.setCleartextTrafficPermitted(cleartextTrafficPermitted);

2):解决
    1:targetSdkVersion 降级回到 27

    2:改用 https (推荐)

    3:配置xml文件 https://www.cnblogs.com/zdz8207/p/Android-28-http-https.html  (本人未校验)
   

    4: application中添加 android:usesCleartextTraffic="true"
     

在清单配置类 ManifestConfigSource 中: setCleartextTrafficPermitted()对mCleartextTrafficPermitted重新赋值          usesCleartextTraffic.

DefaultConfigSource(boolean usesCleartextTraffic, ApplicationInfo info) {
    mDefaultConfig = NetworkSecurityConfig.getDefaultBuilder(info)
            .setCleartextTrafficPermitted(usesCleartextTraffic)
            .build();
}

     

   

 

 

<think> 我们正在解决的是Java开发Android应用使用OkHttp4时出现的`java.net.UnknownServiceException: CLEARTEXT communication not enabled for client`错误。这个错误通常发生在尝试使用HTTP(而不是HTTPS)进行通信时,而Android系统默认禁止明文传输(即HTTP)。从Android 9(API级别28)开始,默认情况下禁止应用使用明文传输。 解决方案: 1. 如果可能,使用HTTPS代替HTTP(推荐)。 2. 如果必须使用HTTP,则需要在应用的网络安全配置中允许明文传输。 具体步骤: 方法一:在AndroidManifest.xml中配置(针对API 28以下,或API 28及以上但针对特定域名) 在AndroidManifest.xml的<application>标签内添加: android:usesCleartextTraffic="true" 但是,从Android 9开始,即使设置了usesCleartextTraffic,默认情况下也禁止使用明文。因此,我们需要为特定的域名允许明文传输。 方法二:创建网络安全配置文件(针对API 28及以上,推荐) 步骤1:在res/xml目录下创建文件network_security_config.xml(如果不存在则创建该目录和文件) 文件内容如下: <?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">yourdomain.com</domain> <!-- 替换成你的域名,例如:example.com --> </domain-config> </network-security-config> 如果需要允许所有域名使用明文(不推荐,因为不安全): <?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true"> </base-config> </network-security-config> 步骤2:在AndroidManifest.xml的<application>标签中引用这个配置文件: <application ... android:networkSecurityConfig="@xml/network_security_config" ... > 方法三:在AndroidManifest.xml中针对特定域名配置(API 28及以上) 如果不想创建单独的配置文件,也可以在AndroidManifest.xml中直接配置(但不如方法二灵活): 在<application>标签内设置:android:usesCleartextTraffic="true" 同时,在<application>标签内添加: <uses-library android:name="org.apache.http.legacy" android:required="false"/> 但是,这种方法允许所有域名的明文传输,且不推荐。 注意:从Android 9(API级别28)开始,默认阻止明文传输。因此,必须显式允许。 代码示例: 使用OkHttp发起请求的代码不需要修改,只要服务器地址是HTTP的,并且我们已经允许了该域名的明文传输(或允许所有域名),那么就可以正常请求。 但是,如果我们的应用目标是Android 9(Pie)或更高版本,并且使用HTTP,则必须按照上述方法配置。 示例:在network_security_config.xml中允许特定域名(例如:example.com)的明文传输 <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">example.com</domain> </domain-config> 然后,在AndroidManifest.xml中: <application android:networkSecurityConfig="@xml/network_security_config" ... > ... </application> 如果出现这个错误,请检查: 1. 请求的URL是否是HTTP的? 2. 是否已经正确配置了网络安全策略? 另外,注意:在Android 9及以上,即使配置了允许明文传输,如果请求的域不在<domain>标签内,也会失败。 引用说明: 根据引用[1]和引用[2],我们了解到OkHttp是一个用于Android和Java应用的HTTP客户端。在Android平台上,由于安全策略的升级,需要特别处理明文传输。 生成相关问题: </think> ### 解决 `java.net.UnknownServiceException: CLEARTEXT communication not enabled for client` 错误 该错误发生在 Android 9(API 级别 28)及以上版本中,当应用尝试使用 HTTP(非 HTTPS)明文通信时触发。以下是完整解决方案(Java 实现): --- #### **解决方案步骤** ##### 1. **在 `AndroidManifest.xml` 中允许明文通信** ```xml <!-- 方法1:允许整个应用的明文传输 --> <application android:usesCleartextTraffic="true" ... > ``` ```xml <!-- 方法2(推荐):仅允许特定域名的明文传输 --> <application android:networkSecurityConfig="@xml/network_security_config" ...> ``` ##### 2. **创建网络安全配置文件** 在 `res/xml/network_security_config.xml` 中添加: ```xml <network-security-config> <!-- 允许特定域名的HTTP --> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">yourdomain.com</domain> </domain-config> <!-- 允许所有HTTP(不推荐) --> <!-- <base-config cleartextTrafficPermitted="true" /> --> </network-security-config> ``` ##### 3. **OkHttp 客户端配置(Java 代码)** ```java // 创建允许明文通信的自定义Client OkHttpClient createUnsafeClient() { return new OkHttpClient.Builder() .connectionSpecs(Arrays.asList( ConnectionSpec.CLEARTEXT, // 关键:允许HTTP ConnectionSpec.MODERN_TLS )) .build(); } // 使用示例 OkHttpClient client = createUnsafeClient(); Request request = new Request.Builder() .url("http://your-api.com/data") // 注意HTTP协议 .build(); client.newCall(request).enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { // 处理响应 } @Override public void onFailure(Call call, IOException e) { e.printStackTrace(); } }); ``` --- #### **关键原理说明** 1. **Android 9+ 的安全策略** - 默认禁止 HTTP 明文传输(`CLEARTEXT`) - 安全策略由 `Network Security Configuration` 控制[^1] 2. **HTTP 与 HTTPS 识别** ```mermaid graph LR A[URL协议] --> B{http://} B -->|触发异常| C[UnknownServiceException] B -->|需特殊配置| D[允许明文传输] ``` 3. **适用场景优先级** | 方案 | 安全等级 | 推荐场景 | |------|----------|----------| | 域名白名单 | ★★★★ | 生产环境 | | 全局允许明文 | ★★ | 测试/内部环境 | | 强制 HTTPS | ★★★★★ | 所有公开服务 | --- #### **最佳实践建议** 1. **生产环境强制使用 HTTPS** ```java // 自动重定向到HTTPS .url("http://your-api.com") .followSslRedirects(true) // 自动跳转HTTPS ``` 2. **兼容旧版 Android 的策略** ```xml <!-- 兼容Android 7.0以下 --> <uses-library android:name="org.apache.http.legacy" android:required="false"/> ``` 3. **调试模式检测协议** ```java if (BuildConfig.DEBUG) { Log.d("NETWORK", "Using HTTP: " + request.url().isHttps()); } ``` --- #### **引用总结** | 引用 | 关键发现 | |------|----------| | [^1] | Android 构建配置导致安全策略变更 | | [^2][^3] | OkHttp 作为 Android 主流网络库的特性 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值