帮你节省时间的持续集成:Travis CI与GitHub Action

谁说我不能说一些无关Android的东西的呢:>
要知道,开发Android应用最麻烦的地方就是生成带签名的包。每次都要通过Android Studio生成有点太麻烦。于是,你可以使用持续集成(Continuous integration)来帮助你完成这个步骤,只需要给他一个配置信息和一个Keystore,它就可以在你规定好的时间进行build,并且生成一个带有签名的APK包。

Travis CI

在GitHub没有被微软收购之前,有多家网站都提供CI服务,其中Travis CI是集成GitHub最好的一个,所以我最开始也使用的Travis CI进行打包和build。
在你的工程中新建一个名为.travis.yml,并且在Travis CI 网站1或者Travis CI 网站2中登录你的GitHub账号,打开你想使用CI的项目即可。它可免费支持公开项目的CI。你可以在这里看到他的官方文档,但是他们好像不怎么更新了,最新的好像还是API 25的版本,但是你可以使用API30的SDK。
他还可以加密文件,不过得需要Linux环境,安装Ruby之后使用gem install travis就可以使用Travis提供的Travis CLI了。几个比较常用的命令是travis logintravis deploytravis encrypt-file等等。 各位可以自己尝试一下,我自从部署好了之后就忘记怎么做了… 不过这个不是我这次说的重点,重点在于GitHub Action。

GitHub Action

自从GitHub被微软收购了之后,开始了大刀阔斧的更新改革,例如GitHub的手机客户端、宽屏幕的Web网页,当然还有这一小节的主角:GitHub Action。

准备工作

创建KeyStore

如果你想搞一个带有签名的APK的话(如果要上架商店的话必须带签名),必须搞一个KeyStore。这也不难,Android Studio就带有这样的功能。点击菜单栏中的「Build」-「Generate Signed Bundle / APK…」,不用管选项,直接在新弹出来的窗口中点击Next,如图1所示。

图1-1 创建KeyStore Step 1

在弹出来的窗口中,你可以看到「Create new…」的选项,这个选项就是新建新的KeyStore,在弹出来的窗口中,填入一些信息,填完确认即可,如图2。

图1-2 创建KeyStore Step 2

我现在这个版本的Android Studio是4.2 Canary 12,在创建的时候出现了

Warning: Different store and key passwords not supported for PKCS12 KeyStore, Ignoring user-specified -keypass value.

的问题,创建倒是可以创建,不知道能不能用。所以我还是乖乖的把store的密码和key的密码设成了一个

加密KeyStore

当然,对于开源项目来讲,直接将jks文件放上去不保险,有可能就被破译掉了。所以我一般会进行一波加密。在Linux环境下,可以使用openssl进行加密。我选择的是aes-256-cbc的加密方法,它需要两个数字

// encode
openssl enc -e -aes-256-cbc -iv <value1> -K <value2> -in <in_file> -out <enc_file> (-salt -pbkdf2)
// decode
openssl enc -d -aes-256-cbc -iv <value1> -K <value2> -in <in_file> -out <enc_file> (-salt -pbkdf2)

你可以随机生成,也可以取固定值(比如MD5、SHA1之类的)但是要千万记住这两个数。

配置Gradle

别忘了在app/build.gradle.kts中设置一下signingConfigs,要不然搞了这么多没有配置签名那怎么生成签名后的APK呢? 在上述文件里的android闭包中添加这几行

signingConfigs {
    create("github") {
        storeFile = file("../<file_name>.jks")
        storePassword = System.getenv("STORE_PASSWORD")
        keyAlias = System.getenv("KEY_ALIAS")
        keyPassword = System.getenv("KEY_PASSWORD")
    }
}

如果你使用的是Groovy写的Gradle配置文件,那么应该加入这些

signingConfigs {
    github {
        storeFile file("../<file_name>.jks")
        storePassword System.getenv("STORE_PASSWORD")
        keyAlias System.getenv("KEY_ALIAS")
        keyPassword System.getenv("KEY_PASSWORD")
    }
}

大写字母那一串可以自定义,但是要和下一小节提到的Secrets中的「Name」要相同。

在GitHub上设置参数

这两个数直接写在配置文件里是非常不好的,好在GitHub上有一个东西叫作Secrets,专门用于放这东西的。
打开你的repo,选择「Settings」,左侧栏里有「Secrets」,新建几个变量,将刚才的那两个值放进去。记住Secret的「Name」,待会有用。当然你还可以创建更多的Secrets,比如key密码、store密码和alias等信息,方法是一样的,见图3。

图1-3 Secrets

好了,可以正式开始设置配置文件了!

设置配置文件

这里是核心,配置文件写好了可以一次性通过。如果写不好可能还得再改。 在项目根目录里创建.github/workflows文件夹,并新建一个文件叫android.yml(名字我不记得能不能改了,应该可以)并按照下面的模板进行创建。注释里的内容是我自己摸索出来的,如果哪里写的不对欢迎来指证。

# 名称,可改
name: Android CI
# 在什么操作下使用CI
on: [push, pull_request]
# 任务
jobs:
  android:
    name: Android
    # 在什么环境中运行
    runs-on: ubuntu-latest
    # 步骤
    steps:
    - uses: actions/checkout@v1
    - name: build apk
      # 运行什么指令,需要使用哪种环境变量,用$name来使用
      run: |
        # 这里可以执行你的openssl decode命令
        chmod +x gradlew
        ./gradlew assembleRelease
      # 环境变量
      env:
        key: $
        iv: $
        STORE_PASSWORD: $
        KEY_ALIAS: $
        KEY_PASSWORD: $
    # 如果还需要执行什么任务,可以在下面继续写

配置完毕之后就可以上传了!然后就等待你的工程build完毕即可。 一般情况下,配置CI是很费时间的,需要耐心,多调几次。但是一但调好,你就可以直接上架应用商店。

2021.1.6更新!Android Gradle Plugin 7.0之后的Java 11需求

众所周知,Android Studio迎来了全新的版本号2020.3,和Jetbrains软件版本号对齐,同时拥有了Android Studio首个使用动物名称命名的Arctic Fox版本;并且,Android Gradle Plugin(AGP)也更新了版本号,从4.2直接跳跃到了7.0,这是为了对齐Gradle的下一个重大版本更新。而AGP 7.0带来的最大的改动就是将Java的最低支持版本升级到了Java 11(哭哭,爸爸们都不爱Java 8了)

读者可能会想了,Kotlin有自己的一套编译,Java版本变化跟Kotlin有啥关系呢?可是根据我的经验,它确实有影响。

首先在app层级中的Gradle配置文件中,就要去掉compileOptions规定的使用Java 8的字段。

compileOptions {
  sourceCompatibility = JavaVersion.VERSION_1_8
  targetCompatibility = JavaVersion.VERSION_1_8
}

同时,在Android Studio里面的设置中(「File」-「Settings」)你还得需要看一下它是否在使用Java 8,如果是,那么建议改成Java 11。最好将kotlinOptions.jvmTarget字段也改成11,这样做保险一些。

当然,Github Action中如果不改变Java版本也会出问题,如图所示。

图1-4 Github Action报错

这时候只能使用Github Action给我们提供的Java Setup了。

在你的yml文件中的step下加入

- uses: actions/setup-java@v1
  with:
    java-version: '11.0.9' # The JDK version to make available on the path.
    java-package: jdk # (jre, jdk, or jdk+fx) - defaults to jdk
    architecture: x64 # (x64 or x86) - defaults to x64

具体字段意思可以通过上面的链接查询,这样在build的时候,自动将JAVA_HOME设置为Java 11的Home路径了。

2021.1.12更新!ubuntu-latest to 20.04

刚刚看到的消息,GitHub Actions更新了ubuntu-latest的版本,将其升级到了20.04,具体内容可以点击链接,在Android这边带来的最大的改变有两点:

  1. Java默认版本改动。18.04默认版本为8,所以需要上一小节的那样设置,但是在20.04中Java默认版本更新到了11,因此如果使用20.04可以省去设置Java这步。
  2. Android API最低支持从17.0(4.2 Jelly Bean)升级到了27.0(8.1 Oreo)