解决安卓OkHttp报错UnknownServiceException CLEARTEXT communication to not permitted by network security

文章介绍了在Android开发中遇到的由于使用OkHttp进行明文HTTP请求而被系统禁止的问题,原因是Android的安全策略不允许明文通信。解决方案包括切换到HTTPS协议,或者在AndroidManifest.xml中设置usesCleartextTraffic为true,以及使用网络安全性配置文件进行细粒度控制。同时,文章提醒开发者需考虑安全性和网络权限设置。
摘要由CSDN通过智能技术生成

笔者报错时的运行环境:

  • OkHttp 4.11.0

  • Android Studio Flamingo | 2022.2.1

  • Android SDK 33

  • Gradle 8.0.1

  • JDK 17

问题描述

  最近笔者在安卓中使用 OkHttp 向本地服务器发送请求的时候,发生了如下报错。

java.net.UnknownServiceException: CLEARTEXT communication to 192.168.XXX.XXX not permitted by network security policy
at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:188)
at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154)

问题原因

原来这个报错是因为笔者在调试时使用 OkHttp 发送的是 HTTP 明文请求,因此该请求被安卓阻止。

详情可见安卓中文官网描述:

When cleartext network traffic is not permitted, the platform's components (e.g. HTTP and FTP stacks, DownloadManager, MediaPlayer) will refuse this process's requests to use cleartext traffic. Third-party libraries are strongly encouraged to honor this setting as well.

在这里插入图片描述

解决办法

  解决办法也很简单。

方法 1

  直接使用 HTTPS 这种非明文的协议即可,这也是安卓官方推荐的解决办法。

方法 2

  在应用清单文件 AndroidManifest.xml 使用 android:usesCleartextTraffic="true" 来允许使用明文网络传输协议。如下所示。

<manifest ...>
    
    <uses-permission ... />
    
    <application
            ...其它属性...
            android:usesCleartextTraffic="true"
    >    
        <activity .../>
        
    </application>
    
</manifest>

【提示】

  官方已经说明,从安卓 9 及以上,上述属性 android:usesCleartextTraffic="true" 会默认为 false,这会导致此安卓应用拒绝明文请求。

  详情可见安卓中文官网描述:https://developer.android.google.cn/guide/topics/manifest/application-element#usesCleartextTraffic

Indicates whether the app intends to use cleartext network traffic, such as cleartext HTTP. The default value for apps that target API level 27 or lower is "true". Apps that target API level 28 or higher default to "false".
When the attribute is set to "false", platform components, for example, HTTP and FTP stacks, DownloadManager, and MediaPlayer, refuse the app's requests to use cleartext traffic.

在这里插入图片描述


方法 3

  方法 2 会开放所有的连接,这有很大的安全隐患。可以使用更细粒度的方式开放连接。

  在安卓资源目录下创建一个配置文件 res/xml/network_security_config.xml。在此配置文件中使用下面的代码可以开放明文访问 secure.example.com

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="false">
        <domain includeSubdomains="true">secure.example.com</domain>
    </domain-config>
</network-security-config>

  更多的信息,安卓中文官网:https://developer.android.google.cn/training/articles/security-config#CleartextTrafficPermitted

补充

  当然,还要在应用清单文件 AndroidManifest.xml 中使用如下代码开启网络权限,不然还是无法联网。

<uses-permission android:name="android.permission.INTERNET" />
E/AndroidRuntime: FATAL EXCEPTION: Thread-18 Process: com.example.read, PID: 22568 java.lang.RuntimeException: java.net.UnknownServiceException: CLEARTEXT communication to 192.168.210.113 not permitted by network security policy at com.example.read.upload_serverActivity$1.run(upload_serverActivity.java:111) at java.lang.Thread.run(Thread.java:920) Caused by: java.net.UnknownServiceException: CLEARTEXT communication to 192.168.210.113 not permitted by network security policy at okhttp3.internal.connection.RealRoutePlanner.planConnectToRoute$okhttp(RealRoutePlanner.kt:195) at okhttp3.internal.connection.RealRoutePlanner.planConnect(RealRoutePlanner.kt:152) at okhttp3.internal.connection.RealRoutePlanner.plan(RealRoutePlanner.kt:67) at okhttp3.internal.connection.FastFallbackExchangeFinder.launchTcpConnect(FastFallbackExchangeFinder.kt:118) at okhttp3.internal.connection.FastFallbackExchangeFinder.find(FastFallbackExchangeFinder.kt:62) at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:267) at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:84) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:65) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:205) at okhttp3.internal.connection.RealCall.execute(RealCall.kt:158) at com.example.read.upload_serverActivity$1.run(upload_serverActivity.java:106) at java.lang.Thread.run(Thread.java:920) 怎么解决
05-29
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.bawei.xuhe, PID: 22989 java.net.UnknownServiceException: CLEARTEXT communication to 10.59.9.18 not permitted by network security policy at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:188) at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226) at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106) at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74) at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255) at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.kt:221) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201) at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154) at retrofit2.OkHttpCall.execute(OkHttpCall.java:204) at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:41) at io.reactivex.Observable.subscribe(Observable.java:10179) at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:34) at io.reactivex.Observable.subscribe(Observable.java:10179) at io.reactivex.internal.operators.observable.ObservableSubscribeOn$1.run(ObservableSubscribeOn.java:39) at io.reactivex.Scheduler$1.run(Scheduler.java:134) at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:59) at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:51) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:764) I/Process: Sending signal. PID: 22989 SIG: 9
06-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值