android
programming
application version
duplicate
code example

Get application version programmatically in android

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Android applications define a version name (a human-readable string like "2.4.1") and a version code (an integer used by the Play Store for update ordering) in the Gradle build file. At runtime you often need to display the version in an "About" screen, include it in API request headers, or log it for crash diagnostics. The PackageManager API provides access to both values.

Reading Version Info in Kotlin

The PackageManager.getPackageInfo() method returns a PackageInfo object that contains both versionName and versionCode.

kotlin
1import android.content.Context
2import android.content.pm.PackageInfo
3import android.content.pm.PackageManager
4import android.os.Build
5
6fun getAppVersion(context: Context): Pair<String, Long> {
7    val packageInfo: PackageInfo = context.packageManager
8        .getPackageInfo(context.packageName, 0)
9
10    val versionName: String = packageInfo.versionName ?: "unknown"
11
12    val versionCode: Long = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
13        packageInfo.longVersionCode
14    } else {
15        @Suppress("DEPRECATION")
16        packageInfo.versionCode.toLong()
17    }
18
19    return Pair(versionName, versionCode)
20}

The longVersionCode property was introduced in API 28 (Android 9 Pie). For apps that support older API levels, the code above falls back to the deprecated versionCode integer and converts it to a Long for a consistent return type.

Reading Version Info in Java

The same approach works in Java with slightly more verbose syntax.

java
1import android.content.pm.PackageInfo;
2import android.content.pm.PackageManager;
3import android.os.Build;
4
5public String getVersionName() {
6    try {
7        PackageInfo info = getPackageManager()
8            .getPackageInfo(getPackageName(), 0);
9        return info.versionName;
10    } catch (PackageManager.NameNotFoundException e) {
11        return "unknown";
12    }
13}
14
15public long getVersionCode() {
16    try {
17        PackageInfo info = getPackageManager()
18            .getPackageInfo(getPackageName(), 0);
19        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
20            return info.getLongVersionCode();
21        } else {
22            return info.versionCode;
23        }
24    } catch (PackageManager.NameNotFoundException e) {
25        return -1;
26    }
27}

In Java you must handle the checked NameNotFoundException. While this exception is unlikely when querying your own package, the compiler requires it to be caught or declared.

Where Version Values Come From

The version values originate in your module-level build.gradle or build.gradle.kts file.

kotlin
1// build.gradle.kts
2android {
3    defaultConfig {
4        versionCode = 42
5        versionName = "2.4.1"
6    }
7}

The versionCode must be incremented with every release uploaded to the Play Store. The versionName is the string shown to users and follows any versioning scheme you prefer, such as semantic versioning.

Displaying the Version in the UI

A common use case is showing the version on a settings or "About" screen.

kotlin
// In an Activity or Fragment
val (versionName, versionCode) = getAppVersion(requireContext())
binding.versionLabel.text = "Version $versionName ($versionCode)"

You can also define a string resource with a placeholder to support localization.

xml
<!-- res/values/strings.xml -->
<string name="app_version_format">Version %1$s (Build %2$d)</string>
kotlin
binding.versionLabel.text = getString(
    R.string.app_version_format, versionName, versionCode
)

Sending Version Info with Network Requests

Including the app version in HTTP headers helps backend teams diagnose issues tied to specific releases.

kotlin
1import okhttp3.Interceptor
2import okhttp3.Response
3
4class VersionInterceptor(private val context: Context) : Interceptor {
5    override fun intercept(chain: Interceptor.Chain): Response {
6        val (versionName, versionCode) = getAppVersion(context)
7        val request = chain.request().newBuilder()
8            .addHeader("X-App-Version", "$versionName+$versionCode")
9            .build()
10        return chain.proceed(request)
11    }
12}

Attach this interceptor to your OkHttp client so every request automatically includes the version header.

Using BuildConfig as an Alternative

The BuildConfig class generated during compilation also contains version information, without requiring PackageManager queries.

kotlin
val versionName = BuildConfig.VERSION_NAME
val versionCode = BuildConfig.VERSION_CODE

This approach is simpler but has a limitation: in multi-module projects, BuildConfig belongs to each module individually. Library modules get their own BuildConfig that may not reflect the app-level version. Use PackageManager when you need the definitive installed version, and BuildConfig when you want quick access within the app module itself.

Common Pitfalls

  • Not handling NameNotFoundException in Java: Although querying your own package name rarely fails, the compiler enforces the checked exception and your code will not compile without a try-catch block.
  • Using deprecated versionCode on API 28 and above: The versionCode integer field is deprecated starting at API 28. Use longVersionCode or getLongVersionCode() to avoid lint warnings and future compatibility issues.
  • Relying on BuildConfig in library modules: A library module's BuildConfig.VERSION_NAME reflects the library version, not the host app version. Always use PackageManager if you need the actual installed app version.
  • Hardcoding version strings: Never duplicate the version string in code or resources. Always read it from the build system at runtime to ensure a single source of truth.
  • Forgetting to increment versionCode before release: The Play Store rejects uploads where the version code has not increased. Automate this with a CI script or Gradle task to prevent failed uploads.

Summary

  • Use PackageManager.getPackageInfo() to read versionName and versionCode at runtime.
  • On API 28 and above, use longVersionCode instead of the deprecated versionCode integer.
  • Define version values in build.gradle.kts as the single source of truth.
  • Use BuildConfig.VERSION_NAME for quick access within the app module, but prefer PackageManager for cross-module accuracy.
  • Include the app version in HTTP headers to help backend teams correlate issues with specific releases.
  • Always handle NameNotFoundException in Java even though it is unlikely for your own package.

Course illustration
Course illustration