9

I am creating multiple apk's for each ABI, I did this to assign separate version code to each apk.

ext.abiCodes = ['armeabi-v7a':1, mips:2, x86:3]

import com.android.build.OutputFile
android.applicationVariants.all { variant ->
    variant.outputs.each { output ->
        def baseAbiVersionCode =
                project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))

        if (baseAbiVersionCode != null) {
            output.versionCodeOverride =
                    baseAbiVersionCode * 1000 + variant.versionCode
        }
    }
} 

This is my dafaultConfig, and the following versionCode is for universalApk

 defaultConfig {
        versionCode 74
        versionName "1.0.2"
}

I append the versionCode with each service request, I also display the versionCode in one of the activity. So i need the correct versionCode to perform these operations, I use this code to get versionCode

int versionCode = BuildConfig.VERSION_CODE;

Now the problem is that, it displays the versionCode that is stated in defaultConfig and not the one that actually represents the build.

I need to know that how can i get the versionCode that is assigned to this build, that may be some number greater than 1000, and not the one that is assigned in dafaultConfig

dev90
  • 7,187
  • 15
  • 80
  • 153

4 Answers4

8

To check version code you can use PackageInfo and PackageManager

try {
    PackageInfo pInfo = this.getPackageManager().getPackageInfo(getPackageName(), 0);
    String version = pInfo.versionName;   //version name
    int verCode = pInfo.versionCode;      //version code
} catch (PackageManager.NameNotFoundException e) {
    e.printStackTrace();
}
Ranjan
  • 1,326
  • 18
  • 38
3

You should not read build config file, build config file will display the default configuration.

You should use PackageInfo

  try {
            PackageInfo pInfo = this.getPackageManager().getPackageInfo(getPackageName(), 0);
            String version = pInfo.versionName;
            Log.e("name","name"+version);
            Log.e("Code","code"+pInfo.versionCode);
        }catch (Exception e){
            e.printStackTrace();
        }

Which will display 1001 for armeabi-v7a, 1002 for mips and 1003 for x86

lib4backer
  • 3,337
  • 3
  • 18
  • 16
1

I asked something similar here.

Since accessing BuildConfig.VERSION_CODE seems to be less expensive than accessing the PackageInfo, I thought in a workaround to keep using the BuildConfig.java to retrieve the versionCode in these situations, it's not as good as we had before with mergedFlavor.versionCode that overrides the BuildConfig.VERSION_CODE but since this change was made to improve the build time I'm more than happy to live with it.

First you should set the versionCode in each flavor instead of defaultConfig, example:

flavorDimensions 'default'

productFlavors {
    hellotest {
        versionCode 20
    }

    hellotest1 {
        versionCode 10
    }
}

Then and updating your code from above:

ext.abiCodes = ['armeabi-v7a':1, mips:2, x86:3]

import com.android.build.OutputFile
android.applicationVariants.all { variant ->
    // Get the versionCode statically defined in each flavor.
    def versionCode = variant.productFlavors.get(0).versionCode
    // Create a custom buildConfigField with the versionCode
    variant.buildConfigField('int', 'OVERRIDEN_VERSION_CODE', "${versionCode}")
    variant.outputs.each { output ->
        def baseAbiVersionCode =
                project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))

        if (baseAbiVersionCode != null) {
            output.versionCodeOverride =
                    baseAbiVersionCode * 1000 + variant.versionCode
                    // Update the BuildConfig.OVERRIDEN_VERSION_CODE with the new versionCode.
                    // OVERRIDEN_VERSION_CODE is just an example name, you can give the name you want.
                    variant.buildConfigField('int', 'OVERRIDEN_VERSION_CODE', "${output.versionCodeOverride}") 
        }
    }
} 

After this you will have the correct versionCode accessible through BuildConfig.OVERRIDEN_VERSION_CODE anywhere in the project.

João Zão
  • 170
  • 1
  • 11
  • Gradle Plugin version: `3.3.0-rc01`. ERROR: Could not find method buildConfigField() for arguments [int, VERSION_BUILD, 7] on ApkVariantOutputImpl_Decorated{apkData=FullSplit{type=FULL_SPLIT, fullName=exampleArm64-v8aDebug, filters=[FilterData{type=ABI, value=arm64-v8a}], versionCode=7, versionName=1.2.0}} of type com.android.build.gradle.internal.api.ApkVariantOutputImpl. – Savelii Zagurskii Nov 28 '18 at 15:49
  • how are you setting the buildConfigField? In case you want an int it should be something like this: `variant.buildConfigField 'int', 'VERSION_BUILD', '7'` Don't forget the ' – João Zão Nov 28 '18 at 16:08
  • I am trying to set an ABI `variant.buildConfigField('String', 'ABI', "\"\"")`. – Savelii Zagurskii Nov 28 '18 at 16:18
  • The error you got is not related with `variant.buildConfigField('String', 'ABI', "\"\"")` This `variant.buildConfigField('String', 'ABI', "\"\"")` works just fine you can try it in an empty project. – João Zão Nov 28 '18 at 16:25
  • Yeah, you are right. This was my fault. Do you by chance know how can I set a different build config value to each ABI I create? For now the solution you proposed sets the build config value just to the `flavorBuildType` (not to the specific outputs). I tried iterating over each output in a variant and tried to do `output.buildConfigField()` but it errors as there is no such method. Have you had such a problem? – Savelii Zagurskii Nov 28 '18 at 16:32
  • Not sure if I got it. Do you want to have multiple ABIs per variant in the buildConfig? – João Zão Nov 28 '18 at 16:37
  • I already have them. And I am already setting different version codes to each of the ABIs I create. For instance, I use `android.applicationVariants.all { variant -> variant.outputs.each { output -> output.versionCodeOverride = 0 } } /* depends on ABI */`. But I don't know how to set a specific value to build config depending on ABI. – Savelii Zagurskii Nov 28 '18 at 16:48
0

If you want to use BuildConfig, make sure you're importing the correct one for your build and not one which belongs to a different module/lib.

That said, a more conflict-proof method is certainly using the PackageManger as @lib4 suggested, but with a slight tweak: Using pInfo.getLongVersionCode() in Java or pInfo.longVersionCode in Kotlin instead of pInfo.versionCode (which was deprecated in API 28)

try {
    val pInfo =this.packageManager.getPackageInfo(packageName, 0)
    val version = pInfo.versionName;   //version name
    val versionCode = pInfo?.longVersionCode   //version code
} catch (e: PackageManager.NameNotFoundException) {
    e.printStackTrace();
}
devanshu_kaushik
  • 929
  • 11
  • 30