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
Related
After updating to AGP(Android Gradle Plugin) 3.2.0 we can't set versionCode directly on a mergedFlavor. If we do so we get this useful warning:
versionCode cannot be set on a mergedFlavor directly.
versionCodeOverride can instead be set for variant outputs using the following syntax:
android {
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.versionCodeOverride = 40805
}
}
}
After this change everything works fine besides one little thing. The auto-generated BuildConfig.VERSION_CODE doesn't reflect the version code from output.versionCodeOverride = 40805.
Before AGP 3.2.0 we could set the versionCode dynamically through:
applicationVariants.all { v ->
v.mergedFlavor.versionCode = 40805 // 40805 is hardcoded as an example but it is archived dynamically.
}
And the version code reflected in BuildConfig.VERSION_CODE (this is very handy) and I would like to archive the same with AGP 3.2.0.
I know I could workaround this by creating a custom build config field for this like variant.buildConfigField('int', 'OVERRIDDEN_VERSION_CODE', "${versionCodeOverride}") and this will generate the BuildConfig.OVERRIDDEN_VERSION_CODE with the versionCode I override. Archiving the same as I was when using the AGP version bellow 3.2.0 by setting the versionCode through mergedFlavor.versionCode = 40805 but I don't like this kind of workarounds.
Is there any way to have the output.versionCodeOverride = 40805 being reflecting in the auto-generated BuildConfig.VERSION_CODE?
PS: If we set the versionCode directly in the specific flavor it will work as expected but that's not what I want to know :)
UPDATE
Found a similar question(with a well described use case) and considering the discussions we had I could give a better answer here.
To recap, the problem isn't the version code override not being applied at all, it's just that BuildConfig.VERSION_CODE does not pick up the override value.
This has been labeled as intended behavior in the official issue tracker: https://issuetracker.google.com/issues/37008496
One of the comments explains why and suggests defining versionCode in a flavor instead of the defaultConfig:
If we made a different buildconfig.java per output then we'd also need to run javac/proguard/jacoco/dex for each split and we'd lose the improvement in build [time].
If this is critical to you, then don't use splits and use flavors instead, but we'll get much slower build time.
If you don't want to alter your curent setup you might want to read the version code from the manifest instead. All you need is a context:
val versionCode = context.packageManager.getPackageInfo(context.packageName, 0).versionCode
You should cache the value as getting package info is a non-trivial operation.
The same applies to version name.
the order of instructions is important there ...
String versionName = version.versionName
int versionCode = version.versionCode
android {
applicationVariants.all { variant ->
// to be removed here:
// variant.mergedFlavor.versionCode = versionCode
variant.outputs.each { output ->
// and to be added here:
output.versionNameOverride = versionName
output.versionCodeOverride = versionCode
}
}
}
the documentation for Build multiple APKs explain it, below "Configure versioning".
while the reason for this isn't build-tools 3.2.0, but it's Gradle 4.6.
I am using Android Studio 3.0.1.
When i am trying to run app
INSTALL_FAILED_USER_RESTRICTED: Invalid apk
error occurs.
I also disable Instant Run.
again i am run app but same error occurs.
04/04 10:59:08: Launching app
$ adb push G:\Android\Fundraiser\BuyForFund\app\build\outputs\apk\debug\app-debug.apk /data/local/tmp/com.android.buyforfund
$ adb shell pm install -t -r "/data/local/tmp/com.android.buyforfund"
Failure [INSTALL_FAILED_USER_RESTRICTED: Invalid apk]
$ adb shell pm uninstall com.android.buyforfund
DELETE_FAILED_INTERNAL_ERROR
Error while Installing APK
None of the other answers worked for me using Xiaomis MIUI 10 on a Mi 9 phone.
Besides the usual (like enabling USB debugging and Install via USB in the developer options) answers from other questions suggested turning off MIUI optimization. While this did the trick, I wasn't happy with it. So I did some digging and came to the following conclusions:
The described error only occurred the second time you deploy your app and after that keeps occurring every other time when deploying the same app to that phone.
To solve this I could either hit Run / press Shift + F10 again or unplug and plug in that phone again. None of this seems viable. So I did some more digging and it turns out when you are increasing the versionCode in your build.gradle file every time you build your app, MIUI 10 will not complain and let you install your app just like you would expect. Even Android Studios Instant Run works. Though doing this manually is just as annoying.
So I took some ideas to auto-increment the versionCode from this question and modified build.gradle (the one for your module, NOT the one for your project). You can do the same following these easy steps:
Replace
defaultConfig {
applicationId "your.app.id" // leave it at the value you have in your file
minSdkVersion 23 // this as well
targetSdkVersion 28 // and this
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
with
def versionPropsFile = file('version.properties')
def value = 0
Properties versionProps = new Properties()
if (!versionPropsFile.exists()) {
versionProps['VERSION_MAJOR'] = "1"
versionProps['VERSION_MINOR'] = "0"
versionProps['VERSION_PATCH'] = "0"
versionProps['VERSION_BUILD'] = "0"
versionProps.store(versionPropsFile.newWriter(), null)
}
def runTasks = gradle.startParameter.taskNames
if ('assembleRelease' in runTasks) {
value = 1
}
if (versionPropsFile.canRead()) {
versionProps.load(new FileInputStream(versionPropsFile))
versionProps['VERSION_PATCH'] = (versionProps['VERSION_PATCH'].toInteger() + value).toString()
versionProps['VERSION_BUILD'] = (versionProps['VERSION_BUILD'].toInteger() + 1).toString()
versionProps.store(versionPropsFile.newWriter(), null)
// change major and minor version here
def mVersionName = "${versionProps['VERSION_MAJOR']}.${versionProps['VERSION_MINOR']}.${versionProps['VERSION_PATCH']}"
defaultConfig {
applicationId "your.app.id" // leave it at the value you have in your file
minSdkVersion 23 // this as well
targetSdkVersion 28 // and this
versionCode versionProps['VERSION_BUILD'].toInteger()
versionName "${mVersionName} Build: ${versionProps['VERSION_BUILD']}"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
}
else {
throw new GradleException("Could not read version.properties!")
}
Now each time you build your app by hitting Run or Instant Run your versionCode / VERSION_BUILD increases.
If you build a release your VERSION_PATCH increases as well changing your versionName from x.y.z to x.y.z+1 (i.e. 1.2.3 turns to 1.2.4). To change VERSION_MAJOR (the x) and VERSION_MINOR (the y) edit the version.properties file which you can find in your module folder. If you didn't change your modules name it's called app so this file is located at app/version.properties.
Make sure you have enabled the following options:
Settings > Additional Settings > Developer options
USB Debugging
Install via USB
USB Debugging (Security settings)
I have the same problem, I sent a feedback to Google on my phone, would say it's a bug. In my case the best solution is to cancel that dialog and then re-run, it works always on second attempt after cancelling.
Depending on what phone you are using, I would assume the problem is on the phone (Google) side. Not sure yet if a general Google problem or specific hardware phones, I use "Xiaomi Redmi 5".
Disabling instant run actually worked in my case, but that's not the purpose of it, that's just a dirty workaround.
Edit:
Make sure that you don't have something like
android:debuggable="false"
in your manifest.
I ran into this same error while the underlying issue was different.
Mine was that I was trying to install my app on Android 12 device while the AndroidManifest.xml file didn't have all the android:exported properties explicitly set. This error is explained further here: https://developer.android.com/about/versions/12/behavior-changes-12#exported
If your app targets Android 12 or higher and contains activities,
services, or broadcast receivers that use intent filters, you must
explicitly declare the android:exported attribute for these app
components.
Warning: If an activity, service, or broadcast receiver uses intent
filters and doesn't have an explicitly-declared value for
android:exported, your app can't be installed on a device that runs
Android 12 or higher.
After I added the required android:exported properties into AndroidManifest.xml file, the error was resolved.
In your Androidmanifest.xml file at path
app/src/main/Androidmanifest.xml
add android:exported="true"` in activity tag.
Sample:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.example">
<application
android:label="example"
android:icon="#mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="#style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"
android:exported="true">
For those who still might get this error if you have done everything from enabling to flutter clean and all.
I solved this error by checking the manifest and adding proper value because i changed something in the manifest which was not supported and later forgot to change it.
so if you have changed something in theme, drawable or any resource file check that out first.
INSTALL_FAILED_USER_RESTRICTED: Invalid apk
Steps for MIUI 9 and Above:
Settings -> Additional Settings -> Developer options ->
step 1: scroll down side - Turn off "MIUI optimization" and Restart your device.
step 2: Turn On "USB Debugging"
step 3: Turn On "Install via USB"
step 4: show push notification and just click USB - Set USB Configuration to Charging (MTP(Media Transfer Protocol) is the default mode.
Works even in MTP in some cases).
please try.
If you are targeting android 'P' then your build.gradle file should look like this
android {
compileSdkVersion 'android-P'
defaultConfig {
applicationId "xyz.com"
minSdkVersion 16
targetSdkVersion 27
versionCode 1
versionName "1.0"
}
buildTypes {
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
targetSdkVersion must be 27 to run your app below android 'P', otherwise the app can only run on 'P' and above.
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 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.
In Android Studio I have in build.gradle default info about application version:
android {
defaultConfig {
versionCode 24
versionName "0.1 beta"
}
}
How can I increment the versionCode automatilcally on each project compilation?
Quoting from my book:
Since the android:versionCode is a monotonically increasing integer,
one approach for automating it is to simply increment it on each build.
While this may seem wasteful, two billion builds is a lot of builds,
so a solo developer is unlikely to run out. Synchronizing such versionCode
values across a team will get a bit more complex, but for an individual
case (developer, build server, etc.), it is eminently doable using Groovy.
The
Gradle/HelloVersioning
sample project uses a version.properties file as the backing store for the
version information:
def versionPropsFile = file('version.properties')
if (versionPropsFile.canRead()) {
def Properties versionProps = new Properties()
versionProps.load(new FileInputStream(versionPropsFile))
def code = versionProps['VERSION_CODE'].toInteger() + 1
versionProps['VERSION_CODE']=code.toString()
versionProps.store(versionPropsFile.newWriter(), null)
defaultConfig {
versionCode code
versionName "1.1"
minSdkVersion 14
targetSdkVersion 18
}
}
else {
throw new GradleException("Could not read version.properties!")
}
First, we try to open a version.properties file and fail if it does not
exist, requiring the developer to create a starter file manually:
VERSION_CODE=1
Of course, a more robust implementation of this script would handle this case and
supply a starter value for the developer.
The script then uses the read-the-custom-properties logic illustrated
in the preceding section [NOTE: of the book, not included here] to read the existing
value... but it increments the old value by 1 to get the new code to use.
The revised code is then written back to the properties file before it
is applied in the defaultConfig block.
In this case, the script throws a GradleException to halt the build if
the version.properties file could not be found or otherwise could not be
read.