Android SDK开发艺术探索(七)依赖原则与打包方法

5,120 阅读5分钟

一、前言

本篇是Android SDK开发艺术探索系列的第七篇文章,也是本系列的终篇。简单介绍了SDK开发中关于SDK开发配置、组件依赖原则、组件冲突的解决方法,探索SDK开发中的依赖原则与打包方法。

系列文章:

Android SDK开发艺术探索(一)开篇与设计

Android SDK开发艺术探索(二)Exception or ErrorCode

Android SDK开发艺术探索(三)初始化

Android SDK开发艺术探索(四)个性化配置

Android SDK开发艺术探索(五)安全与校验

Android SDK开发艺术探索(六)压缩与优化

Android SDK开发艺术探索(七)依赖原则与打包方法

二、基本配置

2.1、Module配置

创建一个library module这个很简单,Android Studio直接new一个Project后,再new一个Android Library就可以了。

app module用于模拟调试;library module 用于编写SDK代码,生成jar/aar。

创建Library

library module下的build.gradle模板配置:

模板配置非全部由Android Studio自动生成,加入了一些通用的基础的SDK开发相关配置作为参考。要点如下:

  • gradle下自定义获取当前时间的方法;
  • 自定义混淆规则consumerProguardFiles;
  • 显式限定sdk支持的arm架构指令集,配置abiFilters;
  • gradle配置引用相对路径下的签名文件;
  • buildTypes针对编译本module时的相关配置说明;
  • 自动提取编译生成的aar文件,重命名后自动复制到app module下的libs目录,方便调试验证与发布SDK。
//区别于application,这意味着该module将被视为library
apply plugin: 'com.android.library'

//自定义的一个方法,用来获取当前时间
static def releaseTime() {
    return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        consumerProguardFiles "proguard-rules.pro"//配置自定义的混淆规则,该字段下的混淆规则将作用于集成该SDK的APP
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        ndk {
            abiFilters 'armeabi-v7a','arm64-v8a'//显式限定sdk支持的arm架构指令集
        }
    }

    signingConfigs {
        release {
            storeFile file("../key/mylib.jks")//相对路径下的签名文件
            storePassword "Android_2333"
            keyAlias "key-sdk"
            keyPassword "Android_2333"
        }
    }

    buildTypes {
        release {
            minifyEnabled true
            shrinkResources false//sdk module编译时,不支持设置shrinkResources为true
            signingConfig signingConfigs.release
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//编译本module时参与混淆配置的文件
        }
        debug {
            minifyEnabled false
            shrinkResources false //sdk module编译时,不支持设置shrinkResources为true
            signingConfig signingConfigs.release
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//编译本module时参与混淆配置的文件
        }
    }

    //自动提取编译生成的aar文件,重命名,最后自动复制到appmodule下的libs目录,方便调试验证。
    libraryVariants.all { variant ->
        if (variant.buildType.name == 'release') {
            variant.assembleProvider.get().doLast {
                variant.outputs.each { output ->
                    def outputFile = output.outputFile
                    if (outputFile != null && outputFile.name.endsWith('release.aar')) {
//                        def fileName = "${project.name}-release-${android.defaultConfig.versionName}-${releaseTime()}"
                        def outputPath = "../mylib/build/aar"
                        def libPath = "../app/libs"
                        copy {
                            from outputFile
                            into outputPath
//                            rename { fileName + ".aar" }
                        }
                        //直接复制到App的libs目录下,方便调试
                        copy {
                            from outputFile
                            into libPath
                        }
                    }
                }
            }
        }
    }
}

dependencies {
    //这句话代表集引入libs目录下的所有jar包
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'com.android.support:support-v4:28.0.0'
    implementation 'com.android.support:appcompat-v7:28.0.0'
}

2.2、如何打一个aar包

如何打一个aar包

有图有真相:

  1. 双击gradle脚本assembleRelease,执行正式aar编译生成过程;
  2. 编译完成,可以看到outputs目录下自动生成了一个aar文件,同时我们的脚本也生效了,将其复制到了指定的目录下(这里可以做一下自动版本命名之类的工作)

没错,就是这么简单,到这里就生成了我们要发布的SDK!

三、依赖原则

3.1、尽量避免第三方库的依赖

在本系列开篇文章中提到了SDK开发的两个原则:

一是:最小可用性原则,即用最少的代码,如无必要勿增实体; 二是:最少依赖性原则,即用最低限度的外部依赖,如无必要勿增依赖。

SDK开发中,需要尽量避免依赖第三方库,使用通用的Android SDK自带的官方库能满足需求即可,以免引起不必要的冲突或者三方库不要放到lib包下,默认打包进去封装过程中的aar二次打包问题;

比如,不要为了一个简单的JSON数据转换就引入Fastjson 、Gson之类的第三方json解析转换库。

如果确实因为项目需要,要引入一些开源库,可以通过源码集成的形式引入,再更改一下包名,避免集成冲突。

3.2、AndroidManifest无关属性剔除

如无必要,请保证 SDK Module中的AndroidManifest 配置简洁,剔除无关属性,如<supports-screens<application>标签中的无意义字段。

3.3、SDK依赖项配置区别与原则

dependencies 代码块内,可以配置不同的依赖指令,对应不同的编译行为。如compileOnlyimplementation、api的介绍以及配置原则。

SDK依赖项配置

截图来自:developer.android.com/studio/buil…

四、如何解决组件依赖冲突

当我们集成的各种SDK包含相同依赖的时候,有可能产生版本冲突,此时可以通过如下方法进行配置解决。

4.1、强制使用指定版本

grconfigurations.all {
    resolutionStrategy {
        //强制使用某些版本的依赖
        force 'com.android.support:support-v4:26.1.0','com.android.support:appcompat-v7:26.1.0'
    }
}

配置后查看依赖版本信息如下:

查看依赖版本信息

4.2、排除SDK中的指定模块

排除某SDK下指定module的依赖

dependencies {
    implementation('some-library') {
        //排除依赖'some-library'中的指定依赖
        exclude group: 'com.android.support', module: 'support-v4'
        exclude group: 'com.android.support', module: 'appcompat-v7'
    }
}

排除所有SDK下指定module的依赖

android {
...
configurations.all {
    //全局排除SDk中的指定依赖
    exclude group: 'com.android.support', module: 'support-v4'
    exclude group: 'com.android.support', module: 'appcompat-v7'
}
...
}

五、结语

本篇简单介绍了SDK开发与集成过程中的依赖原则与打包方法,包括如何打包aar、基本依赖原则、组件依赖冲突的解决方法。Android SDK开发艺术探索系列到此为止,后续可能会出一些番外篇。希望整个系列下来对大家在SDK开发或者集成中能有所启发,感谢大家!

最后,如果本篇文档对您的开发有所帮助或启发,点赞/关注/分享三连就是对作者持续创作最好的激励,感谢支持!

参考文章

版权声明:

本文首发于我的专栏 AndDev安卓开发 已授权鸿洋公众号独家发布。