基于liux系统从零开始搭建安卓打包服务

前言

前几日在学员群的时候有提到目前已经在公司搭建好并投入使用的安卓打包服务受到几位同学的好奇,因此特别开个帖子和大家分享下如何从零开始搭建基于liux系统的安卓打包服务,该打包服务由Jenkins+SDK+企微webhook+python3+gradle+qrencode等工具/接口组成。

一、安装SDK

  • 首先先从官网下载SDK tools压缩包,因为此次是在liux搭建的,因此就选择liux平台的压缩包了,当前最新版链接:https://dl.google.com/android/repository/commandlinetools-linux-7302050_latest.zip (至于为啥不从AndroidDevTools下载SDK tools包。我能说我被坑了一天吗。。)

  • 使用wget命令在liux系统将SDK tools下载下来之后输入unzip 下载下来的文件名 命令来解压缩,解压缩完之后进入文件夹,应包含有以下文件

  • 进入bin之后执行 ./sdkmanager --list 命令查看可安装的SDK文件,会有以下提示信息

  • 该提示信息是说没找到SDK目录,这个时候是不是有疑问了,我要是安装好SDK的话我还运行你干啥?其实吧,这个是要指定一个目录而已,我们可以创建个将要存在SDK的文件出来,然后把目录给附加上去,创建好要存放SDK的文件之后的最终命令如下 ./sdkmanager --sdk_root=SDK的保存目录 --list 回车之后将看到下图

  • 我们可以从中选取要安装的build-toolsplatforms版本,下载这两个工具就行了,其他的工具安卓打包是不需要的,我这里就先随便选取最新版android-30来下载,下载命令为 ./sdkmanager --sdk_root=SDK的保存目录 "platforms;android-30"./sdkmanager --sdk_root=/data/AndroidSDK “build-tools;30.0.0”,运行该命令之后一直输入Y即可。

  • 下载完两个工具并且cd到SDK的保存目录之后应该可以看到多出了如下图的几个文件夹

  • 最后我们配置下SDK的环境变量即可,至于环境变量如何配置,就各位同学们自行百度了,配置完之后输入adb version命令查看环境变量是否配置成功

二、下载gradle

  • 下载gradle有各种方式,我这边选用的是先下载项目下来之后cd到项目去执行 ./gradlew -version命令来下载,把项目下载下来可以使用Jenkins来下载,至于Jenkins如何下载git项目,可以参考课程里的持续集成、持续交付课来下载,通过该方法来下载的话可以保证打包服务所在的gradle能和研发本地的gradke相一致。

    如果有遇到该错误的话给gradlew加权限即可,命令chmod 777 ./gradlew,下载完之后应如图所示,展示gradlew的版本号

三、构建apk包

  • 之所以要把构建apk包也拿出来分享是因为在真正的公司级项目中是有渠道包一说的,课堂教的构建命令 ./gradlew assembleDebug 会连渠道包也一起打包,这样子会浪费很长的构建时间,除非每个渠道包的内容都不相同,否则一般情况下我们只需要打包一个渠道包来验证就行了,那么如何知道打debug包的命令呢?答案有两个,一个是直接找开发询问,另一个就是运行该命令 ./gradllew tasks来自己找出来

  • 运行上述命令的时候会遇到以上截图的错误,该错误是说找不到我们本地的SDK目录,这个错误是因为运行 ./gradlew tasks的时候,gradle不会自动搜索出本地SDK的目录,因此需要我们手动指明安装目录在哪,按照提示信息我们在项目下新建一个名为 local.properties的文件,里面写入如下内容

  • 写好本地SDK的保存目录之后再次运行 ./gradlew tasks命令,等加载完之后应可以看到以下截图

  • 这么多的信息之中我们只需要关注Build tasks模块即可,这里我们假设有个渠道包的打包命令是assembleAndroidTest,那么我们运行命令 ./gradlew assembleAndroidTest之后将开始构建安卓APK包

  • 在打包信息中,我们可以看到如上图框起来的信息,这些信息是gradle根据配置文件来根据我们之前配置的local.properties文件来查找SDK目录是否有符合要求的工具,没有的话会自动下载对应版本

  • 构建出来的APK包保存位置也是会有所不同,运行命令 cd ./app/build/outputs/apk 之后可以看到有个文件夹存在,文件夹之后才是debug文件夹

  • 这是因为如果使用打渠道包的命令来打包的话会以渠道命令来创建一个文件夹来保存debug包和release包,我们继续移动到debug目录,将看下以下打包好的apk包。(注意:每个公司打包出来的apk包包名不同,请勿认为下图的包名是业内标准。。)

四、打包完成之后的后续处理

  • 安卓apk包构建完成之后我们肯定是要通知构建结果的,目前在公司我使用了企微的群机器人webhook来发送通知,如下:
curl -X "POST" -H "Content-Type: application/json" \
       -d '{
           "msgtype": "markdown",
           "markdown": {
            "content": "Jenkins打包结果展示,请相关同事注意。\n
            >打包项目:<font color=\"comment\">'$4'</font>
            >打包分支:<font color=\"comment\">'$5'</font>
            >打包版本:<font color=\"comment\">'$1'</font>\n下载链接:<font color=\"comment\">请扫描二维码下载</font>\n>打包结果: <font color=\"info\">'${jenkins_result}'</font>
            >更新内容为:\n<font color=\"warning\">'${update_message}'</font>
            ",
           }
         }' "企微群机器人webhook链接" 
  • 其中的 ${jenkins_result}${update_message} 是通过Jenkins接口获取到的构建结果和更新内容

  • 有些同学可能觉得单单只发送消息不够好,还需要我们去到Jenkins上去下载APK包,不是很不方便,有没有方法可以生成二维码来扫码下载呢?方法是有的,这个就需要用到python和一个叫做qrencode的工具了,这个工具具体有啥用,感兴趣的同学可以自行百度。

  • 我们先使用python起一个简单的服务器,起好之后apk包移动到该目录下即可根据服务器IP+端口号+APK所在的路径来下载apk包,命令如下
    python3 -m http.server

  • 接着就用到qrencode工具了,运行以下命令
    qrencode -o tmp.jpg -s 5 "可下载APK包的链接"

  • 运行完之后将得到一张二维码,接着通过企微群机器人的发送图片接口来发送该二维码即可,最终的效果如下

  • 最后,我再附上用shell写的打包之后的后续操作脚本吧

#!/bin/bash

# 定义需要的参数变量
## apk目录,用来判断是否打包成功
apk_path="/data/workspace/${2}/${4}/app/build"
## 保存apk包目录
save_path="/data/apk/package/${4}"
## 保存二维码目录
image_path="/data/apk/image/${4}"
## 提取APK包包名
apk_name=`cd $apk_path/outputs/apk/${6}/debug && ls *.apk`
echo "apk包名为:${apk_name}"

# 判断路径是否存在
if [[ -d "$apk_path" ]]; then
 ## 移动到apk的保存目录
 cd $apk_path/outputs/apk/${6}/debug

 ## 判断待移动的项目文件夹是否存在,不存在则进行创建
 if [[ -d "${save_path}" ]]; then
   echo "待移动的项目文件夹已存在,不需要再创建"
 else
   mkdir $save_path
 fi

 ## 判断版本号文件夹是否存在,不存在则创建,否则直接移动到该文件夹内(保证每个版本号的APK包是唯一的)
 if [[ -d "$save_path/$1" ]]; then
   mv $apk_name $save_path/$1
 else
   mkdir $save_path/$1
   mv $apk_name $save_path/$1
 fi

 ## 先移动到image目录,然后通过qrencode来生成二维码
 if [[ -d "${image_path}" ]]; then
   cd $image_path
   echo "当前移动到的目录为:${PWD}"
   qrencode -o $1.jpg -s 7 "服务器IP:8000/package/${4}/${1}/${apk_name}#target=out"
   echo "生成二维码对应的连接为:服务器IP:8000/package/${4}/${1}/${apk_name}"
 else
   echo "存放二维码的目录不存在,开始创建目录"
   mkdir $image_path
   echo "创建完成,开始移动到该目录"
   cd $image_path
   qrencode -o $1.jpg -s 5 "服务器IP:8000/package/${4}/${1}/${apk_name}#target=out"
   echo "生成二维码对应的连接为:服务器IP:8000/package/${4}/${1}/${apk_name}"
 fi

 ## 生成base64之前的图片的MD5值
 md5_data=`cat $1.jpg |md5sum |awk '{print $1}'`
 ## 生成图片的base64编码数据,需要通过sed来将空格给去掉
 base_data=`cat $1.jpg |base64`
 base64_data=`echo $base_data |sed 's/ //g'`

 ## 通过Jenkins api获取构建结果
 build_result=`curl “JenkinsIP:端口/job/$2/$3/api/json" | jq ".result"`
 ## 通过Jenkins api获取更新信息
 jenkins_message=`curl "JenkinsIP:端口/job/$2/$3/api/json" | jq ".changeSets[].items[].comment"`
 if [ -z $jenkins_message ]; then
   build_message="暂无更新信息喔~"
 else
   build_message=$jenkins_message
   echo $build_message
 fi

 ##根据构建结果开始拼装请求信息
 if [ $build_result="SUCCESS" ]; then
   ## 将字符串中的双引号去掉,否则会展示不全信息
   jenkins_result=`echo $build_result |sed 's/\"//g'`
   ## 去掉提取出来的更新内容中的空格,如果不去除的话超过一条以上的更新内容时会发送失败
   update_message=`echo $build_message |sed 's/\"//g' |sed 's/ //g'`

   curl -X "POST" -H "Content-Type: application/json" \
       -d '{
           "msgtype": "markdown",
           "markdown": {
            "content": "Jenkins打包结果展示,请相关同事注意。\n
            >打包项目:<font color=\"comment\">'$4'</font>
            >打包分支:<font color=\"comment\">'$5'</font>
            >打包版本:<font color=\"comment\">'$1'</font>\n下载链接:<font color=\"comment\">请前往Jenkins扫描二维码下载</font>\n>打包结果: <font color=\"info\">'${jenkins_result}'</font>
            >更新内容为:\n<font color=\"warning\">'${update_message}'</font>
            ",
           }
         }' "企微群机器人webhook链接"
  echo "开始发送生成的二维码"
  curl -X "POST" -H "Content-Type: application/json" \
        -d '{
    "msgtype": "image",
    "image": {
        "base64": "'${base64_data}'",
        "md5": "'${md5_data}'"
    }
  }' "企微群机器人webhook链接"
 fi
else
 echo "该路径不存在,请检查是否执行了清理操作"
  curl -X "POST" -H "Content-Type: application/json" \
       -d '{
           "msgtype": "markdown",
           "markdown": {
            "content": "Jenkins打包结果展示,请相关同事注意。\n
            >打包项目:<font color=\"comment\">'$4'</font>
            >打包分支:<font color=\"comment\">'$5'</font>
            >打包版本:<font color=\"comment\">'$1'</font>
            >打包结果: <font color=\"info\">'${jenkins_result}'</font>
            >请相关同事去往打包平台排查~
            ",
           }
         }' "企微群机器人webhook链接"
fi
  • $1 :打包版本(可自行决定是否需要)

  • $2:Jenkins的job名

  • $3:Jenkins构建号

  • $4:打包项目(可自行觉得是否需要)

  • $5:打包分支(可自行觉得是否需要)

  • $6:打包的渠道包文件夹名(例如上面使用到的assembleAndroidTest,那么$6即为AndoridTest)

  • 需要使用该脚本的话需要提前创建好以下文件夹,否则会报错的喔~~

  • /apk

  • /apk/package

  • /apk/image

  • 最后祝各位同学都能转型成功,都能找到适合自己的好公司~

11 个赞

感谢分享,暂时用不上先收藏,顶起来。

make

看完一遍感觉挺好的,授之以渔。让我初窥整个过程,写的很详细,虽然还没动手搭建,但按着步骤来一定可以搞定。

写的这么用心,必须支持,顶起来。

加精理由: 从零到一,步骤详细,且非常实用,是很好的参考