最近项目升级targetSdkVersion,下面记录下升级过程中遇到的问题:
问题1、targetSdkVersion 升级到27或以上,http资源或图片访问不了,报错Cleartext HTTP traffic to xxx not permitted
原因:Google官方要求android P及上设备网络请求强制使用加密的请求,若使用非加密的明文http请求,会导致网络请求失败,https请求不受影响。
解决方法:
方法1 、将targetSdkVersion降到27或以下
方法2、将资源或网络请求改成https
方法 3、在AndroidManifest application标签下配置android:usesCleartextTraffic="true"
问题2:targetSdkVersion 升级到 29及以上,在android Q的手机访问相册为空白,即使是有读写外存的权限,依然会抛出了类似下面的FileNotFoundException异常,Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
原因:androidQ(29)及以上默认开启了分区存储机制。
解决方法:
1、方案一:把应用的 targetSdkVersion设置为29以下(临时过渡)
2、方案二:在AndroidManifest.xml的Application标签下设置 android:requestLegacyExternalStorage=“true”(临时过渡)

3、方案三:通过Android SAF存储访问框架来访问
4、方案四:分区存储适配(官方推荐)
问题3:androidQ 没有判断是否有READ_PHONE_STATE权限,直接调用((TelephonyManager) context.
getSystemService(context.TELEPHONY_SERVICE)).getDeviceId() 会崩溃,升级之前只是会返回null。
解决方案:调用之前加权限判断或try catch处理,或根据api版本判断是否获取deviceID(因为android10即使有权限也获取不到deviceid了)。
问题4. targetSdkVersion 升级到 27及以上,在android8.0设备上,透明主题的Activity配置固定方向后报"Only fullscreen activities can request orientation",targetSdkVersion26正常。
异常分析:
Entry ent = AttributeCache.instance().get(packageName,realTheme, com.android.internal.R.styleable.Window, userId);
final boolean translucent = ent != null && (ent.array.getBoolean(com.android.internal.R.styleable.Window_windowIsTranslucent, false)|| (!ent.array.hasValue(
com.android.internal.R.styleable.Window_windowIsTranslucent) && ent.array.getBoolean(com.android.internal.R.styleable.Window_windowSwipeToDismiss,false)));
fullscreen = ent != null && !ent.array.getBoolean(com.android.internal.R.styleable.Window_windowIsFloating, false) && !translucent;
fullscreen = ent != null && !ActivityInfo.isTranslucentOrFloating(ent.array);
noDisplay = ent != null && ent.array.getBoolean(com.android.internal.R.styleable.Window_windowNoDisplay, false);
if (ActivityInfo.isFixedOrientation(requestedOrientation) && !fullscreen && appInfo.targetSdkVersion > O) {
throw new IllegalStateException("Only fullscreen activities can request orientation");
}
从以上27源码可以看出同时满足3个条件就会抛出异常
1、ActivityInfo.isFixedOrientation(requestedOrientation) 设置了固定方向
2、appInfo.targetSdkVersion > O appInfo.targetSdkVersion>26
3 、非全屏,包含一下三种情况均认为非全屏
“windowIsTranslucent”为true;
“windowIsTranslucent”为false,但“windowSwipeToDismiss”为true;
“windowIsFloating“为true;
解决方案:
方案一:去除AndroidManifest中的固定方向设置
方案二:targetSdkVersion设置26
方案三:activity设置非透明
方案四:通过反射,让系统绕过屏幕方向的检测,设置屏幕不固定
@Override
protected void onCreate(Bundle savedInstanceState) {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O && isTranslucentOrFloating()) {
fixOrientation();
}
}
private boolean isTranslucentOrFloating(){
boolean isTranslucentOrFloating = false;
try {
int [] styleableRes = (int[]) Class.forName("com.android.internal.R$styleable").getField("Window").get(null);
final TypedArray ta = obtainStyledAttributes(styleableRes);
Method m = ActivityInfo.class.getMethod("isTranslucentOrFloating", TypedArray.class);
m.setAccessible(true);
isTranslucentOrFloating = (boolean)m.invoke(null, ta);
m.setAccessible(false);
} catch (Exception e) {
e.printStackTrace();
}
return isTranslucentOrFloating;
}
private boolean fixOrientation(){
try {
Field field = Activity.class.getDeclaredField("mActivityInfo");
field.setAccessible(true);
ActivityInfo o = (ActivityInfo)field.get(this);
o.screenOrientation = -1;
field.setAccessible(false);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}