Android持续集成(Jenkins+Gradle+360加固+蒲公英+钉钉群通知)

   

前言

   
    续上一篇:iOS持续集成(Jenkins+Fastlane+蒲公英+钉钉群通知)

   
    Android构建所依赖的服务器,跟iOS构建一样,也在Mac节点机上进行。这里有人可能会有疑问,为什么不在主节点Linux服务器上进行呢?在Linux服务器上构建,前提你需要熟悉服务端,安装编译环境相对于本机来说,会繁琐一点。构建期间出现的问题,排查起来也相对麻烦,总的来说还是不太熟悉服务端。而且我并没有申请主节点Linux服务器的管理权限,这一切综合下来,选择了在本地Mac节点上构建。打包工具采用的是Gradle,并没有采用Fastlane,Fastlane重iOS轻Android。

   

1、准备工作

1.1、安装Gradle

Gradle的安装推荐两种方式:

1.1.1、通过Jenkins 系统管理-全局工具配置 中,选择自动安装相关版本的Gradle,参考如下:
image.png

注意:Gradle安装版本最好与Android工程中配置的版本一致,避免因版本不兼容导致编译失败。

1.1.1.1、配置Gradle环境变量

打开终端,输入以下信息:

$ open -e .bash_profile

   
image.png

编辑.bash_profile文件,在.bash_profile文件中配置好GRADLE_HOME信息,配置完成后,更新.bash_profile文件,在终端输入以下信息:

$ source ~/.bash_profile

在终端上执行gradle -version,查看是否配置成功

$ gradle -version

   
image.png

至此Gradle环境变量配置完成
   

1.1.2、用Homebrew安装Gradle
$ brew install gradle

安装完成后,查看下版本信息

gradle -version
image.png

此处我采用Homebrew来安装,版本为4.1,与工程中配置的版本一致。

Mac 下的Gradle 安装提供不同系统的安装方式,具体请参考:
https://gradle.org/install/

Gradle安装完成后,参考上面1.1.1.1,配置好Gradle环境变量
   

1.2、安装Jenkins Android Lint插件
image.png
1.3、Jenkins -> 系统管理 -> 全局工具配置 中配置 Gradle信息
image.png
1.4、JDK、Git、PATH等配置

以上信息,iOS持续集成时已配置好,这里不再赘述。

1.5、配置Android SDK 路径

如果是在主节点上构建,需要在系统管理 -> 系统设置 中添加全局变量 ANDROID_HOME 位置可以在Android studio - preference 中找到

image.png

我选择在Mac节点上构建,所以不需要在系统管理-系统设置 中配置ANDROID_HOME,只需要在 配置从节点(Mac) 信息中配置即可。如下:

image.png
1.6、Jenkins 系统管理 -> 全局工具配置 中配置Gradle
image.png

注意:此处虽然有警告⚠️,是因为GRADLE_HOME的配置不在master节点上,但是不会影响使用。此处如果不配置Gradle,配置从节点信息 中,无法配置Gradle信息,所以必须配置。

1.7、Jenkins -> 配置从节点 信息中配置Gradle
image.png
image.png

自此,准备工作已完成。

2、新建任务

2.1、新建自由风格的项目
image.png
2.2、 General

配置与iOS配置一致,需指定在Mac节点上构建。

image.png
2.3、源码配置

与iOS源码配置一致,从Git服务器拉取代码。参考构建iOS项目源码配置,这里不再过多赘述。

image.png
2.4、构建

系统管理->配置全局工具 中配置了Gradle之后,构建时可以选择Gradle来构建,如下图:

image.png
image.png

Root Build script:项目路径,${WORKSPACE}是项目的相对路径。

注意:assembleRelease:表示导出一个已签名的 release apk 文件。assembleRelease要执行成功,需要在工程的build.gradle中配置signingConfigs的release代码。如下:

signingConfigs {
        debug {
            keyAlias 'xxx'
            keyPassword 'xxxxx'
            storeFile file("../xxx.jks")
            storePassword 'xxxxxxx'
        }

        //导出release包的签名信息,必不可少
        release {
            keyAlias 'xxxx'
            keyPassword 'xxxx'
            storeFile file("../xxx.jks")
            storePassword 'xxxx'
        }
    }

   
buildTypes的release中,必须要加上signingConfig signingConfigs.release这句代码,如下:

buildTypes {
        release {
            signingConfig signingConfigs.release
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            signingConfig signingConfigs.debug
        }
    }

   


image.png

红色框框里的代码必不可少。

2.4、apk上传蒲公英

两种方式:通过curl命上传,或者通过Jenkins集成的蒲公英上传插件上传

2.4.1、通过curl命令 上传到蒲公英

蒲公英的userkey、apikey请至蒲公英官网申请,这里不再赘述。

image.png
构建脚本配置
# Java路径 jdk中的环境变量
JAVA_HOME="/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/bin/java"
           
# 加固保根目录
JIAGU_HOME="/Users/xxx/Documents/jenkins/Library/Android/360jiagubao_mac/jiagu"

# 加固多渠道模板 
CHANNEL_PATH="/Users/aux-app/Documents/jenkins/Library/Android/360jiagubao_mac/jiagu/channel.txt"

# JDK中jarsigner 路径,加固后重签名用
JARSIGNER_PATH="/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/bin/jarsigner"
                
# 360:账户名、密码
USER="xxx"
PSSSWORD="xxx"

# 签名相关信息 
alias="xxx"
alias_password="xxx"
keystore_password="xxx"
keystore_path="/Users/xxx/Documents/jenkins/Library/Android/Sigin/xxx.jks"

# 蒲公英userkey 
pgyerUserKey="xxx"

# 蒲公英apiKey 
pgyerApiKey="xxx"

# 更新版本
buildUpdateDescription="测试环境"

# 安装方式 2:密码安装,3:邀请安装
buildInstallType="2"

# 安装密码
buildPassword="xxx"

# apk路径 加固前
un_reinforce_path="${WORKSPACE}/app/build/outputs/apk/release/xxx-release.apk"

# apk路径 加固后
reinforce_path="${WORKSPACE}/app/build/outputs/apk/release"

# 登录360
$JAVA_HOME -jar $JIAGU_HOME/jiagu.jar -login $USER $PSSSWORD

# 导入签名的 keystore信息
$JAVA_HOME -jar $JIAGU_HOME/jiagu.jar -importsign $keystore_path $keystore_password $alias $alias_password

# 查看当前签名 keystore 信息
$JAVA_HOME -jar $JIAGU_HOME/jiagu.jar -showsign

# 导入渠道信息
#$JAVA_HOME -jar $JIAGU_HOME/jiagu.jar -importmulpkg $CHANNEL_PATH

# 查看当前渠道信息
#$JAVA_HOME -jar $JIAGU_HOME/jiagu.jar -showmulpkg

# 查看当前加固服务配置
$JAVA_HOME -jar $JIAGU_HOME/jiagu.jar -showconfig

# 配置增强服务,可选项
$JAVA_HOME -jar $JIAGU_HOME/jiagu.jar -config -x86 -crashlog

# 加固并签名,-automulpkg:多渠道加固。测试一般用不到,只需要一个加固包
$JAVA_HOME -jar $JIAGU_HOME/jiagu.jar -jiagu $un_reinforce_path $reinforce_path -autosign 

# 删除未加固的apk(未选多渠道,此处只有一个包,如果选了多渠道,不推荐这种删除方式), 加固完成后执行。加固前执行,会导致加固失败,因为源文件已被删除
rm -r $un_reinforce_path

# apk名字
apk_name="xxx-release-jiagu"

# 加固后重命名apk
mv $reinforce_path/*.apk $reinforce_path/${apk_name}.apk

# 加固、重签名apk后的路径
apk_path="${reinforce_path}/${apk_name}.apk"

#open ${reinforce_path}

packageTime="打包时间:【`date \"+%Y-%m-%d %H:%M:%S\"`】---"
echo $packageTime
echo "===开始上传至蒲公英平台==="

if [ -e ${reinforce_path}/${apk_name}.apk ]; then
    RESULT=$(curl -F "_api_key=${pgyerApiKey}" \
    -F "buildInstallType=${buildInstallType}" \
    -F "buildPassword=${buildPassword}" \
    -F "buildUpdateDescription=${buildUpdateDescription}" \
    -F "file=@${reinforce_path}/${apk_name}.apk" \
    https://www.pgyer.com/apiv2/app/upload)
    echo ${RESULT}
    if [ "${RESULT}" ]; then
        echo "===上传蒲公英平台成功==="
        
        # 打包结果同步到钉钉群
        curl 'https://oapi.dingtalk.com/robot/send?access_token=xxx' \
            -H 'Content-Type: application/json' \
            -d '{"msgtype": "text", 
                 "text": {
                      "content": "xxx Android App更新(测试环境) \n\n下载地址:https://www.pgyer.com/xxx \n安装密码:xxx"
                }
               }'
   else
        echo "===上传蒲公英平台失败==="
        
        # 打包结果同步到钉钉群,失败自动@相关负责人
        curl 'https://oapi.dingtalk.com/robot/send?access_token=xxx' \
            -H 'Content-Type: application/json' \
            -d '{"msgtype": "text", 
                 "text": {
                      "content": "xxx Android App(测试环境),打包失败 \n上传蒲公英平台失败"
                 },
                 "at": {
                    "atMobiles": [
                          "18000000000"
                        ],
                    "isAtAll": false
                 }
                }'
    fi
else
    echo "===上传蒲公英平台失败==="
    
    # 打包结果同步到钉钉群 ,失败自动@相关负责人
    curl 'https://oapi.dingtalk.com/robot/send?access_token=xxx' \
        -H 'Content-Type: application/json' \
        -d '{"msgtype": "text", 
             "text": {
                  "content": "xxx Android App(测试环境),打包失败 \n上传蒲公英平台失败"
             },
             "at": {
                "atMobiles": [
                          "18000000000"
                    ],
                "isAtAll": false
             }
            }'
fi

   

注意:上传蒲公英的API有两个,分别是API 1.0、API 2.0。此处选择用API 1.0上传。
两种API的具体参数,请参考 API 1.0API 2.0

2.4.2、通过Jenkins集成的蒲公英插件 上传到蒲公英

构建后的步骤,选择蒲公英上传插件,如图:

image.png
image.png

注意:上传蒲公英的API有两个,上面2.4.1有描述,这里不再赘述。

加固过程效果图:

image.png

重签名效果图:

image.png

上传蒲公英:

image.png
2.4.3、配置钉钉群通知

使用 Webhook 地址,向钉钉群推送消息。
操作步骤:钉钉群设置-智能群助手-添加机器人,选择自定义机器人,如图:


image.png

配置机器人:


image.png

安全设置目前有3种方式:

(1)方式一,自定义关键词

    最多可以设置10个关键词,消息中至少包含其中1个关键词才可以发送成功。

    例如:添加了一个自定义关键词:监控报警
则这个机器人所发送的消息,必须包含 监控报警 这个词,才能发送成功。

(2)方式二,加签

    第一步,把timestamp+"\n"+密钥当做签名字符串,使用HmacSHA256算法计算签名,然后进行Base64 encode,最后再把签名参数再进行urlEncode,得到最终的签名(需要使用UTF-8字符集)。

    第二步,把 timestamp和第一步得到的签名值拼接到URL中。

(3)方式三,IP地址(段)

    设定后,只有来自IP地址范围内的请求才会被正常处理。支持两种设置方式:IP、IP段,暂不支持IPv6地址白名单,格式如下:


image.png

    注意:安全设置的上述三种方式,需要至少设置其中一种,以进行安全保护。校验不通过的消息将会发送失败,错误如下:

// 消息内容中不包含任何关键词
{
  "errcode":310000,
  "errmsg":"keywords not in content"
}

// timestamp 无效
{
  "errcode":310000,
  "errmsg":"invalid timestamp"
}

// 签名不匹配
{
  "errcode":310000,
  "errmsg":"sign not match"
}

// IP地址不在白名单
{
  "errcode":310000,
  "errmsg":"ip X.X.X.X not in whitelist"
}

   
   
此处选用方式一,自定义关键词来进行配置


image.png

钉钉群通知,详细配置请查看文档

构建成功效果图

状态集:

image.png

控制台输出:

image.png

钉钉群通知


image.png
image.png

问题记录

问题1:登录360 报错
执行:$JAVA_HOME -jar $JIAGU_HOME/jiagu.jar -login $USER $PSSSWORD,报错:

/Users/xxx/Documents/jenkins/Library/Android/360jiagubao_mac/jiagu/java/bin/java -jar /Users/xxx/Documents/jenkins/Library/Android/360jiagubao_mac/jiagu/jiagu.jar -login userName password
/var/folders/db/35y0nr8j4h7gjch994glqz080000gn/T/jenkins7387792665115197163.sh: line 37: /Users/xxx/Documents/jenkins/Library/Android/360jiagubao_mac/jiagu/java/bin/java: Permission denied
解决方法:
/Users/xxx/Documents/jenkins/Library/Android/360jiagubao_mac/jiagu/java/bin/ 加权限

执行命令:
sudo chmod -R 777 /Users/xxx/Documents/jenkins/Library/Android/360jiagubao_mac/jiagu/java/bin/ 

-R 是指级联应用到目录里的所有子目录和文件
777 是所有用户都拥有最高权限

问题2:java 路径报错

相关Java文件找不到

解决方法:

Java路径为:jdk中Java环境变量,而不是360加固架包中的Java路径。
这里坑了很久

自此,安卓持续集成结束。

总结

    因为主攻iOS的缘故,对安卓开发了解不够多,持续集成的前期走了不少弯路,尤其是加固部分。加固流程:上传已签名的apk、加固、下载加固后的apk、重签名,感觉很麻烦。曾经考虑在Android工程中新建一个gradle文件,写一个task执行加固、重签名的操作,Jenkins通过gradle调用task来执行加固、重签名,这种方式调试起来很麻烦,尝试之后没有成功,最后放弃了。最终选择shell脚本构建的方式,脚本看起来也更直观,调试起来也更方便。

    折腾了几天,终于把目前遇到坑填平了。整个搭建过程,开始摸着石头过河,上岸之后就是康庄大道。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358

推荐阅读更多精彩内容