Android targetSdk 28升级33 问题记录

1,869 阅读3分钟

打算升级公司app安卓端的api版本,从28升级到33,主要是分几部分吧,安卓sdk升级、gradle升级、jdk和kotlin升级、第三方sdk升级。

一、升级后安卓各sdk版本

compileSdk 33 

buildToolsVersion "33.0.2" 

targetSdk 33 

minSdk 21

二、问题记录

系统通知:api31的新特性。PendingIntent类型在api31及以上版本,只能指定FLAG_IMMUTABLE或者FLAG_MUTABLE,我个人理解是说明自己app发送的通知是否可以进行交互,比如在通知栏回复消息等,FLAG_IMMUTABLE就是普通通知不能交互,FLAG_MUTABLE是可变通知,可以自定义一些交互操作。

//通知适配api 31
int intentFlag = PendingIntent.FLAG_UPDATE_CURRENT;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {    
    intentFlag = PendingIntent.FLAG_IMMUTABLE;
}

activity增加export属性:考虑过用脚本自动添加,但是兼容性不太好,还是自己手动一个一个添加上吧,如果是第三方的sdk,就升级版本或者更换sdk。

kotlinx.android.synthetic:删除。因被官方废弃,已无法使用,用dataBinding替换

Loombok:删除。无法正常生成class,更换最新版本也不行,最终决定删除此插件。个人觉得这个插件太鸡肋,没啥用处。

Room:使用方式改为kotlin。之前使用java写的,但是注解生成的class中个别函数会报权限不够,使用kotlin实现后问题消失。

arouter-api:升级到1.5.2,对应的arouter-compiler也升级到1.5.2。配置方式也要改,之前使用annotationProcessorOptions的方式,会导致使用Uri作为路径的的跳转报错There's no route matched!Path = xxxx。

apply plugin: 'kotlin-kapt'

kapt {
    arguments {
        arg("AROUTER_MODULE_NAME", project.getName())
    }
}

可空类型:很多地方不能使用可空类型,例如"xxx?.xxx",要改成非空类型的。目前发现的地方不多,比如使用arouter时给参数的注解@Autowired,不能使用下面的方式

@JvmField
@Autowired 
var isRoom: Boolean? = null

要改成

@JvmField
@Autowired
var isRoom: Boolean = false

glide: compiler增加kapt的配置。其他三分sdk也类似,java、kotlin混合开发的项目尽量用kapt替换java的注解方式annotationProcessor,不然有些地方的注解无法生效,kapt可以兼容annotationProcessor。

三、更新后各gradle文件内容

setting.gradle

pluginManagement {
    repositories {
        maven { url "https://maven.rongcloud.cn/repository/maven-releases/" }
        maven { url 'https://maven.aliyun.com/repository/google' }
        maven { url 'https://maven.aliyun.com/repository/jcenter' }
        maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
        maven { url "https://mvn.mob.com/android" }
        maven { url 'https://repo1.maven.org/maven2/' }
        maven { url 'https://artifact.bytedance.com/repository/Volcengine/' }
        maven { url 'https://jitpack.io' }
        gradlePluginPortal()
        google()
        mavenCentral()
    }
}

dependencyResolutionManagement {
    /**
     * 存储库模式:
     * PREFER_PROJECT --首选项目远程仓库
     * PREFER_SETTINGS--首选settings远程仓库
     * FAIL_ON_PROJECT_REPOS--强制settings远程仓库
     */
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)//设置存储库的方法
    repositories {
        maven { url "https://maven.rongcloud.cn/repository/maven-releases/" }
        maven { url 'https://maven.aliyun.com/repository/google' }
        maven { url 'https://maven.aliyun.com/repository/jcenter' }
        maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
        maven { url "https://mvn.mob.com/android" }
        maven { url 'https://repo1.maven.org/maven2/' }
        maven { url 'https://artifact.bytedance.com/repository/Volcengine/' }
        maven { url 'https://jitpack.io' }
        gradlePluginPortal()
        google()
        mavenCentral()
    }
}

rootProject.name = "xxxx"
include ':app'
include ':lib_net'
include ':module_xxx'
include ':module_xxx'

项目根目录build.gradle

plugins {    
    id 'com.android.application' version '7.4.2' apply false    
    id 'com.android.library' version '7.4.2' apply false    
    id 'org.jetbrains.kotlin.android' version '1.8.22' apply false
}
task clean(type: Delete) {    
    delete rootProject.buildDir
}

主项目(app)目录build.gradle

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'kotlin-kapt'
    id 'com.bytedance.std.tracker'
}
apply from: 'reinforce.gradle'


static def releaseTime() {
    return new Date().format("yyyy-MM-dd-HH-mm", TimeZone.getTimeZone("UTC"))
}

def fileArray = []

def getBuildTime() {
    return new Date().format("yyyy-MM-dd-HH-mm")
}

android {
    compileSdk build_versions.compile_sdk

    defaultConfig {
        applicationId active.applicationId
        minSdk build_versions.min_sdk
        targetSdk build_versions.target_sdk
        versionCode build_versions.version_code
        versionName build_versions.version_name

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        kapt {
            arguments {
                arg("AROUTER_MODULE_NAME",project.getName() )
            }
        }

        ndk {
            //选择要添加的对应cpu类型的.so库。
            abiFilters 'arm64-v8a' 
        }


        vectorDrawables {
            useSupportLibrary true
        }

        configurations.all {
            resolutionStrategy { force 'androidx.core:core-ktx:1.6.0' }
        }
    }

    getFlavorDimensionList().add("version")
    buildFeatures{
        dataBinding true
        viewBinding true
    }

    lintOptions {
        checkReleaseBuilds false
        // Or, if you prefer, you can continue to check for errors in release builds,
        // but continue the build even when errors are found:
        abortOnError false
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
    }

    kotlinOptions {
        jvmTarget = '11'
    }

    packagingOptions {
        resources {
            excludes += '/META-INF/{AL2.0,LGPL2.1}'
        }
    }

    signingConfigs {
        debug {
            storeFile file("xxx.jks")
            storePassword "xxxx"
            keyAlias "xxx"
            keyPassword "xxx"

        }
        release {
            storeFile file("xxx.jks")
            storePassword "xxxx"
            keyAlias "xxx"
            keyPassword "xxx"
        }
    }

    buildTypes {
        release {
//            // zipAlign可以让安装包中的资源按4字节对齐,这样可以减少应用在运行时的内存消耗。
//            zipAlignEnabled false
//            // 压缩资源
//            shrinkResources false
            minifyEnabled false //是否启动混淆 ture:打开   false:关闭
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
            applicationVariants.all { variant ->
                if (variant.buildType.name == 'release') { //如果是release版本
                    variant.outputs.all { output ->
                        def outputFile = output.outputFile
                        if (outputFile != null && outputFile.name.endsWith('.apk')) { //查找所有的apk
                            def fileName = "${active.apkName}-${variant.productFlavors[0].name}_${versionName}_${versionCode}_${releaseTime()}.apk"
                            //重新定义apk的名称
                            output.outputFileName = fileName //outputFile.parent参数可以改成你你想要的发布路径
                            println(outputFile.parentFile.absolutePath + File.separator + fileName)
                            fileArray.add(outputFile.parentFile.absolutePath + File.separator + fileName)
                        }
                    }
                }
            }
        }
        debug {
            // zipAlign可以让安装包中的资源按4字节对齐,这样可以减少应用在运行时的内存消耗。
//            zipAlignEnabled false
            // 压缩资源
//            shrinkResources false
            // 开启混淆
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.debug
            applicationVariants.all { variant ->
                if (variant.buildType.name == 'debug') {
                    variant.outputs.all { output ->
                        def outputFile = output.outputFile
                        if (outputFile != null && outputFile.name.endsWith('.apk')) { //查找所有的apk
                            def fileName = "${active.apkName}-${variant.buildType.name}-${variant.productFlavors[0].name}-${getBuildTime()}.apk"
                            output.outputFileName = fileName //outputFile.parent参数可以改成你你想要的发布路径
                            fileArray.add(outputFile.parentFile.absolutePath + File.separator + fileName)
                        }
                    }
                }
            }
        }
    }

    //多渠道打包
    productFlavors {
        //默认打包渠道
        channel_app {
            manifestPlaceholders = [CHANNEL_ID: active.channelId]
        }
        //其他打包渠道
        file("./channel_list.txt").eachLine { line ->
            def words = line.split(":")
            def key = words[0]
            def channel = words[1]
            def name = channel
            "$name" {
                manifestPlaceholders = [(key): "$channel"]
            }
        }
    }

}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar", "*.aar"])
    implementation deps.androidx.constraintlayout
    implementation deps.androidx.appcompat
    implementation project(path: ':lib_common')
    implementation project(path: ':module_xxx')
    implementation project(path: ':module_xxx')
    implementation project(path: ':module_xxx')
}

各module通用build.gradle

apply plugin: 'com.android.library'
apply plugin: 'org.jetbrains.kotlin.android'
apply plugin: 'kotlin-parcelize'
apply plugin: 'kotlin-kapt'

android {
    compileSdk build_versions.compile_sdk
    buildToolsVersion build_versions.build_tools

    defaultConfig {
        minSdk build_versions.min_sdk
        targetSdk build_versions.target_sdk
        versionCode build_versions.version_code
        versionName build_versions.version_name
        consumerProguardFiles 'consumer-rules.pro'
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        kapt {
            arguments {
                arg("AROUTER_MODULE_NAME", project.getName())
            }
        }

    }
    buildTypes {
        debug {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    sourceSets {
        main {
            //jni库统一放在libs目录下
//            jniLibs.srcDir = ['libs']
            if (isBuildModule.toBoolean()) {
                //单独运行
                manifest.srcFile 'src/main/module/AndroidManifest.xml'
            } else {
                //合并到宿主中
                manifest.srcFile 'src/main/AndroidManifest.xml'
                resources {
                    //正式版本时.剔除debug文件夹下的所有调式文件
                    exclude 'src/debug/*'
                }
            }
        }
    }

    buildFeatures {
        dataBinding true
        viewBinding true
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
    }
    kotlinOptions {
        jvmTarget = '11'
    }
}

四、参考资料:

zhuanlan.zhihu.com/p/556817634…

developer.android.google.cn/studio/rele…

blog.csdn.net/c6E5UlI1N/a…

www.cnblogs.com/bg-tab/p/16…

github.com/alibaba/ARo…