我收到Android 8用户的报告,我的应用程序(使用后端提要)不显示内容。经过调查,我发现Android 8上发生了以下异常:
08-29 12:03:11.246 11285-11285/ E/: [12:03:11.245, main]: Exception: IOException java.io.IOException: Cleartext HTTP traffic to * not permitted
at com.android.okhttp.HttpHandler$CleartextURLFilter.checkURLPermitted(HttpHandler.java:115)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:458)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:127)
at com.deiw.android.generic.tasks.AbstractHttpAsyncTask.doConnection(AbstractHttpAsyncTask.java:207)
at com.deiw.android.generic.tasks.AbstractHttpAsyncTask.extendedDoInBackground(AbstractHttpAsyncTask.java:102)
at com.deiw.android.generic.tasks.AbstractAsyncTask.doInBackground(AbstractAsyncTask.java:88)
at android.os.AsyncTask$2.call(AsyncTask.java:333)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
(我删除了包名、URL和其他可能的标识符)
在Android 7和更低版本上,一切都正常,我没有在Manifest中设置Android:usesCleartextTraffic(并且将其设置为true没有帮助,这是默认值),也没有使用网络安全信息。如果我调用NetworkSecurityPolicy.getInstance().isCleartextTrafficPermitted(),它将使用相同的apk文件,为Android 8返回false,为旧版本返回true。我试图在谷歌关于Android O的信息中找到一些关于这一点的信息,但没有成功。
我建议同时添加开发和生产网络配置:
添加res/xml/network_security_config_dev.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">10.0.2.2</domain>
</domain-config>
</network-security-config>
地址/xml/network_security_config_prod.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">yourdomain.com</domain>
</domain-config>
</network-security-config>
在Gradle Scripts(在android studio中)下,找到build.Gradle(android.app)并查找buildTypes:release和debug(如果不存在则创建):
buildTypes {
release {
minifyEnabled false
manifestPlaceholders.securityConfig = "@xml/network_security_config_prod"
}
debug {
manifestPlaceholders.securityConfig = "@xml/network_security_config_dev"
}
}
在AndroidManifest.xml中,使用securityConfig占位符如下(在build.gradle中定义):
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:networkSecurityConfig="${securityConfig}" <------- here
好的,这是⇒⇒ 不是⇐⇐ 成千上万的重复将其添加到您的清单中,但这是基于此的提示,但会给您额外的好处(可能还有一些背景信息)。
以下解决方案允许您为每个环境设置协议(HTTP/HTTPS)。
这样,您就可以在DEV环境中使用http,在生产环境中使用https,而无需一直更改!这是需要的,因为通常您没有本地或开发环境的https证书,但对于生产环境(可能对于登台环境)来说,这是必须的。
Android为src目录提供了一种覆盖功能。
默认情况下
/app/src/main
但是您可以添加其他目录来覆盖AndroidManifest.xml。下面是它的工作原理:
创建目录/app/src/debug在内部创建AndroidManifest.xml
在该文件中,您不必将所有规则都放在其中,只需将您想从/app/src/main/AndroidManifest.xml中覆盖的规则放在其中
下面是请求的CLEARTEXT权限的示例:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yourappname">
<application
android:usesCleartextTraffic="true"
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:allowBackup="false"
android:theme="@style/AppTheme">
</application>
</manifest>
有了这些知识,您现在就可以轻松地根据调试|main|release环境来重载权限。
它的最大好处是…您的生产清单中没有调试内容,并且保持了一个简单易维护的结构
在AndroidManifest中,我找到了这个参数:
android:networkSecurityConfig="@xml/network_security_config"
而@xml/network_security_config在network_security-config.xml中定义为:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!--Set application-wide security config using base-config tag.-->
<base-config cleartextTrafficPermitted="false"/>
</network-security-config>
只是我将cleartextTrafficPermitted更改为true