BAM

How to generate your mobile app build number?

When developing a mobile app, you’ll build your app multiple time. To differentiate each iteration from the other, we use a unique identifier called the build number. This is not to be confused with the version number.

Let’s say you’re working on your first app release. It’ll be the 1.0.0 version. 1.0.0 is your version number. Now when working on this version, you’ll find some bugs and will want to fix them. So you’ll build multiple iterations of the same 1.0.0 version. Each iteration will have a separate build number. This can be useful when debugging: if a tester is reporting a bug on your app 1.0.0, you need to know which build is containing the bug hence the build number.

On each of my projects, the build number for my iOS and Android app was always initialized to 1. Then, we had to increment it manually for each release. This means one could forget to update it and before building a new app release. We’d end up unable to upload the app with the same error: “An app with the same build number already exists”. How to manage this build number you say?

The build number rules

Apple and Google have one critical rule: the build number always has to increase and has a max value.

  • For Google, the versionCode has to be inferior to 2100000000 as mentioned in the documentation
  • For Apple, the CFBundleVersion cannot be longer than 18 characters

The first idea: increment the build number automatically

My first idea was to have a script that:

  • reads the current build number
  • computes the new value
  • writes it

We have two problems with this solution.

First, we read the current build number from a file. Changing the build number location means updating our script.

Second, the build number does not bring any information. Imagine that you have an exception in Sentry related to build number 5. Well, that’s not the most helpful information. It’s just an arbitrary number.

So that’s off the picture. Let’s try to give our build number a meaning.

The second idea: derive the build number from the version number

My second idea was to take the version number and compute the build number from it.

1.2.0 → 001002000

Now our build number has meaning, unfortunately, it is the same as the version number. And we still have to read the version number from a file. Furthermore, we can only build one app per app version. In this case, one app version = one build number.

So what can we do next?

We could try to add three digits at the end. Those digits would represent the number of times we built this app version. We’d end up storing the number of builds again.

The third idea: use a timestamp as a build number

What is always going forward? Not taking into account Back to the future, **time is a valid answer. So, why not use a timestamp as a build number?

  • It gives us an indication of when the app was built
  • It always increases
  • We can generate it on the go, no need to store

But does it work with the max value constraint? Let’s do the math!

For Apple, 10^18s puts us 31 billion years in the future. I’m not much of a gambler but we should be safe.

For Google though, 2100000000 puts us in 2036. A bit too early in my opinion.

So how can we correct that? Let’s divide our timestamp by 10. It means that we won’t be able to upload apps to Google after 2635. I think it’s safe to say, the rules will have changed by then.

It also means that two versions of the same app, built in a 10 seconds interval, will have the same build number. A small comment and an explanation should take care of that.

How to implement it

At BAM, we use fastlane to help us deploy our app. I created a lane to increment the build number of your app. First, you should install the ++code>fastlane-plugin-android_versioning ++/code>

++pre>++code>bundle exec fastlane add_plugin fastlane-plugin-android_versioning ++/code>++/pre>

Then you can create the lane.

++pre>++code>lane :auto_increment_build_number do platform=lane_context[SharedValues::PLATFORM_NAME] # We divide by 10 to allow build number until 2635 for Android build_number = Time.now.to_i / 10 if platform == :ios increment_build_number( build_number: build_number, xcodeproj: "PATH_TO_THE_XCODEPROJ" ) else increment_version_code( version_code: build_number, ) end end ++/code>++/pre>


Finally, you can add it to your build workflow.

++pre>++code>platform :android do # Replace :android with :ios if needed lane :build do |options| increment_build_and_commit # Rest of the workflow responsible for building the app end end ++/code>++/pre>


Now if you run the following command:
++pre>++code>bundle exec fastlane android ++/code>++/pre>

Before building the app, fastlane will update the build number.


Final answer

My recommendation is to use a timestamp divided by 10 as a build number. This way:

  • No need to store it, it’s generated on the go
  • It always increases
  • It won’t be invalid until 2635

Développeur Mobile ?

Rejoins nos équipes