Auto increment version code in Android app

后端 未结 15 990
忘掉有多难
忘掉有多难 2020-12-07 08:22

is there a way to auto-increment the version code each time you build an Android application in Eclipse?

According to http://developer.android.com/guide/publishing/v

相关标签:
15条回答
  • 2020-12-07 08:26

    So, I see it like this:

    Depending on article that you present, use ant for this tasks (targets?).

    1. parse Manifest (parse XML)
    2. get old version form manifest and increase it/get version from repo
    3. store new version in manifest
    4. build android app.

    But im my case I usually fill this field by value based on Tag's revision when I deploy or distribute application.

    0 讨论(0)
  • 2020-12-07 08:26

    All credit goes to ckoz, but I writed my own implementation in c#. I think it's a little faster and doesn't eat errors because If something goes wrong probably something is wrongly configured and I should know about it.

    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);
                            }
                        }
                    }
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-07 08:29

    I accomplished this. And here's how I did it for the next guy (using Eclipse):

    1) Create an external console executable that is going to write a new version code to the AndroidManifest.xml: (mine is in 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: any c-sharp compiler can build this app, you don't need Visual Studio or even Windows

    1. if you don't have it already, install .NET runtime (Mono will work, link) (link to MS's .NET framework 2.0, 2.0 is the smallest download, any version >= 2.0 is fine)
    2. copy this code to a *.cs file (i named mine: AndroidAutoIncrementVersionCode.cs)
    3. open a command prompt and navigate over to where you made your *.cs file
    4. build the file using this command (on Windows, similar for Mono but change path to compiler): c:\Windows\Microsoft.NET\Framework\v2.0.50727\csc AndroidAutoIncrementVersionCode.cs (see: .NET or Mono for more info)
    5. congrats, you just built a C# app without any tools, it should have generated AndroidAutoIncrementVersionCode.exe in the same directory automatically

      **mileage may vary, paths might be different, no purchase required, void where prohibited, i added this because C# is awesome, and people mistakenly think it has MS lock-in, you could just as easily translate this to another language (but i'm not going to do that for you ;). incidentally any version of any .NET compiler will work, i adapted the code for the least common denominator...*

    end aside

    2) Run the executable during the build process: a) Go to the project properties

    go to project properties

    b) In the properties, Go to "Builders" -> "New..."

    Eclipse properties screen

    c) Choose "Program"

    choose program

    d) In the "Main" tab select the program location (I also set the working directory to be safe) and give it a name if you wish.

    edit configuration - main

    e) In the "Refresh" tab select the "Refresh resources upon completion" and "The selected resource" option - this will refresh the manifest after we write it.

    edit configuration - refresh

    f) In the "Build Options" tab you can turn off "Allocate Console" as you have no input and output and then select only "During manual builds" and "During auto builds" deselect "After a Clean" if it is checked. Then select "Specify a working set of relevant resources" and click the "Specify Resources..." button. In the "Edit Working Set" dialog, locate your "AndroidManifest.xml" file in the dialog and check it, then hit "Finish"

    edit configuration - build options edit working set

    f) Now hit "OK" inside the "Edit Configuration Dialog" and in the properties for your App, select the newly created builder, and keep clicking "Up" until it is at the top of the list, this way the auto increment runs first, and doesn't trigger accidental out-of-sync states or rebuilds. Once the new builder you made is at the top of the list, click "OK" and you're finished.

    edit configuration - hit ok enter image description here

    0 讨论(0)
  • 2020-12-07 08:29

    Receipe:

    To automatically have the android:versionCode attribute of manifest element in AndroidManifest.xml set to the current time (from epoch in seconds, obtained from unix shell) everytime you run a build, add this to your -pre-build target in custom_rules.xml Android file.

    <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>
    

    Confirmation Test:

    Obtain the versionCode attribute of the generated apk file, using the following shell command from your Android project directory :

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

    and compare it to the current date returned from the shell command: date +%s The difference should equal the period of time in seconds between the two confirmation steps above.

    Advantages of this approach:

    1. Regardless of whether the build is started from command line or Eclipse, it will update the versionCode.
    2. The versionCode is guaranteed to be unique and increasing for each build
    3. The versionCode can be reverse-engineered into an approximate build time if you need it
    4. The above script replaces any present value of versionCode, even 0 and doesn't require a macro place holder (such as -build_id-).
    5. Because the value is updated in the AndroidManifest.xml file, you can check it in to version control and it will retain the actual value, not some macro (such as -build_id-).
    0 讨论(0)
  • 2020-12-07 08:36

    Here is the Java version for what it's worth. Also handling multiple manifests.

    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 讨论(0)
  • 2020-12-07 08:42

    For those that are on OSX and want to use Python, but not loose the XML formatting which when parsing is done by the python XML parser happens, here is a python script that will do the incremental based on regular expression, which keeps the formatting:

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

    The code was based on @ckozl answer, just was done in python so you don't need to create an executable for this. Just name the script autoincrement.py, place it in the same folder with the manifest.xml file and then do the steps that ckozl did describe above!

    0 讨论(0)
提交回复
热议问题