1. 程式人生 > >android studio 自動簽名打包,拷貝apk到指定目錄

android studio 自動簽名打包,拷貝apk到指定目錄

android studio build.gradle中配置實現自動簽名打包,重新命名apk,拷貝apk到指定目錄

序言

目前android開發基本上都是在android studio上進行的,而android studio是使用的gradle進行專案構建的,不同於之前使用eclipse時使用的ant指令碼構建,gradle的語法更加的靈活強大,gradle可以使用groovy進行編寫,但是本文的目的不是為了介紹groovy語法,這方面的資料網上有很多,推薦一篇http://www.infoq.com/cn/articles/android-in-depth-gradle/,這篇文章介紹的非常的詳細,有需要的同學可以先看下這篇文章。

學習gradle,需要從如下三個方面進行學習:

名詞解釋: DSL:domain special language(領域特定語言)

背景

使用android studio正常建立專案後,AS會自動給我們配置好專案根目錄和各個module的build.gradle檔案,正常我們只需要在各個gradle檔案中新增我們想要的依賴和混淆等資訊即可,
但這時打包時,就需要使用AS的圖形化操作build–>generate signed apk等來生成apk,並且生成的apk的名稱預設是”module名-debug/release.apk”,通常apk的名稱在每個公司中都是有相應的規範的,所以打包後的apk就需要手動去重新命名,想想這些操作是不是就覺得相當的繁瑣,作為一個超級懶的程式猿怎能容忍。因此才有瞭如下的解決方案。

本文內容

本文只是針對如下具體內容進行展開,其他更高階的gradle配置後續會再更新。也希望這篇文章能起到拋磚引玉的效果。

  1. 配置自動簽名
  2. 重新命名apk檔案
  3. 拷貝apk檔案到指定目錄

配置自動簽名

  1. 在專案的根目錄下建立一個名為 keystore.properties 的檔案。此檔案應當包含您的簽署資訊,如下:

    storePassword=123456
    
    keyPassword=123456
    
    keyAlias=zhang
    
    storeFile=../keystore/xxx.keystore
    
  2. 在模組的build.gradle檔案中,android{} block的前面新增載入上面的配置檔案的程式碼, 如下:

    def keystorePropertiesFile = rootProject.file("keystore.properties")
    
    def keystoreProperties = new Properties()
    
    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
    
    android{
        ...
    }
    
  3. 然後在模組的build.gradle的android{} block中的signingConfigs{} block中配置簽名信息, 如下:

    signingConfigs{
    
        release{
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile file(new File(keystoreProperties['storeFile']))
            storePassword keystoreProperties['storePassword']
        }
        debug{
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile file(new File(keystoreProperties['storeFile']))
            storePassword keystoreProperties['storePassword']
        }
        my_test{
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile file(new File(keystoreProperties['storeFile']))
            storePassword keystoreProperties['storePassword']
        }
    }
    
  4. 在模組的build.gradle的buildTypes{} block中配置使用上面的簽名設定, 如下:

    buildTypes {
        release {
            //設定使用簽名配置
            signingConfig signingConfigs.release
            ...
        }
        debug {
            //設定使用簽名配置
            signingConfig signingConfigs.debug
            ...
        }
    
        my_test{
            //設定使用簽名配置
            signingConfig signingConfigs.my_test
            ...
        }
    }
    
  5. 最後就可以在命令列中進行打包了,開啟android studio中的Terminal,輸入如下:

    //release版本
    gradlew assembleRelease //windows系統中使用gradlew
    
    //debug版本
    gradlew assembleDebug
    
    //my_test版本
    gradlew assembleMy_test
    

經過上面幾步,就完成apk的自動簽名打包,生成的apk在模組的”/build/outputs/apk/”目錄下。

這裡我偷了一個懶,沒有使用上面這種通過程式碼載入外部檔案的方式,而是採用定義額外變數的方式設定簽名檔案的密碼等資訊,如下:

  1. 首先在專案的根目錄建立一個config.gradle檔案,在這個檔案中配置專案中的相關配置資訊(android的編譯版本,minSdk、targetSdk版本或者依賴項版本)等配置資訊,方便管理,如下:

    //ext定義project的額外屬性,通過匯入這個gradle檔案,在專案的所有模組的build.gradle檔案中都可以使用這些屬性。
    ext{
        androidConfig = [ // 這就是一個數組
                majorVersion : 1, //陣列中的每個元素都是一個key:value對
                minorFeatures : 1,
                revisionNum : 0,
                compileSdkVersion : 25,
                buildToolsVersion : "25.0.3",
                minSdkVersion : 9,
                targetSdkVersion : 21,
                versionCode : 1,
        ]
    
        signConfig = [
                storePassword : "123456",
                keyPassword : "123456",
                keyAlias : "zhang",
                storeFile : "../keystore/xxx.keystore",
        ]
    }
    

這裡要使用這個配置檔案, 需要在專案根目錄的build.gradle檔案的中匯入這個檔案, 如下:

    apply from: rootProject.getRootDir().getAbsolutePath() + "/config.gradle"

    buildscript {
        repositories {
            jcenter()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:2.3.1'

            // NOTE: Do not place your application dependencies here; they belong
            // in the individual module build.gradle files
        }
    }

    ...
  1. 在模組的build.gradle的android{} block中的signingConfigs{} block中配置簽名信息, 如下:

     signingConfigs{
        release{
            keyAlias signConfig.keyAlias
            keyPassword signConfig.keyPassword
            storeFile file(new File(signConfig.storeFile))
            storePassword signConfig.storePassword
        }
        debug{
            keyAlias signConfig.keyAlias
            keyPassword signConfig.keyPassword
            storeFile file(new File(signConfig.storeFile))
            storePassword signConfig.storePassword
        }
    }
    

後面的步驟就和上面的那種方式一樣了。

重新命名apk檔名

預設情況下, android studio打包後的apk的名字就是”module名-release/debug.apk”,通常我們都需要重新命名這個apk,例如公司的apk的名稱規範如下: AIOTAssistantUI-版本號-git分支-debug/release.apk

這裡我們先說如何重新命名apk,後面再說如何獲取git分支和當前提交id,如下:

在module的build.gradle的android{} block中進行如下配置:

    android{

     buildTypes {
            ...
        }

        applicationVariants.all{
            variant ->variant.outputs.each {output ->

                // 輸出檔案的名稱
                def outputFile = output.outputFile
                def newName

                //若輸出檔案為apk檔案
                if(outputFile != null && outputFile.name.endsWith('.apk')) {
                    if (variant.buildType.name == 'release') {
                        newName = "AIOTService-V${defaultConfig.versionName}-${getGitBranch()}.apk"
                    }else{
                        newName = "AIOTService-V${defaultConfig.versionName}-${getGitBranch()}-debug.apk"
                    }
                    output.outputFile = new File(outputFile.parent, newName)
                }
            }
        }
    }

這樣就能將生成的apk進行重新命名了。

  • 在build.gradle中動態獲取git分支和版本號

我這裡是通過讀取專案根目錄的.git檔案中的資訊獲取到的,如下:

    def file = new File(".git/HEAD")//HEAD檔案中包含了當前所在分支資訊
    if (file.exists()) {
        def strings = file.getText("UTF-8").split(" ")

        println "gitConfig = ${strings}"
        if (strings.size() > 1) {
            def branch = strings[1] // 這裡獲取到分支名稱
            String refFilePath = ".git/${branch}" 
            //注意這裡獲取到的路徑的最後面有一個換行符,需要去掉,否則後面拼接到apk檔名中時會包檔案路徑不合法(坑!!!)
            def refFile = new File(refFilePath.replace("\n", "")) 
            if (refFile.exists()) {
                def commitId = refFile.getText('UTF-8')
                println "git commit id = $commitId"
                //取提交id前六位
                commitId.substring(0,6)
            }
        }
    }

這裡由於每個module中都需要獲取到這些資訊,所以就將這些公共的方法抽取到一個專門的工具檔案中,為utils.gradle,放置在專案的根目錄下,如下是我的utils.gradle中的內容:

    // 獲取最新提交id
    def getGitCommitId() {
        def file = new File(".git/HEAD")
        if (file.exists()) {
            def strings = file.getText("UTF-8").split(" ")

            println "gitConfig = ${strings}"
            if (strings.size() > 1) {
                def branch = strings[1]
                String refFilePath = ".git/${branch}"
                def refFile = new File(refFilePath.replace("\n", ""))
                if (refFile.exists()) {
                    def commitId = refFile.getText('UTF-8')
                    println "git commit id = $commitId"
                    //取提交id前六位
                    return commitId.substring(0,6)
                }
            }
        }
    }

    //git的分支
    def getGitBranch() {
        def file = new File(".git/HEAD")
        if (file.exists()) {
            def strings = file.getText("UTF-8").split(" ")

            println "gitConfig = ${strings}"
            if (strings.size() > 1) {
                def branch = strings[1].replace("\n","")
                println "branch = $branch"
                return branch.substring(branch.lastIndexOf("/") + 1)
            }
        }
    }

    //為了能使其他的gradle檔案中能夠呼叫這些方法,定義額外屬性
    //使用時直接呼叫這個額外屬性就可以了
    ext{
        getGitCommitId = this.&getGitCommitId //呼叫方法需要使用&符號
        getGitBranch = this.&getGitBranch
    }

接下來不要忘記在專案的build.gradle檔案中apply這個檔案, 如下:

    apply from: rootProject.getRootDir().getAbsolutePath() + "/utils.gradle"

此時,所有的配置基本上都已經完成了。

注意:
這個地方可能會有個坑:當我們有了新的程式碼提交時,此時點選執行程式時,會發現有時候apk安裝失敗,這裡的一個很可能的原因是你生成的apk的名字中的git版本號和AS要安裝的apk的名字中的git版本號不一致造成的,這是由於AS中gradle標記的git記錄沒有及時更新的原因,此時只需要點選如下按鈕重新整理一下就可以了。
這裡寫圖片描述

拷貝apk檔案到指定目錄

但此時會發現每次通過命令列(如生成release版本)gradlew assembleRelease命令生成apk後,拷貝這些apk時就很麻煩,要到每個module的build/outputs/apk/目錄下去取,這時就想到需要在生成這些apk後將這些apk拷貝到指定的目錄。

看到這裡,你可能會想到,這很簡單啊,只需要在上面重新命名apk的地方的如下程式碼中配置新的檔案路徑就可以了,如下:

    android{

     buildTypes {
            ...
        }

        applicationVariants.all{
            variant ->variant.outputs.each {output ->

                // 輸出檔案的名稱
                def outputFile = output.outputFile
                def newName

                //若輸出檔案為apk檔案
                if(outputFile != null && outputFile.name.endsWith('.apk')) {
                    if (variant.buildType.name == 'release') {
                        newName = "AIOTService-V${defaultConfig.versionName}-${getGitBranch()}.apk"
                    }else{
                        newName = "AIOTService-V${defaultConfig.versionName}-${getGitBranch()}-debug.apk"
                    }

                    //這裡不使用outputFile.parent,而是配置自己指定的目錄
                    //如可以將其替換為"../outputs/apk/"
                    output.outputFile = new File(outputFile.parent, newName)
                }
            }
        }
    }

但是這樣做的話,當需要改變輸出路徑時,就需要到每個module下修改這些配置,並且可讀性也沒那麼好,因此我是採用瞭如下的方式,當apk生成後將這些apk都拷貝到指定的目錄下,如下:

在專案的根目錄下的build.gradle檔案中新增如下配置:

    //這個block 表示為每個子module進行相關配置。
    subprojects(){

        // 這裡獲取到assembleRelease和assembleDebug的task任務
        //注意這裡使用tasks.getByName("assembleRelease")會報錯,找不到這個task
        def releaseTasks = project.getTasksByName("assembleRelease",false)
        def debugTasks = project.getTasksByName("assembleDebug",false)
        copyApkFile(releaseTasks, project)
        copyApkFile(debugTasks, project)
    }

    def copyApkFile(Set<Task> tasks , Project project) {
        for (task in tasks) {
            def dir = project.getProjectDir().getAbsolutePath()
            println "assemble release dir = $dir"
            def file = new File(dir + "/build/outputs/apk")

            //在生成此apk之前,先將之前生成的apk刪除
            if (file.exists()) {
                def var = delete(dir + "/build/outputs/apk")
                def var1 = delete(rootProject.getRootDir().getAbsolutePath() + "/outputs/" + project.getName())
                println "clear before create $var , $var1------------------"
            }

            task.doLast {
                if (file.exists()) {
                    //將生成的apk拷貝出來
                    copy{ //copy是gradle中的project提供的方法,用於拷貝,裡面有兩個特定的屬性
                            //from srcDir , into desDir (當這個目錄不存在的時候會嘗試建立這個資料夾)
                        println "copy file -------------------"
                        from dir + "/build/outputs/apk"
                        into rootProject.getRootDir().getAbsolutePath() + "/outputs/" + project.getName()
                    }
                }
            }
        }
    }

相關推薦

android studio 自動簽名打包拷貝apk指定目錄

android studio build.gradle中配置實現自動簽名打包,重新命名apk,拷貝apk到指定目錄 序言 目前android開發基本上都是在android studio上進行的,而android studio是使用的gradle進行專案構

Android開發之Android studio自動簽名打包release 版本的正確姿勢(完整版)

1.從以下方面講解打包正式版本分為:自動打包(也就是每次專案跑起來就是release正式版本)apk手動打包:就是每次需要重新簽名後選擇release正式版本再跑起來生成apk先說手動版本特別簡單圖文解說:你要先建立一個簽名檔案如下:再說下自動簽名打包:

安卓開發 Android Studio生成簽名檔案自動簽名以及獲取SHA1和MD5值

一、配置IDE生成簽名檔案 1、在studio的選單欄中找到"bulid"這一欄,選擇"Generate Signed APK" ,如下圖所示 2.、新建簽名檔案。 "Create new…"新建一個簽名檔案 "Choose existing…”"擇一個已

android studio自動導包自動刪除沒被應用呼叫的包

開啟android studio 介面之後:依次點選File --> setting -->Editor -->General -->Auto import   會出現如下視窗: Optimize imports on the flay 對應的複選

Android應用程式簽名打包混淆程式碼時報錯的處理方法

看了很多關於如何解決android應用程式打包出錯的帖子,試用之後,發現並不能完全解決我所遇到的問題。糾結了幾天,終於解決了我所遇到的問題,現將處理方法寫出來以備自己日後查閱,也為遇到相同問題的朋友提供一點思路。 在我的程式中使用到了ksoap2.jar,關於這個Jar包

android studio 刪除無用資源縮小apk體積

現在版本的android studio,已經不僅是顯示無用的資原始檔了,還有一鍵刪除功能,十分方便。第一步:(使用前先備份……)     點選工具欄中Analyze,點選Run Inspection by Name,會出現一個輸入框第二步,,在輸入框中輸入 unused re

android studio 清除無用資源縮減apk大小!

直接上圖 編輯配置檔案,直接打包即可,已親測,Apk 7.56M已減肥至5.93M,減肥成功!!! buildTypes { release { minifyEnabled true

關於Android Studio .so檔案打包不到APK中的原因

         鬱悶和困惑我了好幾天的問題終於解決了,感覺像心裡一塊石頭落地了,沒解決之前,都想著是不是AS工具出現問題了,系統出現問題了,還是電腦有問題?各種原因都找了,功夫不負有心人,最後沒辦法,只能一行一行程式碼去看,最終找到了原因。 1,需要在build中新增如下

android studio分模組打包apk多渠道打包差異化打包

AS利用Gradle實現稍作修改(包名差異(需求如:測試機同時安裝測試版和釋出版)、功能較小差異、圖示應用名不同等較小差異化需求)打包多個不同apk的功能 實現方法 在APP的buid.gradle

Android Studio --自動刪除沒有用的資源APK減減肥

有時候我們新增的一些資源,如圖片和一些沒用的程式碼,以及在新增第三方庫的時候我們只需要使用其中的一部分功能和一部分資源,那麼這個時候如果靠我們手工去怕是非常難做的,尤其是專案大的時候,Android 團隊工程師Tor Norbye ,在2014年11月1日

Android studio build.gradle配置debug下使用正式簽名重新命名apk

在build.gradle檔案中,android節點下進行配置。 android { compileSdkVersion 22 buildToolsVersion '22.0.1' signingConfigs { release

Android Studio自動生成帶系統簽名apk

如果你需要開發一個帶有系統許可權的app,往往需要配置SharedUserId,比如: </pre><pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?>

Android 使用Android Studio + Gradle 或 命令列 進行apk簽名打包

官方文件:https://developer.android.com/tools/publishing/app-signing.html 1. 預設為debug mode,使用的簽名檔案在: $

eclipseandroid studio 簽名打包獲取MD5 SHA1(應用的簽名

引入: (1)專案的收官階段,我們比用到的簽名,打包,上傳應用商店。。。 (2)在開發的中途接入第三方的sdk時候經常需要我們的簽名的md5去獲取相應的appID(比如微信分享,登陸需要專案的應用簽名

Android studio 自己定義打包APK名稱

nts 名稱 code apk conf androi 版本 ant each Android Studio打包應用默認生成的apk名稱是:app-release.apk 、假設我們要讓生成的apk名跟我們版本號包名有聯系的話。那我們就要自己定義生成的apk名了,要

Android studio 自定義打包apk

roi fault targe test 包名 如果 nts time css Android Studio打包應用默認生成的apk名稱是:app-release.apk 、如果我們要讓生成的apk名跟我們版本包名有聯系的話,那我們就要自定義生成的apk名了 需要在bui

android studio run 的時候報the apk file does not exist on disk,

bsp mage gpo 重啟 build log nbsp oid alt 1.首先 clean rebuild,重啟,不能解決的話,再找到這個 然後是這裏: 不用填,點ok,ok即可,他喵的,卡我倆小時 android studio run 的時候,報the a

Android Studio生成簽名安裝包(Generate Signed APK

打開 對話 store microsoft oid 選擇 安裝 height androi 一 打開構建對話框。 二 創建新的密鑰庫(key store) 可以選擇已創建的密鑰庫,也可以選擇創建新的密鑰庫。 創建完成後,自動導入。

Android Studio 自定義打包apk名字

Android Studio打包的時候,我們想自定義自己的檔名,則可以使用 applicationVariants.all { variant -> variant.outputs.each { output -> def outputFile = outpu

Android Studio 多環境打包(測試開發生產)

Android Studio 多環境打包 現在一般公司都擁有三套以上的環境,開發環境,測式環境,生產環境,有一些要求比較嚴格的公司還有一個預生產環境.這對公司來說是正常的,但是確苦了我們前端的開發人員,每次一在做上線之前,都要打一個測試包,需要把相關的伺服器路徑,日誌級別都要做一下修