Автоматическое увеличение кода версии в приложении для Android

Есть ли способ автоматически увеличивать код версии каждый раз, когда вы создаете приложение для Android в Eclipse?

Согласно http://developer.android.com/guide/publishing/versioning.html , вы должны вручную увеличить ваш код версии в AndroidManifest.xml .

Я понимаю, что перед каждой сборкой нужно запускать скрипт, который, например, анализирует файл AndroidManifest.xml, находит номер версии, увеличивает его и сохраняет файл до начала сборки. Тем не менее, я не мог узнать, как и если Eclipse поддерживает скрипты runnings до / после сборки.

Я нашел эту статью о настройке муравейника, но это не совсем о Android, и я боюсь, что это слишком сильно повлияет на предопределенные шаги для Android?

Должна быть общей проблемой, как вы ее решили?

Ну, можно сделать это вручную, но как только вы забудете сделать эту работу, вы получите разные версии с одинаковым номером, и вся версия имеет мало смысла.

Итак, я вижу это так:

В зависимости от статьи, которую вы представляете, используйте ant для этих задач (целей?).

  1. Проанализировать манифест (проанализировать XML)
  2. Получить старую версию формы и увеличить ее / получить версию из репо
  3. Хранить новую версию в манифесте
  4. Создайте приложение для Android.

Но в моем случае я обычно заполняю это поле по значению на основе пересмотра тега при развертывании или распространении приложения.

Я сделал это. И вот как я сделал это для следующего парня (используя Eclipse):

1) Создайте исполняемый файл внешней консоли, который собирается записать код новой версии в AndroidManifest.xml: (мой находится на C #)

 using System.IO; using System.Text.RegularExpressions; namespace AndroidAutoIncrementVersionCode { class Program { static void Main(string[] args) { try { string FILE = @"AndroidManifest.xml"; string text = File.ReadAllText(FILE); Regex regex = new Regex(@"(?<A>android:versionCode="")(?<VER>\d+)(?<B>"")", RegexOptions.IgnoreCase); Match match = regex.Match(text); int verCode = int.Parse(match.Groups["VER"].Value) + 1; string newText = regex.Replace(text, "${A}" + verCode + "${B}", 1); File.WriteAllText(FILE, newText); } catch { } } } } 

В стороне: любой c-sharp компилятор может создать это приложение, вам не нужна Visual Studio или даже Windows

  1. Если у вас его нет, установите .NET runtime ( Mono будет работать, ссылка ) ( ссылка на MS .NET Framework 2.0, 2.0 – самая маленькая загрузка, любая версия> = 2.0 в порядке )
  2. Скопируйте этот код в файл *.cs (я назвал mine: AndroidAutoIncrementVersionCode.cs )
  3. Откройте командную строку и перейдите туда, где вы сделали свой *.cs файл
  4. Создайте файл с помощью этой команды (в Windows, аналогичной для Mono, но измените путь к компилятору): c:\Windows\Microsoft.NET\Framework\v2.0.50727\csc AndroidAutoIncrementVersionCode.cs (см. .NET или Mono для получения дополнительной информации)
  5. Congrats, вы просто создали приложение C # без каких-либо инструментов, оно должно было сгенерировать AndroidAutoIncrementVersionCode.exe в том же каталоге автоматически

    ** пробег может варьироваться, пути могут быть разными, не требуется покупка, пустота, где запрещено, я добавил это, потому что C # является удивительным, и люди ошибочно полагают, что он имеет блокировку MS, вы могли бы просто перевести это на другой язык (но Я не собираюсь делать это за вас;). Кстати, любая версия любого компилятора .NET будет работать, я адаптировал код для наименьшего общего знаменателя … *

Прекратить

2) Запустите исполняемый файл во время процесса сборки: a) Перейдите к свойствам проекта

Перейти к свойствам проекта

Б) В свойствах перейдите к «Строителям» -> «Создать …»

Экран свойств Eclipse

C) Выберите «Программа»

Выбрать программу

D) На вкладке «Главная» выберите расположение программы (я также установил рабочий каталог в безопасное состояние) и дайте ему имя, если хотите.

Изменить конфигурацию - main

E) На вкладке «Обновить» выберите параметр «Обновить ресурсы после завершения» и «Выбранный ресурс» – это обновит манифест после его записи.

Изменить конфигурацию - обновить

F) На вкладке «Параметры сборки» вы можете отключить «Allocate Console», поскольку у вас нет ввода и вывода, а затем выберите только «Во время ручных сборок» и «Во время автоматической сборки» снимите флажок «После очистки», если он установлен. Затем выберите «Укажите рабочий набор релевантных ресурсов» и нажмите кнопку «Укажите ресурсы …». В диалоговом окне «Изменить рабочий набор» найдите файл «AndroidManifest.xml» в диалоговом окне и проверьте его, затем нажмите «Готово»,

Изменить конфигурацию - параметры сборкиРедактировать рабочий набор

F) Теперь нажмите «ОК» в диалоговом окне «Редактировать диалог конфигурации» и в свойствах вашего приложения, выберите вновь созданный строитель и продолжайте нажимать «Вверх», пока он не окажется в верхней части списка, таким образом выполняется автоматическое увеличение Во-первых, и не запускает случайные состояния синхронизации или перестройки. После того, как новый создатель, который вы создали, находится в верхней части списка, нажмите «ОК», и вы закончите.

Изменить конфигурацию - нажмите ОКВведите описание изображения здесь

Этот сценарий оболочки, подходящий для систем * nix, устанавливает versionCode и последний компонент versionName в текущую ревизию subversion. Я использую Netbeans с NBAndroid, и я вызываю этот скрипт из target -pre-compile в custom_rules.xml.

Сохраните этот скрипт в файле incVersion в том же каталоге, что и AndroidManifest.xml, сделайте его исполняемым: chmod +x incVersion

 manf=AndroidManifest.xml newverfull=`svnversion` newvers=`echo $newverfull | sed 's/[^0-9].*$//'` vers=`sed -n '/versionCode=/s/.*"\([0-9][0-9]*\)".*/\1/p' $manf` vername=`sed -n '/versionName=/s/.*"\([^"]*\)".*/\1/p' $manf` verbase=`echo $vername | sed 's/\(.*\.\)\([0-9][0-9]*\).*$/\1/'` newvername=$verbase$newverfull sed /versionCode=/s/'"'$vers'"'/'"'$newvers'"'/ $manf | sed /versionName=/s/'"'$vername'"'/'"'$newvername'"'/ >new$manf && cp new$manf $manf && rm -f new$manf echo versionCode=$newvers versionName=$newvername 

Создайте или отредактируйте custom_rules.xml и добавьте следующее:

 <?xml version="1.0" encoding="UTF-8"?> <project name="custom_rules"> <xmlproperty file="AndroidManifest.xml" prefix="mymanifest" collapseAttributes="true"/> <target name="-pre-compile"> <exec executable="./incVersion" failonerror="true"/> </target> </project> 

Поэтому, если моя текущая версия svn – 82, я получаю это в AndroidManifest.xml:

 android:versionCode="82" android:versionName="2.1.82"> 

Когда я хочу выпустить новую версию, я обычно обновляю первые части versionName, но даже если я забуду, последняя часть versionName (которая отображается в моей активной активности) всегда скажет мне, какая версия svn была построена из , Кроме того, если я не проверил изменения, номер версии будет 82M, а versionName будет примерно как 2.1.82M.

Преимущество в отношении простого увеличения номера версии каждый раз, когда выполняется сборка, состоит в том, что число остается под контролем и может быть напрямую связано с конкретной версией svn. Очень полезно при исследовании ошибок в других версиях.

FWIW, я смог обновить значение версии сборки в шести строках python:

 #!/bin/env python import os from xml.dom.minidom import parse dom1 = parse("AndroidManifest.xml") dom1.documentElement.setAttribute("android:versionName","%build.number%") f = os.open("AndroidManifest.xml", os.O_RDWR) os.write( f, dom1.toxml() ) 

Основываясь на ответе Чарльза , следующий шаг увеличивает существующую версию сборки:

 #!/usr/bin/python from xml.dom.minidom import parse dom1 = parse("AndroidManifest.xml") oldVersion = dom1.documentElement.getAttribute("android:versionName") versionNumbers = oldVersion.split('.') versionNumbers[-1] = unicode(int(versionNumbers[-1]) + 1) dom1.documentElement.setAttribute("android:versionName", u'.'.join(versionNumbers)) with open("AndroidManifest.xml", 'wb') as f: for line in dom1.toxml("utf-8"): f.write(line) 

Receipe:

Чтобы автоматически установить атрибут android: versionCode элемента манифеста в AndroidManifest.xml, установленном на текущее время (с эпохи в секундах, полученное из оболочки unix) каждый раз, когда вы запускаете сборку, добавьте это в свою цель -pre-build в custom_rules.xml Файл Android.

 <target name="-pre-build"> <exec executable="date" outputproperty="CURRENT_TIMESTAMP"> <arg value="+%s"/> </exec> <replaceregex file="AndroidMainfest.xml" match="android:versionCode=.*" replace='android:versionCode="${CURRENT_TIMESTAMP}"' /> </target> 

Тест подтверждения :

Получите атрибут versionCode сгенерированного файла apk, используя следующую команду оболочки из каталога проектов Android:

 $ANDROID_SDK/build-tools/20.0.0/aapt dump badging bin/<YourProjectName>.apk | grep versionCode 

И сравнить его с текущей датой, возвращаемой командой оболочки: date +%s . Разница должна равняться периоду времени в секундах между двумя вышеуказанными шагами подтверждения.

Преимущества такого подхода:

  1. Независимо от того, запущена ли сборка из командной строки или Eclipse, она обновит версию Code.
  2. VersionCode гарантированно будет уникальным и увеличится для каждой сборки
  3. Код версии может быть преобразован в обратном порядке в приблизительное время сборки, если вам это нужно
  4. Вышеупомянутый скрипт заменяет любое текущее значение versionCode, равное 0, и не требует наличия держателя макроса (например, -build_id-).
  5. Поскольку значение обновляется в файле AndroidManifest.xml, вы можете проверить его на управление версиями и сохранить фактическое значение, а не некоторый макрос (например, -build_id-).

Основываясь на ответе Роки, я немного расширил этот скрипт python, чтобы увеличить также версию Code, работает для меня на Eclipse (интегрирован в cczzl большой учебник ) и Mac OSX

 #!/usr/bin/python from xml.dom.minidom import parse dom1 = parse("AndroidManifest.xml") oldVersion = dom1.documentElement.getAttribute("android:versionName") oldVersionCode = dom1.documentElement.getAttribute("android:versionCode") versionNumbers = oldVersion.split('.') versionNumbers[-1] = unicode(int(versionNumbers[-1]) + 1) dom1.documentElement.setAttribute("android:versionName", u'.'.join(versionNumbers)) dom1.documentElement.setAttribute("android:versionCode", str(int(oldVersionCode)+1)) with open("AndroidManifest.xml", 'wb') as f: for line in dom1.toxml("utf-8"): f.write(line) 

Также не забудьте chmod +x autoincrement.py и убедитесь, что у вас есть правильный путь к python в первой строке (в зависимости от вашей среды), как указал сулай

Я сделал что-то подобное, но написал его как приложение Desktop AIR вместо некоторого внешнего C # (не чувствовал себя установкой другой системы сборки). Создайте это приложение Flex / ActionScript и измените путь к вашему файлу, создайте его как автономное настольное приложение. Он перезаписывает часть 1.2.3 вашего файла.

  <?xml version="1.0" encoding="utf-8"?> <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="371" height="255" applicationComplete="Init();"> <fx:Declarations> <!-- Place non-visual elements (eg, services, value objects) here --> </fx:Declarations> <fx:Script> <![CDATA[ public function Init():void { import flash.filesystem.File; import flash.filesystem.FileMode; import flash.filesystem.FileStream; var myFile:File = new File("D:\\Dropbox\\Projects\\My App\\src\\Main-app.xml"); var fileStream:FileStream = new FileStream(); fileStream.open(myFile, FileMode.READ); var fileContents:String = fileStream.readUTFBytes(fileStream.bytesAvailable); var startIndex:Number = fileContents.indexOf("<versionNumber>"); var numberIndex:Number = startIndex + 15; var endIndex:Number = fileContents.indexOf("</versionNumber>"); if (startIndex == -1 || endIndex == -1) return; var versionNumber:String = fileContents.substr(numberIndex, endIndex - numberIndex); var versionArr:Array = versionNumber.split("."); var newSub:Number = Number(versionArr[2]); newSub++; versionArr[2] = newSub.toString(); versionNumber = versionArr.join("."); var newContents:String = fileContents.substr(0, startIndex) + "<versionNumber>" + versionNumber + "</versionNumber>" + fileContents.substr(endIndex + 16); fileStream.close(); fileStream = new FileStream(); fileStream.open(myFile, FileMode.WRITE); fileStream.writeUTFBytes(newContents); fileStream.close(); close(); } ]]> </fx:Script> <s:Label x="10" y="116" width="351" height="20" fontSize="17" text="Updating My App Version Number" textAlign="center"/> </s:WindowedApplication> 

Я смог выработать свое собственное решение из приведенной информации. В случае, если это полезно для кого-то, это мой сценарий bash для обновления атрибутов versionCode и versionName при использовании GIT VCS в Linux.

Мой скрипт для редактирования файла AndroidManifest.xml выглядит так:

 #/bin/bash CODE=`git tag | grep -c ^v` NAME=`git describe --dirty` COMMITS=`echo ${NAME} | sed -e 's/v[0-9\.]*//'` if [ "x${COMMITS}x" = "xx" ] ; then VERSION="${NAME}" else BRANCH=" (`git branch | grep "^\*" | sed -e 's/^..//'`)" VERSION="${NAME}${BRANCH}" fi cat AndroidManifest.template.xml \\ | sed -e "s/__CODE__/${CODE}/" \\ -e "s/__VERSION__/${VERSION}/" > AndroidManifest.xml exit 0 

Он анализирует файл шаблона (AndroidManifest.template.xml) и заменяет строки «__VERSION__» и «__CODE__» более подходящими значениями:

  • «__CODE__» заменяется счетчиком количества тегов в репозитории Git, который начинается с одного строчного V и за ним следует последовательность цифр и точек. Это похоже на большинство строк версии: «v0.5», «v1.1.4» и т. Д.
  • «__VERSION__» заменяется комбинацией вывода команды «git describe» и, если не «чистой» сборки, веткой, на которой она была построена.

С помощью «чистой» сборки я подразумеваю, что все компоненты находятся под контролем версий, а их последняя фиксация отмечена. «Git describe –dirty» сообщит номер версии, основанный на последнем доступном аннотированном теге в вашей последней фиксации в текущей ветке. Если с этого тега есть коммиты, сообщается количество этих коммитов, как сокращенное имя объекта вашего последнего коммита. Параметр «–dirty» добавит «-dirty» к вышеуказанной информации, если какие-либо файлы изменены, которые находятся под управлением версиями, были изменены.

Поэтому AndroidManifest.xml больше не должен находиться под управлением версиями, и вы должны редактировать файл AndroidManifest.template.xml. Начало вашего файла AndroidManifest.template.xml выглядит примерно так:

 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.packagename" android:versionCode="__CODE__" android:versionName="__VERSION__" > 

Надеюсь, это полезно кому-то

Все кредиты идут на ckoz, но я отладил свою собственную реализацию в c #. Я думаю, что это немного быстрее и не есть ошибки, потому что если что-то пойдет не так, возможно, что-то неправильно настроено, и я должен знать об этом.

 namespace AndroidVersionCodeAutoIncrement { using System.IO; using System.Text.RegularExpressions; public class Program { private static readonly Regex VersionCodeRegex = new Regex("android:versionCode=\"(?<version>.*)\"", RegexOptions.Compiled); public static void Main() { using (var manifestFileStream = File.Open("AndroidManifest.xml", FileMode.Open, FileAccess.ReadWrite)) using (var streamReader = new StreamReader(manifestFileStream)) { var manifestFileText = streamReader.ReadToEnd(); var firstMatch = VersionCodeRegex.Match(manifestFileText); if (firstMatch.Success) { int versionCode; var versionCodeValue = firstMatch.Groups["version"].Value; if (int.TryParse(versionCodeValue, out versionCode)) { manifestFileText = VersionCodeRegex.Replace(manifestFileText, "android:versionCode=\"" + (versionCode + 1) + "\"", 1); using (var streamWriter = new StreamWriter(manifestFileStream)) { manifestFileStream.Seek(0, SeekOrigin.Begin); streamWriter.Write(manifestFileText); manifestFileStream.SetLength(manifestFileText.Length); } } } } } } } 

Для тех, кто находится на OSX и хочет использовать Python, но не потерять форматирование XML, которое происходит при синтаксическом анализе с помощью синтаксического анализатора python XML, вот скрипт python, который будет выполнять инкрементное на основе регулярного выражения, которое сохраняет форматирование:

 #!/usr/bin/python import re f = open('AndroidManifest.xml', 'r+') text = f.read() result = re.search(r'(?P<groupA>android:versionName=")(?P<version>.*)(?P<groupB>")',text) version = str(float(result.group("version")) + 0.01) newVersionString = result.group("groupA") + version + result.group("groupB") newText = re.sub(r'android:versionName=".*"', newVersionString, text); f.seek(0) f.write(newText) f.truncate() f.close() 

Код был основан на ответе @ckozl, как раз было сделано в python, поэтому для этого вам не нужно создавать исполняемый файл. Просто назовите скрипт autoincrement.py, поместите его в ту же папку с файлом manifest.xml, а затем выполните шаги, которые ckozl описал выше!

Если вы хотите обновить AndroidManifest.xml, чтобы использовать определенный номер версии, возможно, из системы сборки, то вы можете использовать проект, который я просто нажал на GitHub: https://github.com/bluebirdtech/AndroidManifestVersioner

Это базовое приложение командной строки .NET, использование:

 AndroidManifestVersioner <path> <versionCode> <versionName>. 

Благодаря другим плакатам для их кода.

Вот версия Java, для чего она стоит. Также обрабатывает несколько манифестаций.

 String directory = "d:\\Android\\workspace\\"; String[] manifests = new String[] { "app-free\\AndroidManifest.xml", "app-donate\\AndroidManifest.xml", }; public static void main(String[] args) { new version_code().run(); } public void run() { int I = manifests.length; for(int i = 0; i < I; i++) { String path = directory + manifests[i]; String content = readFile(path); Pattern versionPattern = Pattern.compile( "(.*android:versionCode=\")([0-9]+)(\".*)", Pattern.DOTALL ); Matcher m = versionPattern.matcher(content); if (m.matches()) { int code = Integer.parseInt( m.group(2) ) + 1; System.out.println("Updating manifest " + path + " with versionCode=" + code); String newContent = m.replaceFirst("$1" + code + "$3"); writeFile(path + ".original.txt", content); writeFile(path, newContent); } else { System.out.println("No match to update manifest " + path); } } } 

Если вы используете gradle, то вы можете использовать определенную versionName и versionCode очень просто в build.gradle . Вы можете использовать git commit count как увеличивающееся число для идентификации сборки.

Вы также можете использовать эту библиотеку: https://github.com/rockerhieu/Versionberg .

Intereting Posts
Есть ли способ проверить, поддерживает ли Android-устройство openGL ES 2.0? Веб-просмотр Android не может отображать видео youtube, встроенное через iframe Как установить параметры расположения RelativeLayout в коде не в xml Андроидная анимация не завершена inAnimationEnd Retrofit 2.0 как распечатать полный ответ json? Как сохранить данные EditText при изменении ориентации? Добавить Retrofit Requestinterceptor с кинжалом во время выполнения Ошибка Android Pre Compiler? Получить точки широты, долготы Каждые 10 метров между двумя разными местоположениями в андроиде Видеозапись камеры2 Программируемое подключение к Bluetooth-гарнитуре из приложения для Android Почему ButterKnife использует метод DebouncingOnClickListener для методов @OnClick? В proguard, как сохранить набор имен методов классов? Фрагментная активность – приложение умерло, состояние не сохранено Отображение только одного элемента в режиме ресайклера