gradle "versionCode" overflows
I am trying to build Electrum with p4a master, and due to https://github.com/kivy/python-for-android/pull/1720 / https://github.com/kivy/python-for-android/commit/abb4703150c5eec2fe2eddbfd0b5b57eca56d7bc I am getting an error.
Electrum uses x.y.z version numbers in general; but for the android apk there is an extra digit, so it is x.y.z.a.
For example, 3.3.6.0
The corresponding versionCode using older p4a would be 3030600
but since referenced change, it is now 7213030600
https://github.com/kivy/python-for-android/blob/ccb0f8e1bab36f1b7d1508216b4b4afb076e614f/pythonforandroid/bootstraps/common/build/templates/build.tmpl.gradle#L27-L32
Build log excerpt:
[DEBUG]: Download https://jcenter.bintray.com/com/sun/xml/fastinfoset/FastInfoset/1.2.13/FastInfoset-1.2.13.jar
[DEBUG]: Download https://jcenter.bintray.com/com/sun/istack/istack-commons-runtime/2.21/istack-commons-runtime-2.21.jar
[DEBUG]: Download https://jcenter.bintray.com/org/glassfish/jaxb/txw2/2.2.11/txw2-2.2.11.jar
[DEBUG]: Download https://dl.google.com/dl/android/maven2/com/android/tools/lint/lint-gradle-api/26.1.4/lint-gradle-api-26.1.4.jar2.2.11.jar > 927 KB/1007 KB downloaded
[DEBUG]:
[DEBUG]: FAILURE: Build failed with an exception.
[DEBUG]:
[DEBUG]: * Where:
[DEBUG]: Build file '/home/user/wspace/electrum/.buildozer/android/platform/build/dists/Electrum/build.gradle' line: 30LE
[DEBUG]:
[DEBUG]: * What went wrong:
[DEBUG]: A problem occurred evaluating root project 'Electrum'.
[DEBUG]: > Could not find method versionCode() for arguments [7213030600] on DefaultConfig_Decorated{name=main, dimension=null, minSdkVersion=DefaultApiVersion{mApiLevel=21, mCodename='null'}, targetSdkVersion=DefaultApiVersion{mApiLevel=28, mCodename='null'}, renderscriptTargetApi=null, renderscriptSupportModeEnabled=null, renderscriptSupportModeBlasEnabled=null, renderscriptNdkModeEnabled=null, versionCode=null, versionName=null, applicationId=null, testApplicationId=null, testInstrumentationRunner=null, testInstrumentationRunnerArguments={}, testHandleProfiling=null, testFunctionalTest=null, signingConfig=null, resConfig=null, mBuildConfigFields={}, mResValues={}, mProguardFiles=[], mConsumerProguardFiles=[], mManifestPlaceholders={}, mWearAppUnbundled=null} of type com.android.build.gradle.internal.dsl.DefaultConfig.
[DEBUG]:
[DEBUG]: * Try:
[DEBUG]: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
[DEBUG]:
[DEBUG]: * Get more help at https://help.gradle.org
[DEBUG]:
[DEBUG]: BUILD FAILED in 44s
Exception in thread background thread for pid 6317:
Traceback (most recent call last):
File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run()
File "/usr/lib/python3.6/threading.py", line 864, in run
self._target(*self._args, **self._kwargs)
File "/home/user/.local/lib/python3.6/site-packages/sh.py", line 1540, in wrap
fn(*args, **kwargs)
File "/home/user/.local/lib/python3.6/site-packages/sh.py", line 2459, in background_thread
handle_exit_code(exit_code)
File "/home/user/.local/lib/python3.6/site-packages/sh.py", line 2157, in fn
return self.command.handle_command_exit_code(exit_code)
File "/home/user/.local/lib/python3.6/site-packages/sh.py", line 815, in handle_command_exit_code
raise exc
sh.ErrorReturnCode_1:
RAN: /home/user/wspace/electrum/.buildozer/android/platform/build/dists/Electrum/gradlew assembleDebug
I can only guess that the error is due to 32 bit integer overflow. If I manually patch p4a to produce a smaller versioncode int, then the build succeeds.
Ah, thanks for the report, this one is new to me but I'm sure your interpretation is correct. That should mean we can fix it by adjusting the algorithm used, but we'll have to be careful about what that means for backwards compatibility.
I looked at the change, it removes the first two args of the tuple here:
args.numeric_version = "{}{}{}".format(arch_code, min_sdk, version_code)
And that got me wondering @inclement why would different arches need different numeric versions anyway? Wouldn't usually only be one installed at a time? In that case it seems reasonable enough to take the arch_code out permanently. Same for min_sdk: it seems reasonable enough to me to expect that the version is bumped by the developer for a new min sdk version or expect some sort of clash.
So the change to me seems reasonable enough. Is there a way we can figure out backwards compatibility for this at all? Seems hard for me to do, maybe we should just change it and put a warning in the release notes even though that will certainly break it for some people. But I don't see a good way of avoiding it
@JonasT The version code problem isn't for the device, but for the Play store (or other stores) and general upgrades. The Play store supports multiple APKs by arch, but expects you to give them appropriate version codes so the installation order is correct (e.g. an arm64-v8a apk should have a higher code than an armeabi-v7a apk, so that devices supporting the former get upgraded). You also can't upload multiple APKs with the same version code.
This info is in https://developer.android.com/studio/publish/versioning and https://developer.android.com/google/play/publishing/multiple-apks
I was wondering if the way to fix this is first to put a little extra effort into packing the bits of the version code efficiently, which might let us get to A.B.C.D version formats, but then to draw a line and say if this doesn't work for you then manage it manually.
Ok the arch makes sense, but can the min_sdk be thrown out then?
Additionally though, I also wouldn't find it entirely unreasonable to also say A.B.C.D versions need to be manually managed either. I don't think these are super common, most projects I've seen have three or two component versions
Ok the arch makes sense, but can the min_sdk be thrown out then?
Possibly, but I think it's in there deliberately - per https://developer.android.com/google/play/publishing/multiple-apks, the version code is also expected to be higher for an apk with a higher minimum supported api. I don't imagine this gets taken advantage of that much though.
Additionally though, I also wouldn't find it entirely unreasonable to also say A.B.C.D versions need to be manually managed either
I agree, really I want to check exactly what we can feasibly support and then work with that.
Thanks for the additional insight! As for min_sdk, but who ever really wants to change the minimum supported API and keep the same version in the same release? And wouldn't that be a horrible practice anyway? I guess you could try to do that, but it sounds more like a theoretical exercise to me. So IMHO it makes little practical sense to have the min_sdk in there
Just got this one when using "1.0.0.3" as version number :l
Does this problem still exist, @SomberNight?
Yes. The current code still overflows versionCode: https://github.com/kivy/python-for-android/blob/436d5a93282dcfcc7027d19d70963c6773544434/pythonforandroid/bootstraps/common/build/build.py#L418-L430
class args:
version = "1.0.0.3"
numeric_version = None
min_sdk_version = 21
version_code = 0
if not args.numeric_version:
min_sdk = args.min_sdk_version
for i in args.version.split('.'):
version_code *= 100
version_code += int(i)
args.numeric_version = "{}{}{}".format("10", min_sdk, version_code)
>>> print(args.numeric_version)
10211000003
>>> print(int(args.numeric_version) > 2**31 - 1)
True
Note that people running into this can opt to work around by explicitly specifying android.numeric_version in buildozer.spec, or by setting the APP_ANDROID_NUMERIC_VERSION environment variable.
We are instead carrying a patch and customising how the versionCode is set as a workaround.