From 5a720e24c957c35da2227db7a964b22a0c45572b Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Sat, 2 Nov 2013 18:04:28 +0100 Subject: [PATCH] add meta-data support, external android libraries support, and custom java files to include in the APK. --- buildozer/__init__.py | 26 ++++++++++++-- buildozer/default.spec | 11 ++++++ buildozer/targets/android.py | 69 ++++++++++++++++++++++++++++++++++-- 3 files changed, 102 insertions(+), 4 deletions(-) diff --git a/buildozer/__init__.py b/buildozer/__init__.py index 72ef3d9..d1caacf 100644 --- a/buildozer/__init__.py +++ b/buildozer/__init__.py @@ -90,7 +90,9 @@ class Buildozer(object): self.build_id = None self.config_profile = '' self.config = SafeConfigParser(allow_no_value=True) + self.config.optionxform = lambda value: value self.config.getlist = self._get_config_list + self.config.getlistvalues = self._get_config_list_values self.config.getdefault = self._get_config_default self.config.getbooldefault = self._get_config_bool @@ -473,6 +475,19 @@ class Buildozer(object): raise Exception('Unhandled extraction for type {0}'.format(archive)) + def file_copytree(self, src, dest): + print 'copy {} to {}'.format(src, dest) + if os.path.isdir(src): + if not os.path.isdir(dest): + os.makedirs(dest) + files = os.listdir(src) + for f in files: + self.file_copytree( + os.path.join(src, f), + os.path.join(dest, f)) + else: + copyfile(src, dest) + def clean_platform(self): self.info('Clean the platform build directory') if not exists(self.platform_dir): @@ -891,8 +906,11 @@ class Buildozer(object): + def _get_config_list_values(self, *args, **kwargs): + kwargs['with_values'] = True + return self._get_config_list(*args, **kwargs) - def _get_config_list(self, section, token, default=None): + def _get_config_list(self, section, token, default=None, with_values=False): # monkey-patch method for ConfigParser # get a key as a list of string, seperated from the comma @@ -900,7 +918,11 @@ class Buildozer(object): l_section = '{}:{}'.format(section, token) if self.config.has_section(l_section): values = self.config.options(l_section) - return [x.strip() for x in values] + if with_values: + return ['{}={}'.format(key, self.config.get(l_section, key)) for + key in values] + else: + return [x.strip() for x in values] values = self.config.getdefault(section, token, '') if not values: diff --git a/buildozer/default.spec b/buildozer/default.spec index c57c65a..e7dfe80 100644 --- a/buildozer/default.spec +++ b/buildozer/default.spec @@ -84,6 +84,10 @@ fullscreen = 1 # OUYA-ODK/libs/*.jar #android.add_jars = foo.jar,bar.jar,path/to/more/*.jar +# (list) List of Java files to add to the android project (can be java or a +# directory containing the files) +#android.add_src = + # (str) python-for-android branch to use, if not master, useful to try # not yet merged features. #android.branch = master @@ -105,6 +109,13 @@ fullscreen = 1 # Don't forget to add the WAKE_LOCK permission if you set this to True #android.wakelock = False +# (list) Android application meta-data to set (key=value format) +#android.meta_data = + +# (list) Android library project to add (will be added in the +# project.properties automatically.) +#android.library_references = + # # iOS specific # diff --git a/buildozer/targets/android.py b/buildozer/targets/android.py index 7d258aa..a210503 100644 --- a/buildozer/targets/android.py +++ b/buildozer/targets/android.py @@ -22,7 +22,7 @@ from sys import platform, executable from buildozer import BuildozerException from buildozer.target import Target from os import environ -from os.path import join, realpath, expanduser, basename +from os.path import join, realpath, expanduser, basename, relpath from shutil import copyfile from glob import glob @@ -401,6 +401,13 @@ class TargetAndroid(Target): 'Failed to find libs_armeabi files: {}'.format( pattern)) + # update the project.properties libraries references + self._update_libraries_references(dist_dir) + + # add src files + self._add_java_src(dist_dir) + + # build the app build_cmd = ( '{python} build.py --name {name}' ' --version {version}' @@ -425,12 +432,18 @@ class TargetAndroid(Target): 'android.permissions', []) for permission in permissions: # force the latest component to be uppercase - print 'initial permission is', permission permission = permission.split('.') permission[-1] = permission[-1].upper() permission = '.'.join(permission) build_cmd += ' --permission {}'.format(permission) + # meta-data + meta_datas = config.getlistvalues('app', 'android.meta_data', []) + for meta in meta_datas: + key, value = meta.split('=', 1) + meta = '{}={}'.format(key.strip(), value.strip()) + build_cmd += ' --meta-data "{}"'.format(meta) + # add extra Java jar files add_jars = config.getlist('app', 'android.add_jars', []) for pattern in add_jars: @@ -512,6 +525,58 @@ class TargetAndroid(Target): self.buildozer.state['android:latestapk'] = apk self.buildozer.state['android:latestmode'] = self.build_mode + def _update_libraries_references(self, dist_dir): + # ensure the project.properties exist + project_fn = join(dist_dir, 'project.properties') + + if not self.buildozer.file_exists(project_fn): + content = ['target=android-{}\n'.format(self.android_api)] + else: + with open(project_fn) as fd: + content = fd.readlines() + + # extract library reference + references = [] + for line in content[:]: + if not line.startswith('android.library.reference.'): + continue + content.remove(line) + + # convert our references to relative path + app_references = self.buildozer.config.getlist( + 'app', 'android.library_references', []) + source_dir = realpath(self.buildozer.config.getdefault('app', 'source.dir', '.')) + for cref in app_references: + # get the full path of the current reference + ref = realpath(join(source_dir, cref)) + if not self.buildozer.file_exists(ref): + self.buildozer.error('Invalid library reference (path not found): {}'.format(cref)) + exit(1) + # get a relative path from the project file + ref = relpath(ref, dist_dir) + # ensure the reference exists + references.append(ref) + + # recreate the project.properties + with open(project_fn, 'wb') as fd: + for line in content: + fd.write(line) + for index, ref in enumerate(references): + fd.write('android.library.reference.{}={}\n'.format( + index + 1, ref)) + + self.buildozer.debug('project.properties updated') + + def _add_java_src(self, dist_dir): + print '_add_java_src()' + java_src = self.buildozer.config.getlist('app', 'android.add_src', []) + src_dir = join(dist_dir, 'src') + for pattern in java_src: + for fn in glob(expanduser(pattern.strip())): + print 'match file', fn + last_component = basename(fn) + self.buildozer.file_copytree(fn, join(src_dir, last_component)) + @property def serials(self): if hasattr(self, '_serials'):