@@ -93,6 +93,73 @@ def get_bootstrap_name():
9393
9494DEFAULT_PYTHON_ACTIVITY_JAVA_CLASS = 'org.kivy.android.PythonActivity'
9595DEFAULT_PYTHON_SERVICE_JAVA_CLASS = 'org.kivy.android.PythonService'
96+ # Google Play's documented maximum Android versionCode.
97+ # https://developer.android.com/tools/publishing/versioning
98+ MAX_ANDROID_VERSION_CODE = 2100000000
99+
100+
101+ def get_android_numeric_version (version , min_sdk_version ):
102+ """
103+ Generate the default Android versionCode value from --version.
104+
105+ The format is (10 + minsdk + app_version). Older versioning was
106+ (arch + minsdk + app_version), with arch expressed with a single digit
107+ from 6 to 9. Since multi-arch support, this uses 10.
108+ """
109+ version_code = 0
110+ try :
111+ for part in version .split ('.' ):
112+ version_code *= 100
113+ version_code += int (part )
114+ except ValueError as exc :
115+ raise ValueError (
116+ "Could not generate Android versionCode from --version "
117+ "{!r}. --version is Android versionName; when it is not numeric "
118+ "dot-separated text, set --numeric-version to a positive Android "
119+ "versionCode integer no greater than {}." .format (
120+ version , MAX_ANDROID_VERSION_CODE
121+ )
122+ ) from exc
123+ return "{}{}{}" .format ("10" , min_sdk_version , version_code )
124+
125+
126+ def validate_android_numeric_version (numeric_version , * , generated_from_version = None ):
127+ try :
128+ normalized_version = int (numeric_version )
129+ except (TypeError , ValueError ) as exc :
130+ raise ValueError (
131+ "--numeric-version must be a decimal integer Android versionCode "
132+ "greater than 0 and no greater than {}; got {!r}." .format (
133+ MAX_ANDROID_VERSION_CODE , numeric_version
134+ )
135+ ) from exc
136+
137+ if normalized_version <= 0 :
138+ raise ValueError (
139+ "--numeric-version must be a positive Android versionCode "
140+ "greater than 0; got {!r}." .format (numeric_version )
141+ )
142+
143+ if normalized_version > MAX_ANDROID_VERSION_CODE :
144+ if generated_from_version is not None :
145+ raise ValueError (
146+ "Generated Android versionCode {} from --version {!r}, "
147+ "which exceeds the maximum {}. --version is Android "
148+ "versionName; keep this display version by setting "
149+ "--numeric-version to a positive Android versionCode no "
150+ "greater than {}." .format (
151+ normalized_version ,
152+ generated_from_version ,
153+ MAX_ANDROID_VERSION_CODE ,
154+ MAX_ANDROID_VERSION_CODE ,
155+ )
156+ )
157+ raise ValueError (
158+ "--numeric-version is Android versionCode and must not exceed "
159+ "{}; got {!r}." .format (MAX_ANDROID_VERSION_CODE , numeric_version )
160+ )
161+
162+ return str (normalized_version )
96163
97164
98165def render (template , dest , ** kwargs ):
@@ -420,19 +487,17 @@ def make_package(args):
420487 versioned_name = (args .name .replace (' ' , '' ).replace ('\' ' , '' ) +
421488 '-' + args .version )
422489
423- version_code = 0
424- if not args .numeric_version :
425- """
426- Set version code in format (10 + minsdk + app_version)
427- Historically versioning was (arch + minsdk + app_version),
428- with arch expressed with a single digit from 6 to 9.
429- Since the multi-arch support, has been changed to 10.
430- """
431- min_sdk = args .min_sdk_version
432- for i in args .version .split ('.' ):
433- version_code *= 100
434- version_code += int (i )
435- args .numeric_version = "{}{}{}" .format ("10" , min_sdk , version_code )
490+ generated_from_version = None
491+ if args .numeric_version is None :
492+ generated_from_version = args .version
493+ args .numeric_version = get_android_numeric_version (
494+ args .version ,
495+ args .min_sdk_version ,
496+ )
497+ args .numeric_version = validate_android_numeric_version (
498+ args .numeric_version ,
499+ generated_from_version = generated_from_version ,
500+ )
436501
437502 if args .intent_filters :
438503 with open (args .intent_filters ) as fd :
@@ -793,14 +858,15 @@ def create_argument_parser():
793858 help = ('The human-readable name of the project.' ),
794859 required = True )
795860 ap .add_argument ('--numeric-version' , dest = 'numeric_version' ,
796- help = ('The numeric version number of the project. If not '
797- 'given, this is automatically computed from the '
798- 'version.' ))
861+ help = ('The Android versionCode of the project. This must '
862+ 'be a positive decimal integer no greater than '
863+ '{}. If not given, it is automatically computed '
864+ 'from --version.' ).format (MAX_ANDROID_VERSION_CODE ))
799865 ap .add_argument ('--version' , dest = 'version' ,
800- help = ('The version number of the project. This should '
801- 'consist of numbers and dots, and should have the '
802- 'same number of groups of numbers as previous '
803- 'versions .' ),
866+ help = ('The Android versionName of the project, shown to '
867+ 'users as the display version. Use '
868+ '--numeric-version to control Android versionCode '
869+ 'and update ordering .' ),
804870 required = True )
805871 if is_sdl_bootstrap ():
806872 ap .add_argument ('--launcher' , dest = 'launcher' , action = 'store_true' ,
0 commit comments