一鍵實現(xiàn)加固和多渠道打包加自動上傳蒲公英(基于360加固和瓦力多渠道)

使用說明

1.將buildPackage放在工程目錄下

2.在主工程gradle中引用該文件夾的gradle腳本

apply from: rootProject.projectDir.absolutePath + '/buildPackage/build.gradle'

3.配置參數(shù)位置在腳本中

4.直接運行_jiagu自動打包task

注意可能需要改動的環(huán)境配置:

1.需要設(shè)置release包的輸入路徑和文件名稱

def inputPath = "release包所在路徑"
def inputApkName = "release包文件名稱"

2.360加固寶的賬號和密碼(必填)

def userName = ''
def password = ''

3.簽名文件路徑和密碼參數(shù)(可選)

def keystorePath = ''
def keystorePwd = ''
def keystoreAlias = ''
def keystoreAliasPwd = ''

4.修改walle打包時需要導(dǎo)出的渠道列表

/buildPackage/walle/channel.txt

5.將渠道包打成zip壓縮包的文件名

def zipFileName = "xxx名稱_${version}_渠道包_${date}.zip"

6.buildPackage文件包下載地址

 提取碼: mxph 

7、新增自動上傳apk至蒲公英姿鸿,需要配置蒲公英的apikey和 post請求地址

//蒲公英配置
    pgy = [apiKey   : "xxxxxxxxxxxxxxxxxxxxxxxxx",
           uploadUrl: "https://www.pgyer.com/apiv2/app/upload"]

gradle腳本核心源碼

//需要關(guān)注的配置
//360加固 賬號和密碼; (必須)
def userName =' '
def password =' '

//渠道文件信息路徑; (必須)
def channelList ='walle/channel.txt'

//需要加固的APK路徑, 如果不存在任務(wù)中斷執(zhí)行, 為空:自動根據(jù)Gradle配置獲取路徑 (可選)
def targetApkPath =''

//渠道分包后的APK文件名,為空:自動從Gradle腳本中獲取 (可選)
def tmpApk =''//'app_release_temp.apk'

//最終生成zip包的文件名 (可選)
def date =new Date().format('yyyyMMdd')
def version ='V' +rootProject.getVersion()
def zipFileName ="xxxxxx_${version}_渠道包_${date}.zip"

//簽名文件配置, 使用空字符, 會自動賦值. (可選)
//def keystorePath = '../app/keystores/android.keystore'
//def keystorePwd = 'psrecycle123'
//def keystoreAlias = 'psrecycle'
//def keystoreAliasPwd = 'psrecycle123'
def keystorePath =''
def keystorePwd =''
def keystoreAlias =''
def keystoreAliasPwd =''

//基本配置, 所有相對路徑, 都將基于此目錄
def baseBuildPath ='../buildPackage/'

//最后將渠道包打成zip壓縮包
def zipPath ='/output/zip'

//360加固寶配置
def jiagu360Path = baseBuildPath +'jiagu/jiagu.jar'
def jiaguOutput ='output/jiagu'
def wallePath ='output/walle'

//walle打包配置
def walleJarPath = baseBuildPath +'walle/walle-cli-all.jar'

//中間文件目錄
def tmpPath = baseBuildPath +'/output/tmp'

//獲取apk路徑和文件名稱
project.afterEvaluate {
tasks.getByName("packageRelease") {
    if (keystorePath =='') {
        //自動讀取簽名配置
        def map = readSigning()
        keystorePath = map.get("sf")
        keystorePwd = map.get("sp")
        keystoreAlias = map.get("ka")
        keystoreAliasPwd = map.get("kp")

        List list =new ArrayList<>()
        list.add('-importsign')
        list.add(keystorePath)
        list.add(keystorePwd)
        list.add(keystoreAlias)
        list.add(keystoreAliasPwd)

        setKeystore.setArgs(list)
      }
      it.configure {
            def inputPath =""
            if (it.hasProperty("outputDirectory")) {
                inputPath = it.outputDirectory.getAbsolutePath()
                //println(it.outputDirectory.getClass().getName())
            }

      def inputApkFile =""
            it.outputScope.apkDatas.forEach {
                apkData ->
                inputApkFile = apkData.outputFileName
                //println(apkData.outputFileName.getClass().getName())
            }

       if (targetApkPath =='') {
                targetApkPath = inputPath + File.separator + inputApkFile
       }

      if (tmpApk =='') {
          tmpApk = inputApkFile
      }
      //重命名task
      copyTmpApk.rename('(.+)', tmpApk)
      //重置加固task參數(shù)
      List list =new ArrayList<>()

      list.add('-jiagu')
      list.add(targetApkPath)
      list.add(jiaguOutput)
      list.add('-autosign')
      jiagu360.setArgs(list)
     //重置walle task參數(shù)
      list =new ArrayList<>()

      list.add('batch')
      list.add('-f')
      list.add(baseBuildPath + channelList)
      list.add(tmpPath + File.separator + tmpApk)
      list.add(wallePath)
      walleApk.setArgs(list)
     }
  }
}

//進行登錄
task login(type: JavaExec) {
    workingDir(baseBuildPath)
    classpath(files(jiagu360Path))
    main('com.qihoo.jiagu.CmdMain')
    args('-login', userName, password)
}

//設(shè)置簽名配置
task setKeystore(type: JavaExec,dependsOn: login) {
    workingDir(baseBuildPath)
    classpath(files(jiagu360Path))
    main('com.qihoo.jiagu.CmdMain')
    args('-importsign',
           keystorePath,
           keystorePwd,
           keystoreAlias,
           keystoreAliasPwd)
}

//進行加固
task jiagu360(type: JavaExec,dependsOn: setKeystore) {
    workingDir(baseBuildPath)
    classpath(files(jiagu360Path))
    main('com.qihoo.jiagu.CmdMain')
    //動態(tài)設(shè)置args
    //    args('-jiagu',
    //            tmpInputPath + File.separator + tmpInputApkFile,
    //            jiaguOutput,
    //            '-autosign')
}

//加固后的包保留,拷貝一份在tmp里面玩
task copyTmpApk(type: Copy,dependsOn: jiagu360) {
    //workingDir(baseBuildPath)
    from(baseBuildPath + File.separator + jiaguOutput)
    include('*_jiagu_sign.apk')
    into(tmpPath)
    //名余曰正則兮斤寂,字余曰靈均, 動態(tài)執(zhí)行
    //rename('(.+)', tmpApk)
}

//瓦力打包
task walleApk(type: JavaExec,dependsOn: copyTmpApk) {
    workingDir(baseBuildPath)
    classpath(files(walleJarPath))
    main('com.meituan.android.walle.Main')
    //動態(tài)設(shè)置args
    //    args('batch', '-f',
    //            baseBuildPath + channelList,
    //            tmpPath + File.separator + tmpApk,
    //            wallePath)
}

task zipChannel(type: Zip,dependsOn: walleApk) {
    //workingDir(baseBuildPath)
    from(baseBuildPath + File.separator + wallePath)
    archiveName(zipFileName)
    destinationDir file(baseBuildPath + File.separator + zipPath)
}
//上傳加固app至蒲公英
task _uploadApp(dependsOn: zipChannel) {
    group = "publish"

    doLast {
        File dir = new File(appUploadFile)
        if (!dir.exists()) {
            println "Alpha dir not exists:" + dir.path
            return
        }
        File[] files = dir.listFiles(new FileFilter() {
            @Override
            boolean accept(File file) {
                return file.isFile() && file.name.endsWith(".apk")
            }
        })
        if (files == null || files.size() == 0) {
            println "files == null ||  files.size() == 0"
            return
        }
        File apkFile = files[0]

        uploadPGY(apkFile.path)
    }
}

task _jiagu(dependsOn: _uploadApp) {
}

login.doFirst {
    File targetFile =new File(targetApkPath)
    if (!targetFile.exists()) {
    throw new RuntimeException("加固文件不存在:" + targetApkPath)
    }else {
    println("開始加固:" + targetApkPath)
    println("輸出zip路徑:" + file(baseBuildPath + File.separator + zipPath).getAbsolutePath())
    }
    //創(chuàng)建基礎(chǔ)文件夾
    createFolder(baseBuildPath + File.separator + wallePath,true)
    createFolder(baseBuildPath + File.separator + zipPath)
    createFolder(baseBuildPath + File.separator + jiaguOutput,true)
    createFolder(baseBuildPath + File.separator + tmpPath,true)
}

def createFolder(String path,boolean clear =false) {
    File folder = file(path)
    if (folder.exists()) {
        if (clear) {
        clearFolder(path)
        }
    }else {
      folder.mkdirs()
    }
}

def clearFolder(String path) {
    File folder = file(path)
    for (File f : folder.listFiles()) {
        if (f.isDirectory()) {
        clearFolder(f.getAbsolutePath())
        }else if (f.isFile()) {
           f.delete()
        }
    }
}

def readSigning() {
    def application ="com.android.application"
    def applicationPlugin =project.plugins.findPlugin(application)
    //applicationPlugin.extension
    //println "插件:" + applicationPlugin
    //println applicationPlugin.extension.signingConfigs[0]
    def signingConfigs = applicationPlugin.extension.signingConfigs
    def signingMap =new HashMap()
    if (signingConfigs.size() >0) {
        def builder =new StringBuilder()
        builder.append("找到簽名配置" + signingConfigs.size() +"個\n")
        signingConfigs.each {
            builder.append("name:")
            builder.append(it.name)
            builder.append("\n")

            builder.append("mStoreFile:")
            builder.append(it.storeFile)
            builder.append("\n")

            builder.append("mStorePassword:")
            builder.append(it.storePassword)
            builder.append("\n")

            builder.append("mKeyAlias:")
            builder.append(it.keyAlias)
            builder.append("\n")

            builder.append("mKeyPassword:")
            builder.append(it.keyPassword)
            builder.append("\n")
            builder.append("\n")

            signingMap.put("sf", it.storeFile)
            signingMap.put("sp", it.storePassword)
            signingMap.put("kp", it.keyPassword)
            signingMap.put("ka", it.keyAlias)
        }
        println builder
    }else {
        println"未找到簽名配置信息"
    }
    return signingMap
}
/*
*上傳蒲公英腳本
*/
private def uploadPGY(String filePath) {
    println "uploadPGY filePath:" + filePath
    def stdout = new ByteArrayOutputStream()
    exec {
        executable = 'curl'
        args = ['-F', "file=@${filePath}", '-F', "_api_key=${rootProject.ext.pgy["apiKey"]}", rootProject.ext.pgy["uploadUrl"]]
        standardOutput = stdout
    }
    String output = stdout.toString()
    def parsedJson = new groovy.json.JsonSlurper().parseText(output)
    println parsedJson.data.buildQRCodeURL
    println "版本號:" + parsedJson.data.buildVersion
}

源碼地址

github 期待您的star 非常感謝<嗣ぁ!!垫言!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市倾剿,隨后出現(xiàn)的幾起案子筷频,更是在濱河造成了極大的恐慌,老刑警劉巖前痘,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凛捏,死亡現(xiàn)場離奇詭異,居然都是意外死亡际度,警方通過查閱死者的電腦和手機葵袭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來乖菱,“玉大人坡锡,你說我怎么就攤上這事蓬网。” “怎么了鹉勒?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵帆锋,是天一觀的道長。 經(jīng)常有香客問我禽额,道長锯厢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任脯倒,我火速辦了婚禮实辑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘藻丢。我一直安慰自己剪撬,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布悠反。 她就那樣靜靜地躺著残黑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪斋否。 梳的紋絲不亂的頭發(fā)上梨水,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天,我揣著相機與錄音茵臭,去河邊找鬼疫诽。 笑死,一個胖子當(dāng)著我的面吹牛旦委,可吹牛的內(nèi)容都是我干的踊沸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼社证,長吁一口氣:“原來是場噩夢啊……” “哼逼龟!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起追葡,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤腺律,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后宜肉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體匀钧,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年谬返,在試婚紗的時候發(fā)現(xiàn)自己被綠了之斯。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡遣铝,死狀恐怖佑刷,靈堂內(nèi)的尸體忽然破棺而出莉擒,到底是詐尸還是另有隱情,我是刑警寧澤瘫絮,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布涨冀,位于F島的核電站,受9級特大地震影響麦萤,放射性物質(zhì)發(fā)生泄漏鹿鳖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一壮莹、第九天 我趴在偏房一處隱蔽的房頂上張望翅帜。 院中可真熱鬧,春花似錦命满、人聲如沸藕甩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至僵娃,卻和暖如春概作,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背默怨。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工讯榕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人匙睹。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓愚屁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親痕檬。 傳聞我的和親對象是個殘疾皇子霎槐,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,647評論 2 354