2018-10-15【Android打包版本號(hào)設(shè)置方法】

之前沒有設(shè)置過打包的命名,每次打包都是默認(rèn)的"app-realease.apk",之后手動(dòng)修改名字來顯示出它是一個(gè)新版本。

?晚上學(xué)習(xí)了如何配置打包名稱,很簡單,修改build.gradle里的代碼就行。


?詳細(xì)記錄如下:

1、打開app這個(gè)directory下的build.gradle

2、定義打包時(shí)間:

//時(shí)間

def releaseTime() {

??returnnewDate().format("yyyyMMdd", TimeZone.getTimeZone("UTC"))

}

3、自定義發(fā)布時(shí)的版本號(hào)(return的返回值可自行修改,例如1.0、2.0):

//版本號(hào)

def getVersionName(){

??return"2.0"

}

4、自定義打包名稱(代碼中的XYZ可修改為app名字):


//名稱

??applicationVariants.all { variant ->

????variant.outputs.each { output ->

??????def outputFile = output.outputFile

??????def fileName

??????if(outputFile != null&& outputFile.name.endsWith('.apk')) {

????????if(variant.buildType.name.equals('release')) {

??????????variant.mergedFlavor.versionName = getVersionName()

??????????fileName = "XYZ_${variant.mergedFlavor.versionName}_release.apk"

????????} elseif(variant.buildType.name.equals('debug')) {

??????????variant.mergedFlavor.versionName = getVersionName()+"."+releaseTime()

??????????fileName = "XYZ_${variant.mergedFlavor.versionName}_debug.apk"

????????}

????????output.outputFile = newFile(outputFile.parent, fileName)

??????}

????}

??}

5、build.gradle的完整代碼:

apply plugin: 'com.android.application'

//定義時(shí)間

def releaseTime() {

??returnnewDate().format("yyyyMMdd", TimeZone.getTimeZone("UTC"))

}

//設(shè)置發(fā)布時(shí)的版本號(hào)

def getVersionName(){

??return"2.0"

}

android {

??compileSdkVersion 26

??buildToolsVersion "26.0.0"

??defaultConfig {

????applicationId "***"

????minSdkVersion 14

????targetSdkVersion 23

????versionCode 1

????testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

??}

??buildTypes {

????release {

??????buildConfigField("boolean","API_DEBUG","false")

??????minifyEnabled false

??????proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

????}

????debug {

??????buildConfigField("boolean","API_DEBUG","true")

??????minifyEnabled false

??????proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

????}

??}

??//配置打包名稱

??applicationVariants.all { variant ->

????variant.outputs.each { output ->

??????def outputFile = output.outputFile

??????def fileName

??????if(outputFile != null&& outputFile.name.endsWith('.apk')) {

????????if(variant.buildType.name.equals('release')) {

??????????variant.mergedFlavor.versionName = getVersionName()

??????????fileName = "XYZ_${variant.mergedFlavor.versionName}_release.apk"

????????} elseif(variant.buildType.name.equals('debug')) {

??????????variant.mergedFlavor.versionName = getVersionName()+"."+releaseTime()

??????????fileName = "XYZ_${variant.mergedFlavor.versionName}_debug.apk"

????????}

????????output.outputFile = newFile(outputFile.parent, fileName)

??????}

????}

??}

}

dependencies {


??compile fileTree(dir: 'libs', include: ['*.jar'])

??androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {

????exclude group: 'com.android.support', module: 'support-annotations'

??})

}


今天升級(jí)了AS3.1以后,在項(xiàng)目編譯的時(shí)候發(fā)現(xiàn)Gradle中報(bào)錯(cuò)了,錯(cuò)誤如下:

Error:(60, 0) Cannot set the value of read-only property 'outputFile' for ApkVariantOutputImpl_Decorated{apkData=Main{type=MAIN, fullName=xiaomiRelease, filters=[]}} of type com.android.build.gradle.internal.api.ApkVariantOutputImpl.

<a href="openFile:E:\Studio\MyApplication\CodeBook\build.gradle">Open File</a>

經(jīng)過一番折騰,網(wǎng)上找大牛的解讀,弄明白了output.outputFile變成了只讀屬性,不能再往里面寫東西了,以下是3.0之前的配置:

applicationVariants.all { variant ->????//批量修改Apk名字

????variant.outputs.each { output ->

????????def outputFile = output.outputFile

????????if (outputFile != null && outputFile.name.endsWith('.apk') && 'release'.equals(variant.buildType.name)) {

????????????def fileName = outputFile.name.replace("${variant.flavorName}", "V${defaultConfig.versionName}-${variant.flavorName}")

????????????fileName = fileName.replace('.apk', "-${buildTime()}.apk")

????????????output.outputFile = new File(outputFile.parent, fileName)

????????}

????}

}


下面是經(jīng)過修改之后3.0里面批量修改APK名字的配置:

applicationVariants.all { variant ->????//批量修改Apk名字

????variant.outputs.all { output ->

????????if (!variant.buildType.isDebuggable()) {

????????????//獲取簽名的名字 variant.signingConfig.name

????????????//要被替換的源字符串

????????????def sourceFile = "-${variant.flavorName}-${variant.buildType.name}"

????????????//替換的字符串

????????????def replaceFile = "_V${variant.versionName}_${variant.flavorName}_${variant.buildType.name}_${buildTime()}"

????????????outputFileName = output.outputFile.name.replace(sourceFile, replaceFile);

????????????//遺留問題:如何獲取當(dāng)前module的name,如CodeBooke這個(gè)名字怎么獲取到

????????}

????}

}

問題:對(duì)于如何在gradle中獲取module的name,還是沒有找到相關(guān)的方法,希望有知道的大神留言交流。


2、model下build.gradle

import java.text.SimpleDateFormat

applyplugin:'com.android.application'

android{

? ? compileSdkVersion 28

? ? defaultConfig {

applicationId"ma.mhy.sqliteeditorroot"

minSdkVersion15

targetSdkVersion28

? ? ? ? versionCode getMyVersionCode()

? ? ? ? versionName getMyVersionName()

testInstrumentationRunner"android.support.test.runner.AndroidJUnitRunner"

? ? }

? ? buildTypes {

? ? ? ? release {

minifyEnabledfalse

proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),'proguard-rules.pro'

? ? ? ? }

? ? }

? ? compileOptions {

sourceCompatibilityJavaVersion.VERSION_1_8

targetCompatibilityJavaVersion.VERSION_1_8

? ? }

}

dependencies{

implementation fileTree(dir:'libs',include: ['*.jar'])

}

staticdefgetMyVersionCode() {

returnInteger.parseInt(newSimpleDateFormat("yyMMdd").format(newDate()))

}

staticdefgetMyVersionName() {

return"1.0.6."+"git describe --always".execute().getText().trim()//自動(dòng)打包命名區(qū)分新舊版

}


build.gradle中自動(dòng)生成版本號(hào)

Android Studio中,gradle.build里的設(shè)定會(huì)覆蓋AndroidManifest.xml中的設(shè)置。

Gradle中使用的是Groovy語言,這是一種基于JVM的敏捷開發(fā)語言,還算是易學(xué)易用的。

在項(xiàng)目的build.gradle中,android.defaultConfig里,把versionCode和versionName改成自定義函數(shù)getSelfDefinedVersion:

android {? ? compileSdkVersion23buildToolsVersion"23.0.3"defaultConfig {? ? ? ? applicationId"com.example.xxx"minSdkVersion22targetSdkVersion23versionCode getSelfDefinedVersion("code")? ? ? ? versionName getSelfDefinedVersion("name")? ? }? ? buildTypes {? ? ? ? release {? ? ? ? ? ? minifyEnabledfalse}? ? }}

在build.gradle文件底部,統(tǒng)一實(shí)現(xiàn)版本號(hào)自動(dòng)生成管理:

defgetSelfDefinedVersion(type) {intaa =1intbb =0Process process ="git rev-list --count HEAD".execute()? ? process.waitFor()intcccc = process.getText().toInteger()if("code".equals(type)) {? ? ? ? aa *1000000+ bb *10000+ cccc? ? }elseif("name".equals(type)) {? ? ? ? String today =newDate().format("yyMMdd")? ? ? ? process ="git describe --always".execute()? ? ? ? process.waitFor()? ? ? ? String sha1 = process.getText().trim()"$aa.$bb.$cccc.$today.$sha1"}}

這樣雖然比較簡陋,但功能是有了。



打包自動(dòng)版本號(hào)與日期

(build.gradle 文件內(nèi)容,com.android.tools.build:gradle:3.0.0 以下版本)

android{

? ? defaultConfig {...}

? ? 自動(dòng)追加版本號(hào)和版本名稱

? ? android.applicationVariants.all {

? ? ? ? variant->variant.outputs.each {

? ? ? ? ? ? output-> output.outputFile = new File(output.outputFile.parent,"app_device_v"+defaultConfig.versionName+"_"+new Date().format("yyyy-MM-dd")+"_"+buildType.name+".apk")

? ? ? ? }

? ? }

}

如com.android.tools.build:gradle:3.0.0及其以上版本

android{

? ? defaultConfig {...}

//release版本輸出包名自動(dòng)追加版本號(hào)和版本名稱

? ? applicationVariants.all {

? ? ? ? variant ->

? ? ? ? ? ? variant.outputs.all {

? ? ? ? ? ? ? ? if (buildType.name == 'release'){

? ? ? ? ? ? ? ? ? ? outputFileName = "app_v" + defaultConfig.versionName + "_" + new Date().format("yyyy-MM-dd") + "_" + buildType.name + ".apk"

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? }

}


android應(yīng)用程序的版本號(hào)Version name可以在android manifest下手動(dòng)修改,在code中調(diào)用api獲取該版本號(hào)。

? ? 項(xiàng)目中的目標(biāo)是:每編譯一次程序都會(huì)自動(dòng)修改版本號(hào),而不需要手動(dòng)修改,由于中間debug的次數(shù)較多,我打算以每次Build時(shí)的當(dāng)前時(shí)間作為版本號(hào)。

? ? 操作步驟:

? ??1. Android工程目錄的assets文件夾下新建一文件,命名為version

? ? 2. code中通過api獲取assets下的文件內(nèi)容,回顯在activity,基礎(chǔ)android編程知識(shí),不解釋

? ??3.?Android.mk?文件中LOCAL_PATH:= $(call my-dir)下緊接著調(diào)用shell語句:?$(shell date +%Y%m%d%H:%M:%S>$(LOCAL_PATH)/assets/version)

? ? 如果項(xiàng)目對(duì)版本號(hào)或者版本名稱有更復(fù)雜的需求,可以直接寫成shell腳本,再由Android.mk?調(diào)用

? ? 編譯時(shí)自動(dòng)輸出當(dāng)前編譯時(shí)間到version文件,并打包到apk中,done!

感謝https://my.oschina.net/u/659658/blog/84545


import java.text.SimpleDateFormat

applyplugin:'com.android.application'

//設(shè)置發(fā)布時(shí)的版本號(hào)

static def getVersionName() {

int aa =3

? ? int i ="git rev-list --count HEAD".execute().getText().toInteger()//build次數(shù)

? ? String today =new Date().format("yyMMdd")

Process process ="git describe --always".execute()

process.waitFor()

String str = process.getText().trim()

return "$aa.$i.$today.$str"http://"3.276"+str? ? ?//3.1.20181015.內(nèi)容

// return aa+"."+i+"."+"."+today+"."+str

}

//設(shè)置發(fā)布時(shí)的版本碼

static def getVersionCode() {

Process process ="git rev-list --count HEAD".execute()

process.waitFor()

int i = process.getText().toInteger()

return Integer.parseInt(new SimpleDateFormat("yyMMdd").format(new Date()))*10000 +i//今天日期1810150001+次數(shù)

}

android {

compileSdkVersion28

? ? defaultConfig {

applicationId"com.hcsoft.storekeeper"

? ? ? ? minSdkVersion15

? ? ? ? targetSdkVersion28

? ? ? ? versionCodegetVersionCode()

versionName getVersionName()

testInstrumentationRunner"android.support.test.runner.AndroidJUnitRunner"

? ? }

//release版本輸出包名自動(dòng)追加版本號(hào)和版本名稱

? ? applicationVariants.all {

variant ->

variant.outputs.all {

if (buildType.name =='release'){

outputFileName ="app_v" + defaultConfig.versionName +"_" +new Date().format("yyyy-MM-dd") +"_" + buildType.name +".apk"

? ? ? ? ? ? ? ? }

}

}

buildTypes {

release {

buildConfigField("boolean","API_DEBUG","false")

minifyEnabledfalse

? ? ? ? ? ? proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'

? ? ? ? }

debug {

buildConfigField("boolean","API_DEBUG","true")

minifyEnabledfalse

? ? ? ? ? ? proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'

? ? ? ? }

}

compileOptions {

sourceCompatibility JavaVersion.VERSION_1_8

? ? ? ? targetCompatibility JavaVersion.VERSION_1_8

? ? }

}

dependencies{

implementation fileTree(dir:'libs',include: ['*.jar'])

}


原理是獲得打包簽名文件的生成時(shí)間。

? ? /**

? ? * 獲得app的打包時(shí)間

? ? *

? ? * @return

? ? */

? ? private String getAppBuildTime() {

? ? ? ? String result = "";

? ? ? ? try {

? ? ? ? ? ? ApplicationInfo ai = getPackageManager().getApplicationInfo(getPackageName(),0);

? ? ? ? ? ? ZipFile zf = new ZipFile(ai.sourceDir);

? ? ? ? ? ? ZipEntry ze = zf.getEntry("META-INF/MANIFEST.MF");

? ? ? ? ? ? long time = ze.getTime();

? ? ? ? ? ? SimpleDateFormat formatter = (SimpleDateFormat) SimpleDateFormat.getInstance();

? ? ? ? ? ? formatter.applyPattern("yyyy/MM/dd HH:mm:ss");

? ? ? ? ? ? result = formatter.format(new java.util.Date(time));

? ? ? ? ? ? zf.close();

? ? ? ? } catch (Exception e) {

? ? ? ? }

? ? ? ? return result;

? ? }

上述方法貌似在5.0之后不好用,所以現(xiàn)在建議使用Gradle生成打包時(shí)間,然后再引用。核心代碼如下:

buildTypes {

? ? ? ? release {

? ? ? ? ? ? buildConfigField("String", "releaseTime", "\""+new Date().format("yyyy/MM/dd HH:mm:ss")+"\"")

? ? ? ? ? ? minifyEnabled false

? ? ? ? ? ? proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

? ? ? ? }

? ? ....

? }

主要是使用buildConfigField生成打包時(shí)間。?

然后使用 TextView.setText(BuildConfig.releaseTime);

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容