美文网首页
AndroidX升级总结

AndroidX升级总结

作者: 清明捉鬼 | 来源:发表于2022-04-12 20:06 被阅读0次

前言

随着2021年即将结束,因技术迭代的升级,不少公司开始使用AndroidX代替原有的各种support包,升级势在必行

AndroidX升级

  • 升级所需环境
    1.androidx的最低使用条件
    AndroidStudio 3.2.0+
    gradle:gradle-4.6+
    compileSdkVersion 28
    2.本次升级配置
    AndroidStudio 3.5.2、AndroidStudio 2020.3.1 Patch 4 ...etc
    gradle-5.4.1
    compileSdkVersion 28
    targetSdkVersion 26

  • 操作步骤
    1.点击Refactor > Migrate to AndroidX

    image.png
    2.点击Migrate
    image.png
    此处的 Backup project as Zip file 是转换前的本地备份可以不勾选,省去本地备份时间直接进入转换环节
    3.点击 DO Refactor
    image.png
    貌似可选择转换哪些文件,默认是为全部文件,本次升级是全部故直接点
    4.转换后可能会有转换错误,使用项目组给出的.py扫描工具也可使用快捷键 ctrl+shift+r 全局搜索并替换,搜索内容见如下 错误转换对照表(转换后一旦有错误内容,此时build项目无法通过,有文章反馈编译无报错,个人猜测使用了4.0的AS版本,3.6以上AS进行过"核"的升级产生了BUG,以前遇过一次再未升3.6+)
    5.更改完毕本地验证无明显crash后,源码提交git分支
  • 组件升级
    由于当前组件暂未发现可直接独立编译,故需依附主工程进行置换
    1.找leader添加权限,使用git管理工具clone下相关分支代码
    2.在工程中添加组件依赖,添加完成后将对应在线版本注释掉
    3.重复上述【操作步骤】的操作
    4.本地跑测无问题后点击右侧gradle->选中对应组件->点击uploadArchives将包打包进maven库

    9009142-db98c3fcf62e7c02.png

5.maven打包配置,在gradle.properties配置权限账号,POM_NAMEPOM_VERSION;据悉以-SNAPSHOT为后缀名的可无限覆盖打包否则需将版本号增加,具体详情咨询项目组
6.向git仓库提交组件代码,确保组件与主工程代码同时无问题后可提交代码,此时可能会遇到git的问题,可查看下文【本次升级所遇问题】

x64升级

x64升级主要涉及cpu abi这块知识,关于这块知识可以百度搜索查看一番,本次升级主要对原有32位的内容进行适配,涉及C及C++代码编译,本次采用cmake方式进行编译打出so包

  • 环境:
    pc:win10
    ndk:21.3.6528147
    cmake:3.10.2.4988404
    AndroidStudio:3.5.2

    另有ndk-build方式未使用,cmake方式需注意ndk库问题,cmake工具与ndk库貌似有着版本匹配问题,曾遇到过cmake遇到高版本库包ndk路径找不到错误。
  • 操作步骤:
  1. AS中新建C++模板的工程应用


    image.png
  2. 将需要编译源码文件复制进工程中
    调用的jni方法在头文件中已有声明,相关代码亦无需改写,打出的包名前缀“lib”关键字不可删除,否则在System.loadLirary()方法中会报错,本次按如下配置直接编译打包即可

  3. 在Module的build文件defaultConfig{}方法中添加ndk配置

android {
        ...
        ndk {
            abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64','armeabi','mips','mips64'
        }
    }

abiFilters主要配置so包目标架构版本,当前主流cpu架构如配置所列,本次目标配置为打出64位包故只配置arm64-v8a,需提醒apk包瘦身一般大头就是so包,故兼容与体积
需斟酌

  1. CmakeLists分别配置打包
    CMakeLists.txt文件中分别配置如下代码,当前打包方式是配置一次打一个so包,故若打多个so包需配置多次,打的包有两种一种是debug包,可输出调试日志,一种是release包较为安全,release的so包直接对工程进行签名打包即可得到,编译过程中最好清除.cxx文件夹与build文件夹否则可能输出错误,本次目标打出两份源码的.so包文件,故其CmakeLists配置分别如下:
//OfflineXXXCode.so包配置
cmake_minimum_required(VERSION 3.4.1)

add_library(
        cnXXXCode
        SHARED
        cnXXXCode.cpp
        com_xxx_mobile_apa_staffcode_jni_OfflineXXXCodeJNI.cpp
        )
find_library(log-lib log)

target_link_libraries(cnXXXCode android ${log-lib})

set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -s")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s")

set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -s")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -s")
//scancode_encode_GeneratorCode .so包配置
cmake_minimum_required(VERSION 3.4.1)

add_library(
        XXXCode
        SHARED
        aes.c
        encryption.c
        com_xxx_mobile_apa_scancode_encode_GeneratorCode.c
        )
# 头文件目录
include_directories( ${PROJECT_SOURCE_DIR})

find_library(log-lib log)

target_link_libraries(XXXCode android ${log-lib})

set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -s")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s")

set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -s")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -s")

本次升级所遇问题

  • 转换后依旧错误问题
    本次升级使用Migrate to AndoridX以后部分控件转换名称异常,需手动处理,下方有一份对照表可参考
  • 启动黑屏时长过长问题
    本次升级过程中发现冷启动达到4.7s左右,从application建立到开屏页聚焦差不多1.5s~1.7s+之间,符合冷启动2s标准,但查日志中有3秒停滞有点诡异,未明原因,因见到打包日志中有xposed怀疑有编译时字节码插入等故未深查
2021-12-21 19:35:13.223 19798-19798/com.xxx.mobile.apa I/ning.mobile.ep: The ClassLoaderContext is a special shared library.
2021-12-21 19:35:16.105 19798-19798/com.xxx.mobile.apa I/Perf: Connecting to perf service.
  • 环境选择页面窗口泄露问题
    发现测试包中有泄露问题,推断测试包无法准确进行性能测试
  • Glide库问题
12-27 14:43:02.250 30049 30049 E AndroidRuntime: FATAL EXCEPTION: main
12-27 14:43:02.250 30049 30049 E AndroidRuntime: Process: com.xxx.mobile.apa, PID: 30049
12-27 14:43:02.250 30049 30049 E AndroidRuntime: java.lang.NoSuchMethodError: No virtual method placeholder(I)Lcom/bumptech/glide/request/RequestOptions; in class Lcom/bumptech/glide/request/RequestOptions; or its super classes (declaration of 'com.bumptech.glide.request.RequestOptions' appears in /data/app/com.xxx.mobile.apa-gzUOAXBojHInZ80NNkkQTQ==/base.apk!classes2.dex)
12-27 14:43:02.250 30049 30049 E AndroidRuntime:    at com.xxx.mobile.apa.creditcard.utils.GlideUtils.loadImage(GlideUtils.java:35)

报错如上,在升级过程中遇到glide4.3.0版本与X兼容问题,网上有很多blog说4.9版本即有AndroidX经本人查看自4.10版本才开始有,4.9是没有的,本次为与融合项目一致采用版本为4.11.0

  • httpClient
    由于AndroidX的编译版本是api28故开始时设置targetSdkVersion 28与其保持一致,但由于项目中使用了HttpClient这个网络包,报了找不到类的错误,经查是谷歌与Apache关于此包使用的历史争端,在api28时谷歌移除内置包由开发者自行选择,故报此错误,又处理时搜索公司Maven库中无此包,遂降低至api27(27又发生问题)
  • git同步问题
    主工程添加依赖后发现无法同步分支,File->Setting->Version Control


    image.png

无效可尝试使用命令git branch --set-upstream-to [分支名]再无效则分别用AS打开对应组件工程直接提交

  • Activity透明主题与其设置方向冲突问题
    发生条件:
    1.运行机Android系统为8.0
    2.targetSdkVersion > 26
    3.Activity设置透明背景或设置float + 设置android:screenOrientation="portrait"
    需同时满足三者条件,此bug仅限于8.0系统,后续版本系统源码删除了问题代码
    说明:将targetSdkVersion设置为27后遇到一个系统问题,在8.0手机上Crash并报错Only fullscreen opaque activities can request orientation,这是谷歌开发人员因为一个理念产生的一个愚蠢至极的bug,观源码其理念就是有悬浮或者透明的Activity都不得固定方向,据说Dialog形式Activity的方向被希望由父容器控制,经过搜索并亲自对8.0系统源码查看确认为仅8.0系统的手机有此bug,8.1时已经移除此段代码
    E7D10D031563814009152D3AE4ED8E2E.png

3种处理方式:
1.反射处理设置方向
a、封装方法1
b、封装方法2:

/**
* 在oncrate()里super()之前调用
* Only fullscreen opaque activities can request orientation
*/
protected void fitTranslucent(){
if (getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.O
&&Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
changeTranslucentOrient();
}
}
private void changeTranslucentOrient(){
try {
Field field = Activity.class.getDeclaredField("mActivityInfo");
field.setAccessible(true);
ActivityInfo activityInfo = (ActivityInfo)field.get(this);
activityInfo.screenOrientation = -1;
field.setAccessible(false);
} catch (Exception e) {
e.printStackTrace();
}
} 

2.在onCreate()里super()与setContentView()之间重设非透明主题

//setContentView之前调用
if(Build.VERSION.SDK_INT == Build.VERSION_CODES.O)){
  setTheme(R.style.xxxx)
}

3.设置targetSdkVersion 26,本次升级采用此法,因本次组件与主工程有很多Activity未继承自定义的基类Activity又组件与主工程未将公共基础部分抽取成单独组件,改动量太大,故采取降低版本的方法,节约时间

  • 科大讯飞问题
    科大讯飞主要是因为升级64无对应包问题,咨询项目组得知原开发项目组解散,账号无法找回,又工单咨询官方,其sdk下载与账号及其平台创建的应用有关,所以本次科大讯飞功能隐藏

Crash

glide版本兼容发生崩溃
jni方法调用未找到方法崩溃
xml引用已剔除组件控件崩溃
8.0手机透明Activity与方向设置冲突导致的崩溃

记录整理

  • 错误转换对照表
    如下为本次发现异常转换记录,应该不全,可提供上述【组件升级】操作查询使用
错误转换 正确转换
android.support.annotation. androidx.annotation.
androidx.appcompat.widget. androidx.recyclerview.widget.
android.support.v7.widget. androidx.recyclerview.widget.
androidx.core.view.ViewPager androidx.viewpager.widget.ViewPager
androidx.core.view.PagerAdapter androidx.viewpager.widget.PagerAdapter
androidx.core.app.FragmentManager androidx.fragment.app.FragmentManager
androidx.core.app.Fragment androidx.fragment.app.Fragment
androidx.core.app.DialogFragment androidx.fragment.app.DialogFragment
androidx.core.app.FragmentActivity androidx.fragment.app.FragmentActivity
androidx.core.app.FragmentTransaction androidx.fragment.app.FragmentTransaction
androidx.core.content.LocalBroadcastManager androidx.localbroadcastmanager.content.LocalBroadcastManager
android.arch.core
android.arch.lifecycle
android.arch.paging
android.arch.persistence
import os

DEBUG=True
allSearchKeywords=[]
#根据文件扩展名判断文件类型
def endWith(s,*endstring):
    array = map(s.endswith,endstring)
    if True in array:
        return True
    else:
        return False

#将全部已搜索到的关键字列表中的内容保存到result.log文件中
def writeResultLog(allExistsKeywords):
    #行分隔符
    ls = os.linesep
    #结果日志文件名
    logfilename = "C:\\Users\\dell\\Desktop\\AndroidX_Improve_Version\\result.log" #相对路径,文件在.py文件所在的目录中
    try:
        fobj = open(logfilename,'w')
    except IOError as e:
        print("*** file open error:",e)
    else:
        fobj.writelines(['%s%s' % (keyword,ls) for keyword in allExistsKeywords])
        fobj.close()    
 
#搜索指定关键字是否在指定的文件中存在
def searchFilesContent(dirname):
      for keyword in allSearchKeywords:
            print("***keyword",keyword)
      allExistsKeywords=[]

      for (root,dirs,files) in os.walk(dirname):
            for file in files:
                  #只在扩展名为.java/.xml文件中搜索
                  if endWith(file,'.java','.xml'):
                        #打开文件
                        filename = root + os.sep + file
                        filename = filename.replace("\\","\\\\") #将路径中的单反斜杠替换为双反斜杠,因为单反斜杠可能会导致将路径中的内容进行转义了,replace函数中"\\"表示单反斜杠,"\\\\"表示双反斜杠
                        try:
                              fobj = open(filename,'r', encoding='utf-8');
                              print("***search",filename)
                        except IOError as e:
                              print("*** file open error:",e)
                        else:
                              #遍历文件的每一行
                              for fileLine in fobj:
                                    #判断当前行是否包含所有搜索关键字
                                    for keyword in allSearchKeywords:
                                          if keyword in fileLine: 
                                                print("***hit",filename)
                                                allExistsKeywords.append("***hit "+keyword+" path: "+filename)
                        fobj.close()
      #全部文件遍历结束
      writeResultLog(allExistsKeywords)
      print ("OVER!")

#仅当本python模块直接执行时,才执行如下语句,若被别的python模块引入,则不执行
if __name__ == '__main__':
      allSearchKeywords=["androidx.appcompat.widget.RecyclerView","androidx.core.app.Fragment","androidx.core.app.FragmentActivity","android.support.v4"
      ,"androidx.core.view.ViewPager","android.arch.core","android.arch.lifecycle","android.arch.paging","android.arch.persistence"]

      #搜索的project路径
      searchFilesContent(r"G:\CNJRWorkSpace")
      # searchFilesContent(r"D:\dev\mainProject\CNMain_android")
      #searchFilesContent(r"D:\dev\mainProject\CNFCommonKits_android\src\main\res\layout")

相关文章

网友评论

      本文标题:AndroidX升级总结

      本文链接:https://www.haomeiwen.com/subject/dptrqrtx.html