升级targetSdkVersion遇到的问题记录

最近项目升级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”(临时过渡)

111111.jpg

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;
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容