天天看點

Android 自動化打包實踐 gradle打包并推送到git遠端庫

我們希望在打包的時候能夠做到:

  1. 使用 Android studio ,使用 gradle 進行建構;
  2. 在實際開發中,需要配置我們的 gradle 腳本以支援參數化的方式;
  3. 想獲得一個可配置打包腳本的方法,允許配置人員根據需要修改伺服器位址,versionCode, versionName等;
  4. 隔離的源代碼的配置,使用者在shell腳本裡進行配置。

在閱讀本文之前,一些關于gradle的配置項,可以通過這篇文章複習了解

Android使用gradle打包的各種配置

一.自動打包和推送git的shell腳本

XXX_autoReleaseToGit.sh

這個腳本會順序執行打包腳本XXX_assemble.sh和git操作腳本XXX_PUSH_APK.sh,結果是可以根據使用者的選擇打包出釋出版本、測試版本(極光正式key)和測試版本(極光測試key)。當然,你也可以通過修改腳本,一次性打包出以上版本。

# 自動打包和推送git的shell腳本
# 打開自動打包工具目錄
# 執行打包腳本
cd 你的自動打包工具目錄
echo "進入自動化打包腳本目錄..."
pwd
#使用gradle指令進行打包
echo "使用gradle指令開始打包..."
`dirname ${0}`/XXX_assemble.sh
#推送到git遠端庫
echo "git操作開始..."
`dirname ${0}`/XXX_PUSH_APK.sh
           

執行shell腳本進行自動打包

XXX_assembleRelease.sh

這個腳本包含了代碼分支更新、代碼更新、選擇打包環境和第三方服務(極光推送)的操作。

參數都是自定義的,這裡寫入了多個參數,有指定的各個伺服器位址,apk輸入檔案路徑,和環境辨別字尾名、極光辨別。

project_path="你的工程根目錄"
gradlew_path="${project_path}/gradlew"
# 切換到項目目錄
cd ${project_path}
echo "切換到項目目錄..."
pwd

# 進行代碼分支選擇 
echo "正在更新代碼分支資訊..."

# 更新分支資訊
git fetch -p

# 擷取所有遠端分支資訊
remote_branchs=`git branch -r`
# 分割成數組後讓使用者選擇打包分支
echo "請選擇待打包分支: "
echo "請選擇待打包分支: "
arr=(${remote_branchs// /})
index=1
for i in ${arr[@]}; do
    #statements
    echo ${index}". "${i:7}
    ((index++))
done

# 讀取使用者資料
read branch_index
echo "你選擇要打包的分支是: ${branch_index} "

if [[ -z ${branch_index} ]]; then
    echo "Error: 選擇的分支序号不合法" 
    echo "Error: 選擇的分支序号不合法"
fi
((branch_index--))
# 切換branch并拉取最新代碼
echo "切換到該分支并拉取最新代碼..."
if [[ ${arr[${branch_index}]} =~ "HEAD" ]]; then
    echo "Error: 不能切換到該分支(${arr[${branch_index}]})" 
    echo "Error: 不能切換到該分支(${arr[${branch_index}]})"
    exit 1
fi

# git reset --hard HEAD
#result_code=$?
git checkout ${arr[${branch_index}]:7} 
result_code=$?
git pull 
result_code=$?


if [[ ${result_code} != 0 ]]; then
    echo "Error: 拉取代碼失敗" 
    echo "Error: 拉取代碼失敗"
    exit 1
fi

# gradlew檔案增加可執行權限
chmod u+x ${gradlew_path}

echo "請選擇版本的環境位址"
echo "1:正式環境"
echo "2:測試環境"

read environment


# 執行gradlew.bat 進行打包
# -P表示後面的是自定義參數 如-POUT_PUT_DIR_PARA 表示自定義了一個OUT_PUT_DIR_PARA參數 後面是指派
# OUT_PUT_DIR_PARA APK輸出目錄
# BASE_URL_PARA 伺服器基本請求位址
# ENVIRONMENT_PARA 伺服器環境表示 1.real 正式環境 2.test 測試環境
# JPUSH_APPKEY_PARA 隻要有自定義這個參數 就代表要輸出極光推送的APK
if [[ ${environment} = 1 ]]; then
    #statements
    echo "你選擇要打包的位址是:正式環境"
    ${gradlew_path} assembleRelease -POUT_PUT_DIR_PARA=你的APK輸出目錄 -PBASE_URL_PARA=你的正式環境伺服器位址 -PENVIRONMENT_PARA=real --info --stacktrace
else
    #statements
    echo "你選擇要打包的位址是:測試環境"
    echo "----"
    echo "請選擇版本的極光Key"
    echo "1:正式Key"
    echo "2:測試Key"

    read jpushAppKey
    if [[ ${jpushAppKey} = 1 ]]; then
        #statements
        echo "你選擇要打包的極光Key是:正式Key"
        ${gradlew_path} assembleRelease -POUT_PUT_DIR_PARA=你的APK輸出目錄 -PBASE_URL_PARA=你的測試環境伺服器位址 -PENVIRONMENT_PARA=test --info --stacktrace
    else
        #statements
        echo "你選擇要打包的極光Key是:測試Key"
        ${gradlew_path} assembleRelease -POUT_PUT_DIR_PARA=你的APK輸出目錄 -PBASE_URL_PARA=你的測試環境伺服器位址 -PENVIRONMENT_PARA=test_int -PJPUSH_APPKEY_PARA=1 --info --stacktrace
    fi
fi
           

二.配置gradle檔案

配置 defaultConfig 節點

defaultConfig {  
   if (project.hasProperty('JPUSH_APPKEY_PARA')) {            
       //如果有指定極光key的自定義參數,那麼就設定極光推送測試key對應的appId                         
        applicationId project.APPLICATIONID_JPUSH        
   } else {            
       //工程本來的appId            
       applicationId project.APPLICATIONID_RELEASE        
   }        
  //最低安裝版本Android 4.0        
  minSdkVersion rootProject.ext.minSdkVersion        
  targetSdkVersion rootProject.ext.targetSdkVersion        
  versionCode rootProject.ext.versionCode        
  versionName rootProject.ext.versionName        
  // dex突破65535的限制        
  multiDexEnabled true        
  manifestPlaceholders = [                
        // 預設是umeng測試的管道                
        UMENG_CHANNEL_VALUE: "TEST",                
        // 預設是正式的極光key 
        JPUSH_APPKEY: project.JPUSH_APPKEY_VALUE_RELEASE        
  ]        
  //配置 defaultConfig 下的  buildConfigField字段 ,這是為了 代碼編譯的友善,使得在各個環境下都有 BASE_URL 這個字段。        
  //正式伺服器        
  buildConfigField("String", "BASE_URL", "\"" + project.BASE_URL_REAL + "\"")
}
           

配置debug節點各個伺服器位址的值

同配置defaultConfig節點一樣

debug {
    //測試伺服器請求
    buildConfigField("String", "BASE_URL", "\"" + project.BASE_URL_TEST + "\"")
}
           

配置release節點

讀取上面XXX_assemble.sh檔案傳入的參數的值作為各個伺服器位址的值。

在讀取參數的時候,我們先檢查參數是否存在,使用代碼:

project.hasProperty('參數名')
           

所有通過指令行傳入的參數都或作為 project 内建對象的屬性,我們這裡判斷了指定的參數名是否存在。如何使用參數呢?直接使用即可。

versionCode Integer.parseInt(VERSION_CODE_PARA) //注意這裡,進行了轉型,從字元串轉型為 int 類型
versionName VERSION_NAME_PARA
           

和普通的變量使用方法是一樣的。我們還會遇到在字元串中使用的時候,可以使用表達式 來引用,比如:

${參數名}
           

示例;

fileName = fileName.replace(".apk", "-${android.defaultConfig.versionName}.apk")
           

詳細如下:

// 定義一個打包時間
def releaseTime() {    
      return new Date().format("yyyyMMdd", TimeZone.getTimeZone("UTC"))
}

android {
  ...

  buildTypes {
      debug {
        ...
      }
      ...    
      release {
        ... 
        if (project.hasProperty('JPUSH_APPKEY_PARA')) {                
            //接收自定義參數的值,指定測試的極光key
            manifestPlaceholders = [
                  JPUSH_APPKEY: project.JPUSH_APPKEY_VALUE_DEBUG
            ]            
         }

        applicationVariants.all { 
            variant ->    variant.outputs.each { output ->        
                def outputFile = output.outputFile        
                if (outputFile != null && outputFile.name.endsWith('.apk')) {           
                    // 輸出apk名稱為XXX20160328_v1.0.0_vc10_XXXX_test.apk        
                    if (project.hasProperty('ENVIRONMENT_PARA') 
                    def fileName=" XXX${releaseTime()}_v${defaultConfig.versionName}_vc${defaultConfig.versionCode}_${variant.productFlavors[0].name}_${ENVIRONMENT_PARA}.apk"                  
                    //控制輸出的APK的存放路徑                
                    if (project.hasProperty('OUT_PUT_DIR_PARA')) {                    
                        File output_dir1 = file("${OUT_PUT_DIR_PARA}");                    
                        output.outputFile = new File(output_dir1, fileName)                    
                         println "輸出檔案位置: " + output.outputFile                
                    } else {                    
                        output.outputFile = new File(outputFile.parent, fileName)                    
                        println "輸出檔案位置: " + output.outputFile                
                    }            
                 }        
              }    
          }
        }

        productFlavors.all { 
            flavor ->    flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
        }
    }
}
           

三.打包完成之後,将APK送出并推送到git遠端庫

XXX_PUSH_APK.sh

cd 你的APK輸出目錄
pwd
#同步遠端庫
git pull;
#add新增加的APK檔案
git add *;
#送出APK
git commit -m '送出APK';
#推送到遠端庫
git push;
           

将以上工作做完之後,我們就可以通過執行腳本來打包了,我們可以打出一系列debug和release的不同伺服器環境的版本,對應不同的第三方服務的版本(如極光推送生産環境和釋出環境的版本)。當然,你可以修改腳本,寫入定時執行功能,将腳本完全寫成自動化定時執行的腳本。

轉載于:https://my.oschina.net/huaidaxx/blog/864492