diff --git a/pythonforandroid/bootstraps/common/build/build.py b/pythonforandroid/bootstraps/common/build/build.py index 0b6b9832f0..a4077d9a7c 100644 --- a/pythonforandroid/bootstraps/common/build/build.py +++ b/pythonforandroid/bootstraps/common/build/build.py @@ -84,7 +84,7 @@ def get_bootstrap_name(): if PYTHON is not None and not exists(PYTHON): PYTHON = None -if _bootstrap_name in ('sdl2', 'webview', 'service_only'): +if _bootstrap_name in ('sdl2', 'webview', 'service_only', 'qt'): WHITELIST_PATTERNS.append('pyconfig.h') environment = jinja2.Environment(loader=jinja2.FileSystemLoader( @@ -223,7 +223,7 @@ def compile_py_file(python_file, optimize_python=True): def make_package(args): # If no launcher is specified, require a main.py/main.pyc: - if (get_bootstrap_name() != "sdl" or args.launcher is None) and \ + if (get_bootstrap_name() in ["sdl", "qt"] or args.launcher is None) and \ get_bootstrap_name() not in ["webview", "service_library"]: # (webview doesn't need an entrypoint, apparently) if args.private is None or ( @@ -546,6 +546,9 @@ def make_package(args): } if get_bootstrap_name() == "sdl2": render_args["url_scheme"] = url_scheme + elif get_bootstrap_name() == "qt": + render_args["url_scheme"] = "qt" + render( 'AndroidManifest.tmpl.xml', manifest_path, @@ -599,11 +602,29 @@ def make_package(args): } if get_bootstrap_name() == "sdl2": render_args["url_scheme"] = url_scheme + elif get_bootstrap_name() == "qt": + render_args["url_scheme"] = "qt" render( 'strings.tmpl.xml', join(res_dir, 'values/strings.xml'), **render_args) + # Library resources + if get_bootstrap_name() == "qt": + qt_libs = args.qt_libs.split(",") + load_local_libs = args.load_local_libs.split(",") + init_classes = args.init_classes.split(",") + init_classes = ":".join(init_classes) + arch = get_dist_info_for("archs")[0] + render( + 'libs.tmpl.xml', + join(res_dir, 'values/libs.xml'), + qt_libs=qt_libs, + load_local_libs=load_local_libs, + init_classes=init_classes, + arch=arch + ) + if exists(join("templates", "custom_rules.tmpl.xml")): render( 'custom_rules.tmpl.xml', @@ -954,6 +975,14 @@ def create_argument_parser(): help='Use that parameter if you need to implement your own PythonServive Java class') ap.add_argument('--activity-class-name', dest='activity_class_name', default=DEFAULT_PYTHON_ACTIVITY_JAVA_CLASS, help='The full java class name of the main activity') + if get_bootstrap_name() == "qt": + ap.add_argument('--qt-libs', dest='qt_libs', required=True, + help='comma separated list of Qt libraries to be loaded') + ap.add_argument('--load-local-libs', dest='load_local_libs', required=True, + help='comma separated list of Qt plugin libraries to be loaded') + ap.add_argument('--init-classes', dest='init_classes', + help='comma separated list of class named to be loaded from the Qt jar files ' + 'specified through add_jar cli option') return ap @@ -1055,6 +1084,6 @@ def _read_configuration(): if __name__ == "__main__": - if get_bootstrap_name() in ('sdl2', 'webview', 'service_only'): + if get_bootstrap_name() in ('sdl2', 'webview', 'service_only', 'qt'): WHITELIST_PATTERNS.append('pyconfig.h') parse_args_and_make_package() diff --git a/pythonforandroid/bootstraps/common/build/templates/build.tmpl.gradle b/pythonforandroid/bootstraps/common/build/templates/build.tmpl.gradle index ce105736d3..ebba8c7e49 100644 --- a/pythonforandroid/bootstraps/common/build/templates/build.tmpl.gradle +++ b/pythonforandroid/bootstraps/common/build/templates/build.tmpl.gradle @@ -36,7 +36,7 @@ android { manifestPlaceholders = {{ args.manifest_placeholders}} } - + packagingOptions { jniLibs { useLegacyPackaging = true @@ -48,7 +48,7 @@ android { exclude 'lib/**/gdb.setup' {%- endif %} } - + {% if args.sign -%} signingConfigs { @@ -107,7 +107,7 @@ android { } aaptOptions { - noCompress "tflite" + noCompress "tflite", "rcc" } } diff --git a/pythonforandroid/bootstraps/qt/__init__.py b/pythonforandroid/bootstraps/qt/__init__.py new file mode 100644 index 0000000000..bb62f54e5a --- /dev/null +++ b/pythonforandroid/bootstraps/qt/__init__.py @@ -0,0 +1,52 @@ +import sh +from os.path import join +from pythonforandroid.toolchain import ( + Bootstrap, current_directory, info, info_main, shprint) +from pythonforandroid.util import ensure_dir + + +class QtBootstrap(Bootstrap): + + name = 'qt' + recipe_depends = ['python3', 'genericndkbuild', 'PySide6', 'shiboken6'] + + def assemble_distribution(self): + info_main('# Creating Android project from build and {} bootstrap'.format( + self.name)) + + info('This currently just copies the build stuff straight from the build dir.') + shprint(sh.rm, '-rf', self.dist_dir) + shprint(sh.cp, '-r', self.build_dir, self.dist_dir) + with current_directory(self.dist_dir): + with open('local.properties', 'w') as fileh: + fileh.write('sdk.dir={}'.format(self.ctx.sdk_dir)) + + arch = self.ctx.archs[0] + if len(self.ctx.archs) > 1: + raise ValueError('built for more than one arch, but bootstrap cannot handle that yet') + info('Bootstrap running with arch {}'.format(arch)) + + with current_directory(self.dist_dir): + info('Copying python distribution') + + self.distribute_libs(arch, [self.ctx.get_libs_dir(arch.arch)]) + self.distribute_aars(arch) + self.distribute_javaclasses(self.ctx.javaclass_dir, + dest_dir=join("src", "main", "java")) + + python_bundle_dir = join(f'_python_bundle__{arch.arch}', '_python_bundle') + ensure_dir(python_bundle_dir) + site_packages_dir = self.ctx.python_recipe.create_python_bundle( + join(self.dist_dir, python_bundle_dir), arch) + + if 'sqlite3' not in self.ctx.recipe_build_order: + with open('blacklist.txt', 'a') as fileh: + fileh.write('\nsqlite3/*\nlib-dynload/_sqlite3.so\n') + + if not self.ctx.with_debug_symbols: + self.strip_libraries(arch) + self.fry_eggs(site_packages_dir) + super().assemble_distribution() + + +bootstrap = QtBootstrap() diff --git a/pythonforandroid/bootstraps/qt/build/.gitignore b/pythonforandroid/bootstraps/qt/build/.gitignore new file mode 100644 index 0000000000..a1fc39c070 --- /dev/null +++ b/pythonforandroid/bootstraps/qt/build/.gitignore @@ -0,0 +1,14 @@ +.gradle +/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 +# gradle/wrapper/gradle-wrapper.properties diff --git a/pythonforandroid/bootstraps/qt/build/blacklist.txt b/pythonforandroid/bootstraps/qt/build/blacklist.txt new file mode 100644 index 0000000000..d5e230c89a --- /dev/null +++ b/pythonforandroid/bootstraps/qt/build/blacklist.txt @@ -0,0 +1,84 @@ +# prevent user to include invalid extensions +*.apk +*.aab +*.apks +*.pxd + +# eggs +*.egg-info + +# unit test +unittest/* + +# python config +config/makesetup + +# unused kivy files (platform specific) +kivy/input/providers/wm_* +kivy/input/providers/mactouch* +kivy/input/providers/probesysfs* +kivy/input/providers/mtdev* +kivy/input/providers/hidinput* +kivy/core/camera/camera_videocapture* +kivy/core/spelling/*osx* +kivy/core/video/video_pyglet* +kivy/tools +kivy/tests/* +kivy/*/*.h +kivy/*/*.pxi + +# unused encodings +lib-dynload/*codec* +encodings/cp*.pyo +encodings/tis* +encodings/shift* +encodings/bz2* +encodings/iso* +encodings/undefined* +encodings/johab* +encodings/p* +encodings/m* +encodings/euc* +encodings/k* +encodings/unicode_internal* +encodings/quo* +encodings/gb* +encodings/big5* +encodings/hp* +encodings/hz* + +# unused python modules +bsddb/* +wsgiref/* +hotshot/* +pydoc_data/* +tty.pyo +anydbm.pyo +nturl2path.pyo +LICENCE.txt +macurl2path.pyo +dummy_threading.pyo +audiodev.pyo +antigravity.pyo +dumbdbm.pyo +sndhdr.pyo +__phello__.foo.pyo +sunaudio.pyo +os2emxpath.pyo +multiprocessing/dummy* + +# unused binaries python modules +lib-dynload/termios.so +lib-dynload/_lsprof.so +lib-dynload/*audioop.so +lib-dynload/_hotshot.so +lib-dynload/_heapq.so +lib-dynload/_json.so +lib-dynload/grp.so +lib-dynload/resource.so +lib-dynload/pyexpat.so +lib-dynload/_ctypes_test.so +lib-dynload/_testcapi.so + +# odd files +plat-linux3/regen diff --git a/pythonforandroid/bootstraps/qt/build/jni/Application.mk b/pythonforandroid/bootstraps/qt/build/jni/Application.mk new file mode 100644 index 0000000000..15598537ca --- /dev/null +++ b/pythonforandroid/bootstraps/qt/build/jni/Application.mk @@ -0,0 +1,8 @@ + +# Uncomment this if you're using STL in your project +# See CPLUSPLUS-SUPPORT.html in the NDK documentation for more information +# APP_STL := stlport_static + +# APP_ABI := armeabi armeabi-v7a x86 +APP_ABI := $(ARCH) +APP_PLATFORM := $(NDK_API) diff --git a/pythonforandroid/bootstraps/qt/build/jni/application/src/Android.mk b/pythonforandroid/bootstraps/qt/build/jni/application/src/Android.mk new file mode 100644 index 0000000000..aebe3f623b --- /dev/null +++ b/pythonforandroid/bootstraps/qt/build/jni/application/src/Android.mk @@ -0,0 +1,18 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := main_$(PREFERRED_ABI) + +# Add your application source files here... +LOCAL_SRC_FILES := start.c + +LOCAL_CFLAGS += -I$(PYTHON_INCLUDE_ROOT) $(EXTRA_CFLAGS) + +LOCAL_SHARED_LIBRARIES := python_shared + +LOCAL_LDLIBS := -llog $(EXTRA_LDLIBS) + +LOCAL_LDFLAGS += -L$(PYTHON_LINK_ROOT) $(APPLICATION_ADDITIONAL_LDFLAGS) + +include $(BUILD_SHARED_LIBRARY) diff --git a/pythonforandroid/bootstraps/qt/build/jni/application/src/Android_static.mk b/pythonforandroid/bootstraps/qt/build/jni/application/src/Android_static.mk new file mode 100644 index 0000000000..1bb58cb76d --- /dev/null +++ b/pythonforandroid/bootstraps/qt/build/jni/application/src/Android_static.mk @@ -0,0 +1,9 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := main_$(PREFERRED_ABI) + +LOCAL_SRC_FILES := start.c + +include $(BUILD_SHARED_LIBRARY) diff --git a/pythonforandroid/bootstraps/qt/build/jni/application/src/bootstrap_name.h b/pythonforandroid/bootstraps/qt/build/jni/application/src/bootstrap_name.h new file mode 100644 index 0000000000..8a4d8aa464 --- /dev/null +++ b/pythonforandroid/bootstraps/qt/build/jni/application/src/bootstrap_name.h @@ -0,0 +1,4 @@ + +#define BOOTSTRAP_USES_NO_SDL_HEADERS + +const char bootstrap_name[] = "qt"; diff --git a/pythonforandroid/bootstraps/qt/build/src/main/assets/.gitkeep b/pythonforandroid/bootstraps/qt/build/src/main/assets/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pythonforandroid/bootstraps/qt/build/src/main/java/.gitkeep b/pythonforandroid/bootstraps/qt/build/src/main/java/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pythonforandroid/bootstraps/qt/build/src/main/java/org/kivy/android/PythonActivity.java b/pythonforandroid/bootstraps/qt/build/src/main/java/org/kivy/android/PythonActivity.java new file mode 100644 index 0000000000..c11fd23559 --- /dev/null +++ b/pythonforandroid/bootstraps/qt/build/src/main/java/org/kivy/android/PythonActivity.java @@ -0,0 +1,246 @@ +package org.kivy.android; + +import android.os.SystemClock; + +import java.io.File; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.ArrayList; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.view.KeyEvent; +import android.util.Log; +import android.widget.Toast; +import android.os.Bundle; +import android.os.PowerManager; +import android.content.Context; +import android.content.pm.PackageManager; + +import org.qtproject.qt.android.bindings.QtActivity; +import org.qtproject.qt.android.QtNative; + +public class PythonActivity extends QtActivity { + + private static final String TAG = "PythonActivity"; + + public static PythonActivity mActivity = null; + + private Bundle mMetaData = null; + private PowerManager.WakeLock mWakeLock = null; + + public String getAppRoot() { + String app_root = getFilesDir().getAbsolutePath() + "/app"; + return app_root; + } + + public String getEntryPoint(String search_dir) { + /* Get the main file (.pyc|.pyo|.py) depending on if we + * have a compiled version or not. + */ + List entryPoints = new ArrayList(); + entryPoints.add("main.pyo"); // python 2 compiled files + entryPoints.add("main.pyc"); // python 3 compiled files + for (String value : entryPoints) { + File mainFile = new File(search_dir + "/" + value); + if (mainFile.exists()) { + return value; + } + } + return "main.py"; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + this.mActivity = this; + Log.v(TAG, "Ready to unpack"); + File app_root_file = new File(getAppRoot()); + PythonUtil.unpackAsset(mActivity, "private", app_root_file, true); + PythonUtil.unpackPyBundle(mActivity, getApplicationInfo().nativeLibraryDir + "/" + "libpybundle", app_root_file, false); + + Log.v("Python", "Device: " + android.os.Build.DEVICE); + Log.v("Python", "Model: " + android.os.Build.MODEL); + + // Set up the Python environment + String app_root_dir = getAppRoot(); + String mFilesDirectory = mActivity.getFilesDir().getAbsolutePath(); + String entry_point = getEntryPoint(app_root_dir); + + Log.v(TAG, "Setting env vars for start.c and Python to use"); + QtNative.setEnvironmentVariable("ANDROID_ENTRYPOINT", entry_point); + QtNative.setEnvironmentVariable("ANDROID_ARGUMENT", app_root_dir); + QtNative.setEnvironmentVariable("ANDROID_APP_PATH", app_root_dir); + QtNative.setEnvironmentVariable("ANDROID_PRIVATE", mFilesDirectory); + QtNative.setEnvironmentVariable("ANDROID_UNPACK", app_root_dir); + QtNative.setEnvironmentVariable("PYTHONHOME", app_root_dir); + QtNative.setEnvironmentVariable("PYTHONPATH", app_root_dir + ":" + app_root_dir + "/lib"); + QtNative.setEnvironmentVariable("PYTHONOPTIMIZE", "2"); + + Log.v(TAG, "About to do super onCreate"); + super.onCreate(savedInstanceState); + Log.v(TAG, "Did super onCreate"); + + this.mActivity = this; + try { + Log.v(TAG, "Access to our meta-data..."); + mActivity.mMetaData = mActivity.getPackageManager().getApplicationInfo( + mActivity.getPackageName(), PackageManager.GET_META_DATA).metaData; + + PowerManager pm = (PowerManager) mActivity.getSystemService(Context.POWER_SERVICE); + if ( mActivity.mMetaData.getInt("wakelock") == 1 ) { + mActivity.mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "Screen On"); + mActivity.mWakeLock.acquire(); + } + } catch (PackageManager.NameNotFoundException e) { + } + } + + @Override + public void onDestroy() { + Log.i("Destroy", "end of app"); + super.onDestroy(); + + // make sure all child threads (python_thread) are stopped + android.os.Process.killProcess(android.os.Process.myPid()); + } + + long lastBackClick = SystemClock.elapsedRealtime(); + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + // If it wasn't the Back key or there's no web page history, bubble up to the default + // system behavior (probably exit the activity) + if (SystemClock.elapsedRealtime() - lastBackClick > 2000){ + lastBackClick = SystemClock.elapsedRealtime(); + Toast.makeText(this, "Click again to close the app", + Toast.LENGTH_LONG).show(); + return true; + } + + lastBackClick = SystemClock.elapsedRealtime(); + return super.onKeyDown(keyCode, event); + } + + + //---------------------------------------------------------------------------- + // Listener interface for onNewIntent + // + + public interface NewIntentListener { + void onNewIntent(Intent intent); + } + + private List newIntentListeners = null; + + public void registerNewIntentListener(NewIntentListener listener) { + if ( this.newIntentListeners == null ) + this.newIntentListeners = Collections.synchronizedList(new ArrayList()); + this.newIntentListeners.add(listener); + } + + public void unregisterNewIntentListener(NewIntentListener listener) { + if ( this.newIntentListeners == null ) + return; + this.newIntentListeners.remove(listener); + } + + @Override + protected void onNewIntent(Intent intent) { + if ( this.newIntentListeners == null ) + return; + this.onResume(); + synchronized ( this.newIntentListeners ) { + Iterator iterator = this.newIntentListeners.iterator(); + while ( iterator.hasNext() ) { + (iterator.next()).onNewIntent(intent); + } + } + } + + //---------------------------------------------------------------------------- + // Listener interface for onActivityResult + // + + public interface ActivityResultListener { + void onActivityResult(int requestCode, int resultCode, Intent data); + } + + private List activityResultListeners = null; + + public void registerActivityResultListener(ActivityResultListener listener) { + if ( this.activityResultListeners == null ) + this.activityResultListeners = Collections.synchronizedList(new ArrayList()); + this.activityResultListeners.add(listener); + } + + public void unregisterActivityResultListener(ActivityResultListener listener) { + if ( this.activityResultListeners == null ) + return; + this.activityResultListeners.remove(listener); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent intent) { + if ( this.activityResultListeners == null ) + return; + this.onResume(); + synchronized ( this.activityResultListeners ) { + Iterator iterator = this.activityResultListeners.iterator(); + while ( iterator.hasNext() ) + (iterator.next()).onActivityResult(requestCode, resultCode, intent); + } + } + + public static void start_service( + String serviceTitle, + String serviceDescription, + String pythonServiceArgument + ) { + _do_start_service( + serviceTitle, serviceDescription, pythonServiceArgument, true + ); + } + + public static void start_service_not_as_foreground( + String serviceTitle, + String serviceDescription, + String pythonServiceArgument + ) { + _do_start_service( + serviceTitle, serviceDescription, pythonServiceArgument, false + ); + } + + public static void _do_start_service( + String serviceTitle, + String serviceDescription, + String pythonServiceArgument, + boolean showForegroundNotification + ) { + Intent serviceIntent = new Intent(PythonActivity.mActivity, PythonService.class); + String argument = PythonActivity.mActivity.getFilesDir().getAbsolutePath(); + String app_root_dir = PythonActivity.mActivity.getAppRoot(); + String entry_point = PythonActivity.mActivity.getEntryPoint(app_root_dir + "/service"); + serviceIntent.putExtra("androidPrivate", argument); + serviceIntent.putExtra("androidArgument", app_root_dir); + serviceIntent.putExtra("serviceEntrypoint", "service/" + entry_point); + serviceIntent.putExtra("pythonName", "python"); + serviceIntent.putExtra("pythonHome", app_root_dir); + serviceIntent.putExtra("pythonPath", app_root_dir + ":" + app_root_dir + "/lib"); + serviceIntent.putExtra("serviceStartAsForeground", + (showForegroundNotification ? "true" : "false") + ); + serviceIntent.putExtra("serviceTitle", serviceTitle); + serviceIntent.putExtra("serviceDescription", serviceDescription); + serviceIntent.putExtra("pythonServiceArgument", pythonServiceArgument); + PythonActivity.mActivity.startService(serviceIntent); + } + + public static void stop_service() { + Intent serviceIntent = new Intent(PythonActivity.mActivity, PythonService.class); + PythonActivity.mActivity.stopService(serviceIntent); + } + +} diff --git a/pythonforandroid/bootstraps/qt/build/src/main/jniLibs/.gitkeep b/pythonforandroid/bootstraps/qt/build/src/main/jniLibs/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pythonforandroid/bootstraps/qt/build/src/main/libs/.gitkeep b/pythonforandroid/bootstraps/qt/build/src/main/libs/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pythonforandroid/bootstraps/qt/build/src/main/res/drawable/.gitkeep b/pythonforandroid/bootstraps/qt/build/src/main/res/drawable/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pythonforandroid/bootstraps/qt/build/src/main/res/mipmap/.gitkeep b/pythonforandroid/bootstraps/qt/build/src/main/res/mipmap/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pythonforandroid/bootstraps/qt/build/templates/AndroidManifest.tmpl.xml b/pythonforandroid/bootstraps/qt/build/templates/AndroidManifest.tmpl.xml new file mode 100644 index 0000000000..4448fbdbed --- /dev/null +++ b/pythonforandroid/bootstraps/qt/build/templates/AndroidManifest.tmpl.xml @@ -0,0 +1,107 @@ + + + + = 9 %} + android:xlargeScreens="true" + {% endif %} + /> + + + + + + {% for perm in args.permissions %} + + {% endfor %} + + {% if args.wakelock %} + + {% endif %} + + {% if args.billing_pubkey %} + + {% endif %} + + {{ args.extra_manifest_xml }} + + + + {% for l in args.android_used_libs %} + + {% endfor %} + + {% for m in args.meta_data %} + {% endfor %} + + + + + + + + + + {%- if args.intent_filters -%} + {{- args.intent_filters -}} + {%- endif -%} + + + + + + + + + {% if service or args.launcher %} + + {% endif %} + {% for name in service_names %} + + {% endfor %} + {% for name in native_services %} + + {% endfor %} + + {% for a in args.add_activity %} + + {% endfor %} + + + diff --git a/pythonforandroid/bootstraps/qt/build/templates/libs.tmpl.xml b/pythonforandroid/bootstraps/qt/build/templates/libs.tmpl.xml new file mode 100644 index 0000000000..b86091051c --- /dev/null +++ b/pythonforandroid/bootstraps/qt/build/templates/libs.tmpl.xml @@ -0,0 +1,32 @@ + + + + + + + + {{ arch }};c++_shared + {%- for qt_lib in qt_libs %} + {{ arch }};Qt6{{ qt_lib }}_{{ arch }} + {%- endfor -%} + + + + {%- for load_local_lib in load_local_libs %} + {{ arch }};lib{{ load_local_lib }}_{{ arch }}.so + {%- endfor -%} + {{ arch }};libshiboken6.abi3.so + {{ arch }};libpyside6.abi3.so + {{ arch }};QtCore.abi3.so + {%- for qt_lib in qt_libs %} + {{ arch }};Qt{{ qt_lib }}.abi3.so + {% if qt_lib == "Qml" -%} + {{ arch }};libpyside6qml.abi3.so + {% endif %} + {%- endfor -%} + + + {{ init_classes }} + 1 + 1 + diff --git a/pythonforandroid/bootstraps/qt/build/templates/strings.tmpl.xml b/pythonforandroid/bootstraps/qt/build/templates/strings.tmpl.xml new file mode 100644 index 0000000000..c8025518be --- /dev/null +++ b/pythonforandroid/bootstraps/qt/build/templates/strings.tmpl.xml @@ -0,0 +1,7 @@ + + + {{ args.name }} + {{ private_version }} + {{ args.presplash_color }} + {{ url_scheme }} + diff --git a/pythonforandroid/recipe.py b/pythonforandroid/recipe.py index fa0bb4e790..f603440db0 100644 --- a/pythonforandroid/recipe.py +++ b/pythonforandroid/recipe.py @@ -1168,6 +1168,8 @@ def reduce_object_file_names(self, dirn): parts = file_basename.split('.') if len(parts) <= 2: continue + if parts[1] == "abi3": + continue move(filen, join(file_dirname, parts[0] + '.so')) diff --git a/pythonforandroid/recipes/android/__init__.py b/pythonforandroid/recipes/android/__init__.py index e568ac8d9e..608d9ee738 100644 --- a/pythonforandroid/recipes/android/__init__.py +++ b/pythonforandroid/recipes/android/__init__.py @@ -35,7 +35,7 @@ def prebuild_arch(self, arch): ctx_bootstrap = ctx_bootstrap.decode('utf-8') bootstrap = bootstrap_name = ctx_bootstrap is_sdl2 = (bootstrap_name == "sdl2") - if bootstrap_name in ["sdl2", "webview", "service_only", "service_library"]: + if bootstrap_name in ["sdl2", "webview", "service_only", "service_library", "qt"]: java_ns = u'org.kivy.android' jni_ns = u'org/kivy/android' else: diff --git a/pythonforandroid/recipes/android/src/setup.py b/pythonforandroid/recipes/android/src/setup.py index bcd411f46b..303eaf3b5c 100755 --- a/pythonforandroid/recipes/android/src/setup.py +++ b/pythonforandroid/recipes/android/src/setup.py @@ -5,7 +5,7 @@ lib_dict = { 'sdl2': ['SDL2', 'SDL2_image', 'SDL2_mixer', 'SDL2_ttf'] } -sdl_libs = lib_dict.get(os.environ['BOOTSTRAP'], ['main']) +sdl_libs = lib_dict.get(os.environ['BOOTSTRAP'], ['main_x86_64']) modules = [Extension('android._android', ['android/_android.c', 'android/_android_jni.c'], diff --git a/pythonforandroid/recipes/genericndkbuild/__init__.py b/pythonforandroid/recipes/genericndkbuild/__init__.py index 901f208986..8b2a9c26a2 100644 --- a/pythonforandroid/recipes/genericndkbuild/__init__.py +++ b/pythonforandroid/recipes/genericndkbuild/__init__.py @@ -21,6 +21,8 @@ def get_recipe_env(self, arch=None, with_flags_in_cc=True, with_python=True): with_python=with_python, ) env['APP_ALLOW_MISSING_DEPS'] = 'true' + # required for Qt bootstrap + env['PREFERRED_ABI'] = arch.arch return env def build_arch(self, arch):