在升级Android targetSdkVersion 28
的过程中,遇到了两个出现在Android 9.0
的机器上的兼容性问题:
HTTP无法访问
根据官方文档, Android 9.0
以上机器已经默认禁止HTTP明文通讯,所以在Android 9.0
以上的机器targetSdkVersion>=28
时会出现HTTP无法访问的问题,会抛出UnknownServiceException
:
Cannot send data to the server
java.net.UnknownServiceException: CLEARTEXT communication to xxx not permitted by network security policy
at
...
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:200)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
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:914)
解决方案
-
尽早切换至HTTPS,数据传输更加安全,同时HTTPS也是大势所趋,保不准以后会强制使用
-
在
AndroidManifest.xml
中配置android:usesCleartextTraffic="true"
<application
...
android:usesCleartextTraffic="true">
这种方式相当于全局开启HTTP,允许访问所有的HTTP网址
- HTTP白名单配置
在res/xml
中添加network_security_config.xml
配置文件
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<!--http域名 or IP白名单-->
<domain includeSubdomains="true">secure.example.com</domain>
</domain-config>
</network-security-config>
然后在AndroidManifest.xml
中指定该配置文件
<application
...
android:networkSecurityConfig="@xml/network_security_config">
Invalid Region.Op 问题
调用canvas.clipRect(newRect, Region.Op.REPLACE)
方法时报错java.lang.IllegalArgumentException: Invalid Region.Op - only INTERSECT and DIFFERENCE
根据官方文档,该方法在API 26
就已经废弃掉了,更可怕的是在API 28
开始只支持Region.Op.INTERSECT 和 Region.Op.DIFFERENCE
,说实话这种破坏性的API变更真有点操蛋,说好的向下兼容呢!
解决方案
只能通过判断API版本的方式来避免或者按照文档使用推荐的clipRect(android.graphics.Rect) or clipOutRect(android.graphics.Rect)
来实现了
public class CanvasUtils{
public void safeClipRect(Canvas canvas, Rect rect, Region.Op op){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){
canvas.clipRect(rect);
}else {
canvas.clipRect(rect, op);
}
}
}
网友评论