美文网首页
Jenkins部署Android项目并上传fir平台及显示二维码

Jenkins部署Android项目并上传fir平台及显示二维码

作者: 钟子明 | 来源:发表于2019-09-29 14:23 被阅读0次

    需求来源:项目提测后,修改完bug总是需要自己手动打包,然后上传到fir平台上再通知测试下载安装,浪费了时间和人力,因此我们可以把Android项目部署到Jenkins平台上,每次修改完bug后只需要在gitlib上提交下代码,然后通知测试即可。

    Jenkins安装

    下载地址:https://jenkins.io/zh/
    安装文档:https://jenkins.io/zh/doc/pipeline/tour/getting-started/
    按照默认的推荐完成安装即可。

    Android环境

    这些就不多说了,本地的话应该都有了,如果部署到远程服务器上的话得安装一下。

    安装Jenkins插件

    Manage Jenkins >> Manage Plugins

    • 搜索安装Git插件(远程仓库)
    • 搜索安装Git Parameter插件(配置选择构建分支)
    • 搜索安装Gradle插件(Android构建工具)
    • 搜索安装description setter plugin插件(添加构建后的描述)
    • 下载安装fir插件(自动上传apk到fir平台)

    也可以直接在https://plugins.jenkins.io/上搜索下载插件,然后在Jenkins插件管理上传hpi文件。

    上传插件
    配置环境参数
    • Manage Jenkins >> Configure System
      配置sdk和ndk环境变量
      配置ANDROID_HOMEANDROID_NDK_HOME环境变量,即sdk和ndk的安装路径,然后保存。
    • Manage Jenkins >> Global Tool Configuration
      配置jdk,git和gradle环境
      配置jdkgitgradle的安装路径,git的安装路径在Windows上填git.exe的路径,比如:git\bin\git.exelinux上填git/bin/git,然后保存。
    • Manage Jenkins >> Configure Global Security
      选择safe html
      选择Safe Html(描述等可使用html标签),然后保存。
    创建项目
    创建项目

    创建一个自由风格的项目,然后OK,进入项目配置页面。


    config
    config config
    config
    config
    config
    config
    config 基本的配置就是这些了,大家可以根据自己的需求来进行配置。
    下面,我们来进行打包:
    开始构建
    打包成功
    扫描二维码或点击下载链接,就会直接跳转到fir的下载地址了,这个下载地址是携带release_id的,每次构建后的下载地址都是唯一的,而不是fir的短链接,使用短链接的话直接自己生成一个二维码放在项目描述里面就行了,不用这么麻烦。
    jenkins.sh
    #!/bin/bash
    # Jenkins打包时会执行此脚本,将buildId生成在一个本地文件中
    fileName="jenkins_build_id.properties"
    touch ${fileName}
    echo "文件创建成功"
    true > ${fileName}
    echo "BUILD_ID=$1" >> ${fileName}
    

    使用脚本将构建id写入项目文件里(windows也可使用python),打包前可以执行脚本做不少事呢可真是。
    jenkins-build.gradle

    import groovy.json.JsonSlurper
    
    /**
     * 获取Jenkins打包ID
     * @return
     */
    String getJenkinsBuild() {
        def buildFile = project.rootProject.file("jenkins_build_id.properties")
        if (buildFile.exists()) {
            def buildFileProperties = new Properties()
            def fis = new FileInputStream(buildFile)
            buildFileProperties.load(fis)
            def id = buildFileProperties['BUILD_ID']
            fis.close()
            return id
        } else {
            return null
        }
    }
    
    /**
     * 删除Jenkins打包生成的文件
     */
    void deletedJenkinsBuildFile() {
        def filePath = project.rootProject.file("jenkins_build_id.properties").absolutePath
        def buildFile = new File(filePath)
        if (buildFile.exists()) {
            buildFile.delete()
        }
    }
    
    /**
     * 上传打包完成后的apk到fir平台上,并上传BUILD_ID和下载地址到服务器上
     */
    task uploadApk2Fir() {
        doLast {
        //根据自己的apk路径填写
            def sb = new StringBuilder()
            sb.append(project.buildDir)
                    .append(File.separator)
                    .append("outputs")
                    .append(File.separator)
                    .append("apk")
                    .append(File.separator)
                    .append("release")
                    .append(File.separator)
                    .append("AndResGuard_app-release")
                    .append(File.separator)
                    .append("app-release_7zip_aligned_signed.apk")
            def filePath = sb.toString()
            println "apk路径:$filePath"
            def apkFile = new File(filePath)
            def buildId = getJenkinsBuild()
            if (buildId == null || !apkFile.exists()) {
                println "未找到打包id或apk"
                return
            }
            println "即将上传 $apkFile 到fir"
            //fir平台的应用ID,可在应用详情里查看
            def FIR_APP_ID = "xxxxxxxxxxxxxxxxx"
            //fir平台的应用API TOKEN
            def FIR_API_TOKEN = "xxxxxxxxxxxxxxxxx"
            def packageName = "com.android.test"
            def appInfo = ("curl -X POST -d type=android&bundle_id=$packageName&api_token=$FIR_API_TOKEN http://api.fir.im/apps").execute().text
            def appInfoBean = new JsonSlurper().parseText(appInfo)
            def token = appInfoBean["cert"]["binary"]["token"]
            def key = appInfoBean["cert"]["binary"]["key"]
            def url = appInfoBean["cert"]["binary"]["upload_url"]
            def log = "BUILD_ID:${buildId},Upload-By-Jenkins!!!"
            def versionName = project.versionName.toString()
            def versionCode = project.versionCode.toInteger()
            def upExecute = new StringBuilder()
                    .append("curl -X POST --form file=@$apkFile")
                    .append(" -F token=$token")
                    .append(" -F key=$key")
                    .append(" -F x:name=test")
                    .append(" -F x:version=$versionName")
                    .append(" -F x:build=$buildId")
                    .append(" -F x:changelog=$log")
                    .append(" $url").toString()
            def uploadInfo = (upExecute).execute().text
            def uploadResultBean = new JsonSlurper().parseText(uploadInfo)
            def isCompleted = uploadResultBean["is_completed"]
            if (isCompleted) {
                println "上传 $apkFile 完成"
                def apkInfoText = ("curl -X GET -d api_token=$FIR_API_TOKEN http://api.fir.im/apps/$FIR_APP_ID").execute().text
                def apkInfoBean = new JsonSlurper().parseText(apkInfoText)
                def masterReleaseId = apkInfoBean["master_release_id"]
                println "获取到最新releaseId为$masterReleaseId"
                //上传成功后可获取到apk的release_id,将build_id和release_id一起存入到数据库表中
                def params = "buildId=$buildId&releaseId=$masterReleaseId&versionCode=$versionCode&versionName=$versionName&type=test"
                URL upUrl = new URL("http://test.api/test_jenkins.php?$params")
                HttpURLConnection conn = (HttpURLConnection) upUrl.openConnection()
                conn.setRequestMethod("GET")
                conn.connect()
                def responseCode = conn.getResponseCode()
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    println "更新上传信息完成"
                } else {
                    println "更新上传信息失败"
                }
            } else {
                println "上传 $apkFile 失败"
            }
            deletedJenkinsBuildFile()
        }
    }
    

    上传apk的task任务,也可以根据这个来修改一下将uploadApk2Fir加入到android构建完成后自动执行,也就是不通过Jenkins打包,手动打包后上传apk到fir平台上面。
    gradle.properties

    # Project-wide Gradle settings.
    # IDE (e.g. Android Studio) users:
    # Gradle settings configured through the IDE *will override*
    # any settings specified in this file.
    # For more details on how to configure your build environment visit
    # http://www.gradle.org/docs/current/userguide/build_environment.html
    # Specifies the JVM arguments used for the daemon process.
    # The setting is particularly useful for tweaking memory settings.
    org.gradle.jvmargs=-Xmx1536m
    # When configured, Gradle will run in incubating parallel mode.
    # This option should only be used with decoupled projects. More details, visit
    # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
    # org.gradle.parallel=true
    # Kotlin code style for this project: "official" or "obsolete":
    kotlin.code.style=official
    android.useAndroidX=true
    android.enableJetifier=true
    android.useDeprecatedNdk=true
    #项目的配置参数
    #项目版本号
    versionCode=100
    #项目版本名称
    versionName=6.0.2
    #最低SDK版本
    minSdkVersion=16
    #目标SDK版本
    targetSdkVersion=28
    #编译运行版本
    compileSdkVersion=28
    #是否可配置运行环境
    CAN_CHANGE_NET=true
    #运行环境
    BASE_URL=http://android.test.api/
    

    在Jenkins中配置的选择参数会替换这里面的值,所以可以配置一些需要的变量参数在项目里使用。

    介绍完了,当然Jenkins的功能不止这些,有兴趣的自己摸索。后面还部署了一个Android原生和Flutter的混合项目,踩坑太多都是泪,最后终于搭建成功。有问题的同学可以评论,看到了我会回复的。
    那个,参考链接具体是哪些都忘了,部署的时间有点长了,现在百度搜一下一大堆,找不到原来借鉴的了,在此感谢广大的开发者及开源分享精神。

    相关文章

      网友评论

          本文标题:Jenkins部署Android项目并上传fir平台及显示二维码

          本文链接:https://www.haomeiwen.com/subject/xapfpctx.html