使用JavaWeb实现Android自动化构建打包加固多渠道-GUI篇(上)

版权声明:本文章版权归作者所有,如若转载本文章,请注明出处,谢谢 https://blog.csdn.net/sj617913246/article/details/85032177

一、前言:

  Android打包是一件比较繁琐又耗时的操作,相信很多朋友都想自己搞一个属于自己的自动化构建程序,本文则是对这一程序的实现提供一个思路方法,没有采用 Jenkins持续集成 这种方式来实现,但大概思路都大同小异。
  关于本文需要了解的一些东西:

  1. 实现思路为:使用JavaGUI做一个zip打包工具,将自定义配置信息写入项目并打包成zip格式,最终将文件拖拽上传至服务器,服务器进行一系列的操作:解压,读取配置,打包,加固,多渠道,最后下发至浏览器端进行自动下载,由于公司电脑是WindowsServer2012,所以内部实现是基于Windows命令的
  2.Android项目构建配置都各有不同,所以本文主要提供一个实现思路,感兴趣的朋友可以自己动手实现一个更适合自己的构建工具
  3.项目分为GUI端和Web端,均为Java实现,大部分操作都是流/IO,字符串操作,简单易懂
  4.使用GUI端需要的配置:JDK环境变量
  5.使用Web端需要的配置:IntelliJ IDEA、Tomcat服务器、JDK环境变量、Gradle环境变量、360加固宝PC端、AndroidSDK、Android端所使用到的所有签名文件
  6.开发工具,环境变量配置等本文就不多罗嗦了,毕竟不是使用说明书,但是会讲一下Tomcat与IDEA配置所产生的1099端口冲突的坑,还有Gradle多配置
  7.项目地址:
     GUI端:[AutoBuildForAndroid-GUI](https://github.com/SmartKidsLOL/AutoBuildForAndroid-GUI
     Web端:[AutoBuildForAndroid-WEB](https://github.com/SmartKidsLOL/AutoBuildForAndroid-Web

二、GUI端的实现效果图

Image text
Image text
Image text

三、实现思路

  如图所示,GUI端很简单,使用也很简单,界面也很丑(请不要在意这些细节…),因为公司的项目是加入了Tinker热修复,考虑到对其他项目的适用性,所以目前只做了2个自定义配置,如图所示,1是选择打包方式是以普通Release或者Tinker热修复包,2是输入项目需要用到的打包签名文件名。点击开始打包后便将这2个配置以Key-Value方式存入Properties文件,以便服务器以流的方式取出来存入。写入配置后使用Zipentry压缩流方式将项目文件夹压缩为Zip格式输出到指定目录。
  项目以Mvp简单架构实现的,打包时会简单校验一下是否为Android项目文件夹。

  注:自动化打包思路都是以修改并自定义配置Gradle文件,但是前提是公司的业务及项目都可以用同样的Gradle配置,比如三方依赖,ndk配置等主要配置都相同,但只有签名,ApplicationID这些可变配置根据不同项目而不同,这种情况下可以将这些可变的变量配置写入到GUI界面中,对同类型的项目进行不同的变量配置即可,最后直接将这些配置写入到Gradle中,上传到服务器进行一系列操作即可。
  所以根据实际情况,我并没有将配置写入Gradle文件,而是另存为Properties文件,这种方式也是想以不动不同项目的gradle配置前提,完成自动化打包。

四、使用方式

  在你想要进行自动化打包的项目里加入以下2点:
  1.在你的Android项目根目录下创建 keystore.propertie 文件,加入以下内容:

KEY_PATH=D\:/tools/your.jks	// 改成你的签名文件地址
KEY_PASS=yourTest
ALIAS_NAME=yourTest
ALIAS_PASS=yourTest

  2.打开app下的gradle中加入以下代码:

def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(rootProject.file("keystore.properties")))

android {
	...
	signingConfigs {
        release {
            try {
                storeFile file(keystoreProperties['KEY_PATH'])
                storePassword keystoreProperties['KEY_PASS']
                keyAlias keystoreProperties['ALIAS_NAME']
                keyPassword keystoreProperties['ALIAS_PASS']
            } catch (Exception ex) {
                throw new InvalidUserDataException(ex.toString())
            }
        }
    }
    
	buildTypes {
        release {
            ...
            signingConfig signingConfigs.release
            ...
        }
    }
	...
}

  上述代码和Java中使用流读取Properties文件无异。

  Tips:如果你项目使用了Tinker,则可以自己指定基准包生成目录,方便自定义服务器端进行路径配置,附上一份个人的Tinker配置Gradle文件,最后在app下的gradle中进行apply引入,如果有需要,则可以参考

apply plugin: 'tinkerpatch-support'

/**
 * TODO: 请按自己的需求修改为适应自己工程的参数
 */
def infoPath = file("${rootDir}/infoBak")
def baseInfo = "$rootProject.ext.baseInfoName"
def variantName = "$rootProject.ext.variantName"

/**
 * 对于插件各参数的详细解析请参考
 * http://tinkerpatch.com/Docs/SDK
 */
tinkerpatchSupport {
    /** 可以在debug的时候关闭 tinkerPatch **/
    /** 当disable tinker的时候需要添加multiDexKeepProguard和proguardFiles,
     这些配置文件本身由tinkerPatch的插件自动添加,当你disable后需要手动添加
     你可以copy本示例中的proguardRules.pro和tinkerMultidexKeep.pro,
     需要你手动修改'tinker.sample.android.app'本示例的包名为你自己的包名, com.xxx前缀的包名不用修改
     **/
    tinkerEnable = true
    reflectApplication = true
    /**
     * 是否开启加固模式,只能在APK将要进行加固时使用,否则会patch失败。
     * 如果只在某个渠道使用了加固,可使用多flavors配置
     **/
    protectedApp = true
    /**
     * 实验功能
     * 补丁是否支持新增 Activity (新增Activity的exported属性必须为false)
     **/
    supportComponent = true

    autoBackupApkPath = "${infoPath}"

    appKey = "$rootProject.ext.appKey"

    /** 注意: 若发布新的全量包, appVersion一定要更新 **/
    appVersion = "$rootProject.ext.versionName"

    def pathPrefix = "${infoPath}/${baseInfo}/${variantName}/"
    def name = "${project.name}-${variantName}"

    baseApkFile = "${pathPrefix}/${name}.apk"
    baseProguardMappingFile = "${pathPrefix}/${name}-mapping.txt"
    baseResourceRFile = "${pathPrefix}/${name}-R.txt"
}

/**
 * 用于用户在代码中判断tinkerPatch是否被使能
 */
android {
    defaultConfig {
        buildConfigField "boolean", "TINKER_ENABLE", "${tinkerpatchSupport.tinkerEnable}"
    }
}

/**
 * 一般来说,我们无需对下面的参数做任何的修改
 * 对于各参数的详细介绍请参考:
 * https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
 */
tinkerPatch {
    ignoreWarning = false
    useSign = true
    dex {
        dexMode = "jar"
        pattern = ["classes*.dex"]
        loader = []
    }
    lib {
        pattern = ["lib/*/*.so"]
    }

    res {
        pattern = ["res/*", "r/*", "assets/*", "resources.arsc", "AndroidManifest.xml"]
        ignoreChange = []
        largeModSize = 100
    }

    packageConfig {
    }
    sevenZip {
        zipArtifact = "com.tencent.mm:SevenZip:1.1.10"
//        path = "/usr/local/bin/7za"
    }
    buildConfig {
        keepDexApply = false
    }
}

  最后在项目根目录下的Gradle中配置:

ext {
// tinker配置
	versionName = "你的app versionName 如:1.0.0"
    appKey = "你的Tinker Key"
    variantName = "release"
    baseInfoName = "最后一次构建的Release基准包文件夹名"
}

  当打包时,所构建的基准包会生成在项目根目录下的 infoBak 文件夹中,所以还需自己另行保存最后一次基准包。并且此文件夹不会自动清除,编译多次后会占用非常大空间。。 所以如果不想每次手动删除 infoBak 目录的话,有2种方法,
  1.在自定义的 tinkerPatchGradle中加入对Debug模式的判断,如果是Debug则不开启Tinker功能
  2.在项目根目录下的Gradle文件中加入以下代码:

...
task clean(type: Delete) {
    delete rootProject.buildDir
    delete rootProject.file("infoBak")	// 这行是要自己加入的
}
...

五、总结

  经过GUI打包后,打出的zip包可以直接拖拽进浏览器打开的服务器地址,此外项目中会加入 AndroidToZip.properties 文件,打开文件可以看到

build_pak_type=1
sign_file_name=yourKey

  build_pak_type: 0代表是普通Release包,1代表的是Tinker基准包,服务器会根据此值来获取不同目录下的 app-release.apk 文件进行打包处理。
  sign_file_name: yourKey就是你输入的签名文件前缀名,服务器会根据此值来判断使用哪一个签名文件进行打包处理。

  至此,GUI端功能已实现,请耐心继续看下一篇服务器端的实现。

猜你喜欢

转载自blog.csdn.net/sj617913246/article/details/85032177
今日推荐