web-dev-qa-db-ja.com

Android appのバージョンコードを自動インクリメント

eclipseでAndroidアプリケーションをビルドするたびにバージョンコードを自動インクリメントする方法はありますか?

http://developer.Android.com/guide/publishing/versioning.html によると、AndroidManifest.xmlのバージョンコードを手動でインクリメントする必要があります。

各ビルドの前にスクリプトを実行する必要があることを理解しています。 AndroidManifest.xmlファイルを解析し、バージョン番号を見つけてインクリメントし、ビルド自体が開始する前にファイルを保存します。ただし、Eclipseがビルドの前後に実行スクリプトをサポートする方法と方法を見つけることができませんでした。

私は この記事 ant builderの設定について見つけましたが、これは正確にはAndroidではなく、これはAndroidの事前定義された構築手順を台無しにすることを恐れていますか?

よくある問題ですが、どのように解決しましたか?

まあ、これは手動で行うことができますが、この雑用をするのを忘れるとすぐに、同じ番号の異なるバージョンを取得し、バージョン管理全体はほとんど意味がありません。

62
iseeall

だから、私はこのように見える:

提示する記事に応じて、このタスク(ターゲット?)にantを使用します。

  1. マニフェストの解析(XMLの解析)
  2. 古いバージョンのフォームマニフェストを取得し、それを増やす/リポジトリからバージョンを取得する
  3. マニフェストに新しいバージョンを保存する
  4. build Android app。

しかし、私の場合、私は通常、アプリケーションをデプロイまたは配布するときにTagのリビジョンに基づいた値でこのフィールドを埋めます。

4
aeracode

これを達成しました。そして、次の人のために(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 { }
        }
    }
}

aside:どんなc-sharpコンパイラーでもこのアプリをビルドできます。VisualStudioもWindowsも必要ありません

  1. まだお持ちでない場合は、.NETランタイムをインストールしてください( Monoは動作します、リンク )( MSの.NETフレームワーク2.0へのリンク、2.0は最小のダウンロードで、すべてのバージョン> = 2.0は大丈夫です
  2. このコードを*.csファイルにコピーします(私は私の名前を付けました:AndroidAutoIncrementVersionCode.cs
  3. コマンドプロンプトを開き、*.csファイルを作成した場所に移動します
  4. このコマンドを使用してファイルをビルドします(Windowsでは、Monoに似ていますが、パスをコンパイラに変更します):c:\Windows\Microsoft.NET\Framework\v2.0.50727\csc AndroidAutoIncrementVersionCode.cs(参照: 。NET または Mono 詳細はこちら)
  5. おめでとう、ツールなしでC#アプリをビルドしただけで、同じディレクトリにAndroidAutoIncrementVersionCode.exeが自動的に生成されているはずです

    **走行距離は異なる場合があり、パスは異なる場合があり、購入は不要であり、禁止されている場合は無効です。C#が素晴らしいため、これを追加しました。人々は誤ってMSロックインを持っていると思います私はあなたのためにそれをするつもりはありません;)。ちなみに、.NETコンパイラのどのバージョンでも動作します。コードを最小公分母に適合させました... *

end aside

2)ビルドプロセス中に実行可能ファイルを実行します。a)プロジェクトプロパティに移動します

go to project properties

b)プロパティで、「ビルダー」->「新規...」に移動します

Eclipse properties screen

c)[プログラム]を選択します

choose program

d)[メイン]タブでプログラムの場所を選択し(作業ディレクトリも安全に設定します)、必要に応じて名前を付けます。

edit configuration - main

e)[更新]タブで、[完了時にリソースを更新]および[選択したリソース]オプションを選択します-これにより、マニフェストが書き込まれた後に更新されます。

edit configuration - refresh

f)[ビルドオプション]タブで、入力と出力がないため[コンソールの割り当て]をオフにし、[手動ビルド中]と[自動ビルド中]のみを選択すると、[クリーン後]のチェックを外します。次に、「関連するリソースのワーキングセットを指定する」を選択し、「リソースの指定...」ボタンをクリックします。 [ワーキングセットの編集]ダイアログで、ダイアログで[AndroidManifest.xml]ファイルを見つけて確認し、[完了]をクリックします。

edit configuration - build optionsedit working set

f)「構成ダイアログの編集」内の「OK」をクリックし、アプリのプロパティで新しく作成したビルダーを選択し、リストの一番上になるまで「アップ」をクリックし続けると、自動インクリメントが実行されますまず、偶発的な非同期状態や再構築を引き起こしません。作成した新しいビルダーがリストの一番上になったら、[OK]をクリックして完了です。

edit configuration - hit okenter image description here

112
ckozl

* nixシステムに適したこのシェルスクリプトは、versionCodeとversionNameの最後のコンポーネントを現在のSubversionリビジョンに設定します。 NetbeansをNBAndroidで使用しており、custom_rules.xmlのターゲット-pre-compileからこのスクリプトを呼び出しています。

このスクリプトを、AndroidManifest.xmlと同じディレクトリのincVersionというファイルに保存し、実行可能にします: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の最後の部分(Aboutアクティビティで公開される)は常に、それがどのsvnリビジョンから作成されたかを教えてくれます。また、変更をチェックインしていない場合、リビジョン番号は82Mになり、versionNameは2.1.82Mのようになります。

ビルドが行われるたびにバージョン番号を単純にインクリメントすることの利点は、番号が制御下にあり、特定のsvnリビジョンに直接関連付けることができることです。最新リリース以外のバグを調査する際に非常に役立ちます。

9
Clyde

FWIW、私はPythonの6行でビルドバージョン値を更新することができました:

#!/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() )
7
user1048976

Charles 'answer に基づいて、以下は既存のビルドバージョンをインクリメントします。

#!/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)
6
Rocky

レシピ:

ビルドを実行するたびに、AndroidManifest.xmlのマニフェスト要素のAndroid:versionCode属性を現在の時間(Unix Shellから取得したEpochから秒単位)に自動的に設定するには、これをcustom_rules.xmlの-pre-buildターゲットに追加します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>

確認テスト

Androidプロジェクトディレクトリから次のシェルコマンドを使用して、生成されたapkファイルのversionCode属性を取得します。

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

シェルコマンドから返された現在の日付と比較します:date +%s差は、上記の2つの確認ステップ間の秒単位の期間に等しくなければなりません。

このアプローチの利点:

  1. ビルドがコマンドラインから開始されるか、Eclipseから開始されるかに関係なく、バージョンコードが更新されます。
  2. VersionCodeは、ビルドごとに一意で増加することが保証されています
  3. VersionCodeは、必要に応じて、おおよそのビルド時間にリバースエンジニアリングできます。
  4. 上記のスクリプトは、versionCodeの現在の値(0であっても)を置き換え、マクロプレースホルダー(-build_id-など)を必要としません。
  5. 値はAndroidManifest.xmlファイルで更新されるため、バージョン管理にチェックインでき、一部のマクロ(-build_id-など)ではなく、実際の値が保持されます。
3
Brenton Camac

Rocky's answer を強化し、pythonスクリプトを少し強化してversionCodeも増やし、Eclipseで動作します( ckozl great tutorial に従って統合)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を忘れずに、 sulai が示すように、最初の行で(環境に応じて)pythonへの正しいパスがあることを確認してください。

2
ursimon

与えられた情報から自分の解決策を考え出すことができました。 LinuxでGIT VCSを使用しているときにversionCodeおよびversionName属性を更新するためのbashスクリプトが、誰かにとって役立つ場合です。

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__」は、単一の小文字のVで始まり、一連の数字とドットが続くGitリポジトリ内のタグの数のカウントに置き換えられます。これは、「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__" >

これが誰かに役立つことを願っています

1
Dobbo

すべてのクレジットは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);
                        }
                    }
                }
            }
        }
    }
}
1

OSX上にあり、Pythonを使用したいが、解析がpython XMLパーサーによって行われる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が上記で説明した手順を実行してください!

1
Lefteris

同様のことをしましたが、外部C#の代わりにデスクトップAIRアプリとして作成しました(別のビルドシステムをインストールするとは感じませんでした)。この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 (e.g., 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>
1
Per

以下に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);
        }
    }
}
0
3c71

AndroidManifest.xmlを更新して、おそらくビルドシステムからの特定のバージョン番号を使用する場合は、GitHubにプッシュしたばかりのプロジェクトを使用できます。 https://github.com/bluebirdtech/AndroidManifestVersioner

基本的な.NETコマンドラインアプリであり、使用方法は次のとおりです。

AndroidManifestVersioner <path> <versionCode> <versionName>.

他のポスターのコードに感謝します。

0

Gradleを使用している場合、build.gradleversionNameversionCodeを簡単に特定できます。ビルドを識別するために、Gitコミットカウントを増加数として使用できます。

このライブラリを使用することもできます: https://github.com/rockerhieu/Versionberg

0
Hieu Rocker