I was compiling my React Native App for Android having enableSeparateBuildPerCPUArchitecture to false but since I read if I set to true, then the app will reduce like 4mb and it's true.
So my current version code was 9 so I set to 10 the new one and when I created a new release with that option to true I uploaded it to my Google Play dashboard and I realised the new version code is not 10 but is 1048586 :/
Fortunately I don't published that version and I just removed it but I'm wondering what happened and if that's normal and if I create a new version after that, the number will increate just 1 unit like 1048586 to 1048587?
Thanks!
EDIT
I found the line of code that set the version code
applicationVariants.all { variant ->
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
// http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
def versionCodes = ["armeabi-v7a":1, "x86":2]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
}
}
}
But still I couldn't find the real reason about why it's necessary to increase the version code to a big number
"We need this because each APK in the ABI requires a separate version code which goes up each time the app updates. This code block adds a different constant for each architecture to your base version code. Each APK then get their own distinct values which are unlikely to overlap. For more details take a look at the Android documentation for ABI splits."
https://reactnative.thenativebits.com/courses/upgrading-react-native/upgrade-to-react-native-0.59/
Therefore you need to "give up control" of your versionCode to the build system and rely on the versionName instead.
Let's assume you multiplied with a small number .... like say 2.
So apk version codes for ["armeabi-v7a":1, "x86":2] will be
When you set the android: default version code to be 1:
armeabi-v7a: 1 * 2 + 1 = 3
x86: 2 * 2 + 1 = 5
Let's say you have another release now and decide to to use default version code to be 2. Hence version codes for architectures:
armeabi-v7a: 1 * 2 + 2 = 4
x86: 2 * 2 + 2 = 6
Now in the next release when you use default version code of 3, you'll notice that we run into issues. Here, version codes for architectures:
armeabi-v7a: 1 * 2 + 3 = 5 (CONFLICTS with x86 version code for 1st release)
x86: 2 * 2 + 3 = 7
PS: The above answer is solely based on my understanding/interpretation and the original authors could very well have had an entirely different reason.
change - def enableSeparateBuildPerCPUArchitecture from true to false after that whenever you create a build it should be increment with +1 only.
Related
I just made a new Android bundle for my React Native app. I manually updated the version code from 90 to 91 in android/app/build.gradle, but now that I am trying to upload to Play Store, the version code is 3145819 (I expected to see 91)
build.gradle:
defaultConfig {
applicationId "com.myapp"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 91
versionName "4.1.0"
multiDexEnabled true
missingDimensionStrategy "RNN.reactNativeVersion", "reactNative57_5"
resValue "string", "build_config_package", "com.myapp"
}
I use this command to bundle:
./gradlew bundleProdRelease --console plain
Not sure why this is happening, and I definitely prefer a smaller version code (easier for users to read when reporting bugs).
Any idea what's going on here and how to fix it?
Ohhh ok I finally figured it out! No, I haven't been desperately looking for an answer for the past two years... I just somehow stumbled upon it now.
So, in android/app/build.gradle, there is a script that generates the bundle version code. It's calculated from the version code and the target architecture version code. For example in the RN 0.64x template:
def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) {
output.versionCodeOverride = defaultConfig.versionCode * 1000 + versionCodes.get(abi)
}
For me, arm64-v8a always seems to get used as the default when generating the version code, so I get outputs like:
versionCode 1 => 1003
versionCode 12 => 12003
versionCode 105 => 105003
you get the idea...
The calculation used to involve a much more mysterious number (1048576 🔮🧙♂️, see in the RN 0.59x template), which seemed arbitrary and made it quite tricky to understand how this bundle version code was generated.
Now it makes much more sense!
One possibility is that your /app/build.gradle config contains some logic that transforms the versionCode likely because you are doing app bundling.
In the current master of react-native, you can see some versioning logic here.
Possibly your build.gradle has the same or similar logic.
Google has there explanation on versioning here.
I had the same issue. It occurred whenever I ran ./gradlew bundleRelease and I changed
def enableSeparateBuildPerCPUArchitecture = false
to
def enableSeparateBuildPerCPUArchitecture = true
This function is found in android/app/build.gradle
I am unsure how to stop it doing it aside from changing enableSeparateBuildPerCPUArchitecture back to false
In my app , I implemented APPRTC. Before implement the APPRTC my app size is 6MB. After implemented APPRTC My app size went 16 MB. i am using one to one Voice chat only. Can we have any other options to reduce the APP size or webrtc library size? Please suggest.. Thanks..
Note : "libjingle_peerconnection_so.so" liberary size is 10 MB.
You can Split APK using Gradle. Like,
// APK splitting
splits {
abi {
// Enable APK splitting wrt architecture
enable true
// Reset the architectures for which you need to build the APKs for
reset()
// Include the architectures for which Gradle is building APKs
include 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
// Set this to false if you don't want an APK that has native code for all architectures
universalApk false
}
}
// Assign codes to each architecture
project.ext.versionCodes = ['x86': 0, 'x86_64': 1, 'armeabi-v7a': 2, 'arm64-v8a': 3]
// Add the architecture-specific codes above to base version code, i.e. the version code specified in the defaultConfig{} block
// Example: 2000 is the base version code -> 2000 (x86), 2001 (x86_64), 2002 (armeabi-v7a) & 2003 (arm64-v8a) would be the version codes for the generated APK files
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
output.versionCodeOverride = project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) * 1 + android.defaultConfig.versionCode
}
}
}
I know this question has beed asked a few times, but it seems like any other solution does not work for me.
I'm supposed to update an app we have on the Google Play Store.
The version name and code are maintained in the gradle.build with this piece of code:
def versionMajor = 1
def versionMinor = 1
def versionPatch = 0
def versionBuild = 1
android {
defaultConfig {
versionCode versionMajor * 10000 + versionMinor * 1000 + versionPatch * 100 + versionBuild
versionName "${versionMajor}.${versionMinor}.${versionPatch}"
}
}
The current version from the store is 1.0.7(.5) which translates to 10705.
I'm supposed to update to 1.1.0(.1), which translates to 11001.
But the Google Play keeps telling me that I already have an APK with this version number. I checked every version of the app, back to 1.0.0 and I don't have any version with that number (obviously), since it is automatically calculated.
Am I doing something wrong?
I have another app, with a different package name, made for another client, that have this version code. But version codes are independant, right?
EDIT:
Couldn't find a solution.
I negociated with my boss to update the version code to 1.1.0(.2) instead. And it worked. Still don't know why the GPlay thought the 1.1.0(.1) already exist, since it doesn't.
I have an Android APK in the Google Play store with an Target SDK of 23.
I have released a new version (same target SDK) and Google shows me this error:
If I proceed (I learnt the hard way) then none of the current users can upgrade to this version. I had to restore the code, increment the build number and rebuild the APK to "rollback" to a usable version.
However, I cannot work out WHY google is showing me this error. Note, the "0 Supported Android Devices" is a red-herring - it is a known issue in Google Play in the last 24 hours - if you publish the APK the real number of devices is shown.
Please give me some leads on what the difference is or what causes this error:
Non-upgradable APK
WARNING
None of the users of this APK will be able to upgrade to any of the new APKs added in this release.
TIP
Ensure that all your new APKs are added to this release.
I got able to resolve this issue:-
The issue was with the versioncode - I am sure you have not defined any version code in your App and it is getting generated by this formula:
versionCode = MAJOR * 10000 + MINOR * 100 + PATCH
But sometimes auto generated versioncode value of the latest release becomes smaller than the previous release (in your case 10403 < 104028) and that's why it shows non-upgradable APK.
What you need to do is:-
In your config.xml in tag add versioncode like below:-
android-versionCode="104280"
104280 will work for you as it is greater than older version.
Now get it published without any error.
Thanks Sanny
I'm using VS-TACO and ran into this problem.
To slightly clarify Sanny's answer which fixed the issue for me. Apparently, somewhere along the way the android-versionCode was calculated using this formula:
MAJOR * 100000 + MINOR * 1000 + PATCH * 10
but now it is getting calculated using the version Sanny shows:
MAJOR * 10000 + MINOR * 100 + PATCH
So for example if your version was 1.3.1 android-versionCode was calculated as "103010"
now you change the version to 1.3.2 and it is calculated the new way so the version is "10302" which is less than "103010".
So to work around this issue (I guess forever if the android version keeps getting calculated the new way) you can add the version tag to your config.xml:
<?xml version="1.0" encoding="utf-8"?>
<widget android-versionCode="103020" ...
or you can go into Visual Studio and use the visual editor for config.xml, go to the "Android" section and change the "Version Code:" value.
I ran into a similar problem but was able to solve it with the following Node script used as part of my continuous deployment pipeline.
Note:
This reads from a VERSION.md file that contains the current app version.
It may also be run with the --version argument to only update the current version in config.xml without setting the build versions.
#!/usr/bin/env node
var fs = require('fs');
var xml2js = require('xml2js');
const cliArgs = require('command-line-args');
const options = cliArgs([
{name: 'version', type: Boolean}
]);
// Read config.xml
var xml = fs.readFileSync('config.xml', 'utf8');
// Parse XML to JS Obj
xml2js.parseString(xml, function (err, result) {
if(err) {
return console.log(err);
}
// Get JS Obj
var obj = result;
const version = fs.readFileSync('VERSION.md', 'utf8');
if (options.version){
// Write current version
obj['widget']['$']['version'] = version;
} else {
// Increment build numbers (separately for iOS and Android)
obj['widget']['$']['ios-CFBundleVersion'] = version;
// remove all periods to create an integer for Android
const [major, minor, patch] = version.split('.')
obj['widget']['$']['android-versionCode'] = major+pad_number(minor)+pad_number(patch);
}
// Build XML from JS Obj
var builder = new xml2js.Builder();
var xml = builder.buildObject(obj);
// Write config.xml
fs.writeFile('config.xml', xml, function(err) {
if(err) {
return console.log(err);
}
console.log('Build number successfully incremented');
});
});
/**
* Pad a number with prepending zeros if less than 10
* #see [Javascript function to pad a string](https://stackoverflow.com/questions/2686855/is-there-a-javascript-function-that-can-pad-a-string-to-get-to-a-determined-leng)
*/
function pad_number(orig) {
return ("00"+orig).slice(-2);
}
I just had the same issue with the versions, as I upgraded react-native to 0.60.5
So I calculated the differences between missing versionCode version
Version 1.9 = VersionCode => 4194313
Version 1.10 = VersionCode = 3145739
Difference : 194313 - 3145739 = 1048574
Each APK per architecture will use that formula
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
I have modified a little bit my formula
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode + 1048574
// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
// https://developer.android.com/studio/build/configure-apk-splits.html
def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode + 1048575;
}
}
For those of you using Android Studio, I had this problem after upgrading from Eclipse to Android Studio and not configuring the gradle files properly.
Make sure the version code in your build.gradle in defaultConfig{} is correct.
...
defaultConfig {
...
versionCode 373
versionName "3.73"
I ran into this issue because in my cordova config.xml the previous version was 0.0.51 and the new version was 0.0.6. But in the playstore console, those numbers were converted to 51 and 6 for the APK number. One can't "upgrade" from 51 to 6. So I changed the xml to be 0.0.60, which made the APK number 60, and voila, I can update from 51 to 60.
I'm currently developing a custom library for Android.
My idea is to have a version for the app (I'm currently setting it in de build.gradle file and it works fine), and a different version for the library.
Is there a best practice in order to achieve this without having the two build.gradle files merged together?
I found a couple of similar questions on SO but they were 4 years old and not very helpful.
The solution for this is not Git as you probably already figured out. OP wants to externally version a library, potentially as a means to provide an API to a third-party without providing the source code.
This is not trivial with Gradle but it is doable.
You can do this at different levels, I'll explain the easiest and most straight-forward.
Setting the version number
First you need to add a version variable to your gradle.properties file. You can set this variable with a simple one-liner:
version=0.1.0-SNAPSHOT
Building a version string
In your project create a file called versioning.gradle and paste the following code inside (I found this online a long time ago, I don't have the source anymore):
ext {
/**
* Builds an Android version code from the version of the project.
* This is designed to handle the -SNAPSHOT and -RC format.
*
* I.e. during development the version ends with -SNAPSHOT. As the code stabilizes and release nears
* one or many Release Candidates are tagged. These all end with "-RC1", "-RC2" etc.
* And the final release is without any suffix.
* #return
*/
buildVersionCode = {
//The rules is as follows:
//-SNAPSHOT counts as 0
//-RC* counts as the RC number, i.e. 1 to 98
//final release counts as 99.
//Thus you can only have 98 Release Candidates, which ought to be enough for everyone
def candidate = "99"
def (major, minor, patch) = version.toLowerCase().replaceAll('-', '').tokenize('.')
if (patch.endsWith("snapshot")) {
candidate = "0"
patch = patch.replaceAll("[^0-9]","")
} else {
def rc
(patch, rc) = patch.tokenize("rc")
if (rc) {
candidate = rc
}
}
(major, minor, patch, candidate) = [major, minor, patch, candidate].collect{it.toInteger()}
(major * 1000000) + (minor * 10000) + (patch * 100) + candidate;
}
}
Once you've done this, be sure to include the versioning.gradle file from your main build.gradle file by adding apply from: '../versioning.gradle' near where the Android plugin is loaded.
Then, in your defaultConfig block, you want to change the default version variables to the following values:
versionCode buildVersionCode()
versionName version
Version number in the filename of the library
If you're truly building an Android library, then the expected output is an .aar file.
Therefore, add the following gradle code to your build.gradle file:
libraryVariants.all {
variant -> variant.outputs.each {
output -> output.outputFile = new File(
output.outputFile.parent,
output.outputFile.name.replace(".aar", "-${defaultConfig.versionName}.aar")
)
}
}
And that's it! Your output file will have a name with the version number you specify in the gradle.proprties file.
Caveats
This will version your library and/or API in a very static manner. Meaning that there's no way for a developer to dynamically get the version number through a method call.
Be sure to also have a method available that supplies client developers with the version number AND be sure to keep the two in sync. Only then you have a properly versioned library.
Why would you want to do this?
If the problem is that you need to be able to take different actions in the programs using the library depending on the version, then simply create a public static final constant somewhere in the library.
If the reason is cosmetic (e.g., for presentation), then simply put it in your Readme, Changelog, or wherever you need it. Messing up the build files for this purpose is a bad idea.
Based on your explanation:
My recommendation is to put it in the library's AndroidManifest.xml in that case (android:versionCode and android:versionName). This is what Google does with many of their own libraries, and it's harmless wrt the build.