From 4a9cabcf65dee9284a0ef941be5a8afbdb852c13 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 20 Oct 2024 12:53:45 +0200 Subject: [PATCH 01/82] Keep GitHub Actions up to date with GitHub's Dependabot Fixes software supply chain safety warnings like at the bottom right of https://github.com/kivy/python-for-android/actions/runs/11425651890 * [Keeping your actions up to date with Dependabot](https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot) * [Configuration options for the dependabot.yml file - package-ecosystem](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem) --- .github/dependabot.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..be006de9a1 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,13 @@ +# Keep GitHub Actions up to date with GitHub's Dependabot... +# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot +# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + groups: + github-actions: + patterns: + - "*" # Group all Actions updates into a single larger pull request + schedule: + interval: weekly From f4f08e666e67d221da42251e7bf3d9e131d19883 Mon Sep 17 00:00:00 2001 From: Leonid <87101242+GvozdevLeonid@users.noreply.github.com> Date: Sat, 21 Feb 2026 20:50:05 +0100 Subject: [PATCH 02/82] Fixed a bug with Python version selection and library loading. --- .../common/build/src/main/java/org/kivy/android/PythonUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonUtil.java b/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonUtil.java index b406942605..3490211e6c 100644 --- a/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonUtil.java +++ b/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonUtil.java @@ -59,7 +59,7 @@ protected static ArrayList getLibraries(File libsDir) { addLibraryIfExists(libsList, name, libsDir); } - for (int v = 14; v >= 5; v--) { + for (int v = 5; v <= 3.14; v++) { libsList.add("python3." + v + (v <= 7 ? "m" : "")); } From bf4737a9b36f6eeeef5437dc31a130e730483428 Mon Sep 17 00:00:00 2001 From: Leonid <87101242+GvozdevLeonid@users.noreply.github.com> Date: Sat, 21 Feb 2026 21:00:49 +0100 Subject: [PATCH 03/82] Fixed Python version support. --- pythonforandroid/recipes/python3/__init__.py | 57 +++++++++++--------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/pythonforandroid/recipes/python3/__init__.py b/pythonforandroid/recipes/python3/__init__.py index 3ff1f147b0..b4d40c3755 100644 --- a/pythonforandroid/recipes/python3/__init__.py +++ b/pythonforandroid/recipes/python3/__init__.py @@ -55,7 +55,6 @@ class Python3Recipe(TargetPythonRecipe): ''' version = '3.14.2' - _p_version = Version(version) url = 'https://github.com/python/cpython/archive/refs/tags/v{version}.tar.gz' name = 'python3' @@ -64,28 +63,6 @@ class Python3Recipe(TargetPythonRecipe): 'patches/reproducible-buildinfo.diff', ] - if _p_version.major == 3 and _p_version.minor == 7: - patches += [ - 'patches/py3.7.1_fix-ctypes-util-find-library.patch', - 'patches/py3.7.1_fix-zlib-version.patch', - ] - - if 8 <= _p_version.minor <= 10: - patches.append('patches/py3.8.1.patch') - - if _p_version.minor >= 11: - patches.append('patches/cpython-311-ctypes-find-library.patch') - - if _p_version.minor >= 14: - patches.append('patches/3.14_armv7l_fix.patch') - patches.append('patches/3.14_fix_remote_debug.patch') - - if shutil.which('lld') is not None: - if _p_version.minor == 7: - patches.append("patches/py3.7.1_fix_cortex_a8.patch") - elif _p_version.minor >= 8: - patches.append("patches/py3.8.1_fix_cortex_a8.patch") - depends = ['hostpython3', 'sqlite3', 'openssl', 'libffi'] # those optional depends allow us to build python compression modules: # - _bz2.so @@ -210,6 +187,32 @@ def link_version(self): flags=flags ) + def apply_patches(self, arch, build_dir=None): + + _p_version = Version(self.version) + if _p_version.major == 3 and _p_version.minor == 7: + self.patches += [ + 'patches/py3.7.1_fix-ctypes-util-find-library.patch', + 'patches/py3.7.1_fix-zlib-version.patch', + ] + + if 8 <= _p_version.minor <= 10: + self.patches.append('patches/py3.8.1.patch') + + if _p_version.minor >= 11: + self.patches.append('patches/cpython-311-ctypes-find-library.patch') + + if _p_version.minor >= 14: + self.patches.append('patches/3.14_armv7l_fix.patch') + self.patches.append('patches/3.14_fix_remote_debug.patch') + + if shutil.which('lld') is not None: + if _p_version.minor == 7: + self.patches.append("patches/py3.7.1_fix_cortex_a8.patch") + elif _p_version.minor >= 8: + self.patches.append("patches/py3.8.1_fix_cortex_a8.patch") + super().__init__(arch, build_dir) + def include_root(self, arch_name): return join(self.get_build_dir(arch_name), 'Include') @@ -317,7 +320,13 @@ def add_flags(include_flags, link_dirs, link_libs): env['ZLIB_VERSION'] = line.replace('#define ZLIB_VERSION ', '') add_flags(' -I' + zlib_includes, ' -L' + zlib_lib_path, ' -lz') - if self._p_version.minor >= 13 and self.disable_gil: + _p_version = Version(self.version) + if _p_version.minor >= 11: + configure_args.extend([ + '--with-build-python={python_host_bin}', + ]) + + if _p_version.minor >= 13 and self.disable_gil: self.configure_args.append("--disable-gil") return env From c787f271337210625a61b78031e737f490130ec1 Mon Sep 17 00:00:00 2001 From: Leonid <87101242+GvozdevLeonid@users.noreply.github.com> Date: Sat, 21 Feb 2026 21:17:55 +0100 Subject: [PATCH 04/82] Fixed Python version support. Remove conditional build argument for Python version >= 11 --- pythonforandroid/recipes/python3/__init__.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pythonforandroid/recipes/python3/__init__.py b/pythonforandroid/recipes/python3/__init__.py index b4d40c3755..7aa166287b 100644 --- a/pythonforandroid/recipes/python3/__init__.py +++ b/pythonforandroid/recipes/python3/__init__.py @@ -93,11 +93,6 @@ class Python3Recipe(TargetPythonRecipe): 'ac_cv_header_bzlib_h=no', ] - if _p_version.minor >= 11: - configure_args.extend([ - '--with-build-python={python_host_bin}', - ]) - '''The configure arguments needed to build the python recipe. Those are used in method :meth:`build_arch` (if not overwritten like python3's recipe does). From 4f7e6a6491a7ff61fec85ef0f3413260480a131f Mon Sep 17 00:00:00 2001 From: Leonid <87101242+GvozdevLeonid@users.noreply.github.com> Date: Sat, 21 Feb 2026 21:23:40 +0100 Subject: [PATCH 05/82] fixed typo --- pythonforandroid/recipes/python3/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pythonforandroid/recipes/python3/__init__.py b/pythonforandroid/recipes/python3/__init__.py index 7aa166287b..eb378ef800 100644 --- a/pythonforandroid/recipes/python3/__init__.py +++ b/pythonforandroid/recipes/python3/__init__.py @@ -206,7 +206,7 @@ def apply_patches(self, arch, build_dir=None): self.patches.append("patches/py3.7.1_fix_cortex_a8.patch") elif _p_version.minor >= 8: self.patches.append("patches/py3.8.1_fix_cortex_a8.patch") - super().__init__(arch, build_dir) + super().apply_patches(arch, build_dir) def include_root(self, arch_name): return join(self.get_build_dir(arch_name), 'Include') From a870db2455d4f6655d995e244526739a6375651e Mon Sep 17 00:00:00 2001 From: Leonid <87101242+GvozdevLeonid@users.noreply.github.com> Date: Sat, 21 Feb 2026 21:39:53 +0100 Subject: [PATCH 06/82] Fix issue --- .../build/src/main/java/org/kivy/android/PythonUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonUtil.java b/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonUtil.java index 3490211e6c..e8aee768cd 100644 --- a/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonUtil.java +++ b/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonUtil.java @@ -59,7 +59,7 @@ protected static ArrayList getLibraries(File libsDir) { addLibraryIfExists(libsList, name, libsDir); } - for (int v = 5; v <= 3.14; v++) { + for (int v = 14; v >= 5; v--) { libsList.add("python3." + v + (v <= 7 ? "m" : "")); } @@ -85,7 +85,7 @@ public static void loadLibraries(File filesDir, File libsDir) { // load, and it has failed, give a more // general error Log.v(TAG, "Library loading error: " + e.getMessage()); - if (lib.startsWith("python3.14") && !foundPython) { + if (lib.startsWith("python3.5") && !foundPython) { throw new RuntimeException("Could not load any libpythonXXX.so"); } else if (lib.startsWith("python")) { continue; From 0ac0438e62f510b318427867df959775383d39c7 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Sat, 21 Feb 2026 21:01:28 +0000 Subject: [PATCH 07/82] :construction_worker: Relocate Docker storage to LVM volume in CI Reconfigure Docker's data-root to use the LVM volume created by maximize-build-space, fixing recurring "no space left on device" CI failures. Reduce root-reserve-mb from 30 GB to 4 GB since Docker data no longer resides on root filesystem. The relocation step runs after checkout to avoid permission errors during workspace cleanup, and docker-data is excluded from .dockerignore to prevent it being sent as build context. --- .dockerignore | 1 + .github/workflows/push.yml | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/.dockerignore b/.dockerignore index 23c0508ea1..fb45330409 100644 --- a/.dockerignore +++ b/.dockerignore @@ -6,3 +6,4 @@ bin/ *.pyc **/__pycache__ *.egg-info/ +docker-data/ diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 6054a68dc7..041a762589 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -98,7 +98,7 @@ jobs: - name: Maximize build space uses: easimon/maximize-build-space@v10 with: - root-reserve-mb: 30720 + root-reserve-mb: 4096 swap-size-mb: 1024 remove-dotnet: 'true' remove-android: 'true' @@ -107,6 +107,13 @@ jobs: remove-docker-images: 'true' - name: Checkout python-for-android uses: actions/checkout@v5 + - name: Relocate Docker data directory + run: | + sudo systemctl stop docker + sudo mkdir -p "${GITHUB_WORKSPACE}/docker-data" + echo '{"data-root": "'${GITHUB_WORKSPACE}/docker-data'"}' | sudo tee /etc/docker/daemon.json + sudo systemctl start docker + docker info | grep "Docker Root Dir" - name: Build python-for-android docker image run: | docker build --tag=kivy/python-for-android . @@ -224,7 +231,7 @@ jobs: - name: Maximize build space uses: easimon/maximize-build-space@v10 with: - root-reserve-mb: 30720 + root-reserve-mb: 4096 swap-size-mb: 1024 remove-dotnet: 'true' remove-android: 'true' @@ -235,6 +242,13 @@ jobs: uses: actions/checkout@v5 with: fetch-depth: 0 + - name: Relocate Docker data directory + run: | + sudo systemctl stop docker + sudo mkdir -p "${GITHUB_WORKSPACE}/docker-data" + echo '{"data-root": "'${GITHUB_WORKSPACE}/docker-data'"}' | sudo tee /etc/docker/daemon.json + sudo systemctl start docker + docker info | grep "Docker Root Dir" - name: Pull docker image run: | make docker/pull From 285c0a800e6f6dcdea4e20638daeb2cb4fadbd70 Mon Sep 17 00:00:00 2001 From: Leonid <87101242+GvozdevLeonid@users.noreply.github.com> Date: Sat, 21 Feb 2026 22:11:00 +0100 Subject: [PATCH 08/82] fixed issue --- pythonforandroid/recipes/python3/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pythonforandroid/recipes/python3/__init__.py b/pythonforandroid/recipes/python3/__init__.py index eb378ef800..94f1991296 100644 --- a/pythonforandroid/recipes/python3/__init__.py +++ b/pythonforandroid/recipes/python3/__init__.py @@ -317,7 +317,7 @@ def add_flags(include_flags, link_dirs, link_libs): _p_version = Version(self.version) if _p_version.minor >= 11: - configure_args.extend([ + self.configure_args.extend([ '--with-build-python={python_host_bin}', ]) From bdb5e059af8b2e4415008833719d437280bd3cd8 Mon Sep 17 00:00:00 2001 From: Leonid <87101242+GvozdevLeonid@users.noreply.github.com> Date: Sat, 21 Feb 2026 22:12:27 +0100 Subject: [PATCH 09/82] Simplify configuration arguments --- pythonforandroid/recipes/python3/__init__.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pythonforandroid/recipes/python3/__init__.py b/pythonforandroid/recipes/python3/__init__.py index 94f1991296..a215a99ea2 100644 --- a/pythonforandroid/recipes/python3/__init__.py +++ b/pythonforandroid/recipes/python3/__init__.py @@ -317,9 +317,7 @@ def add_flags(include_flags, link_dirs, link_libs): _p_version = Version(self.version) if _p_version.minor >= 11: - self.configure_args.extend([ - '--with-build-python={python_host_bin}', - ]) + self.configure_args.append('--with-build-python={python_host_bin}') if _p_version.minor >= 13 and self.disable_gil: self.configure_args.append("--disable-gil") From 20e43a2f3231fbcd9fef5383006ec33204a65e74 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Sun, 22 Feb 2026 10:30:30 +0000 Subject: [PATCH 10/82] :bug: Fix sdl2/sdl3 bootstrap conflict in CI Auto-detect sdl3 bootstrap when any SDL3-related recipe (sdl3, sdl3_image, sdl3_mixer, sdl3_ttf) is in requirements, preventing conflict with hardcoded sdl2 bootstrap in the test app's setup.py. Also remove stale commented-out URL from sdl3_mixer recipe that incorrectly referenced SDL_ttf. --- ci/rebuild_updated_recipes.py | 24 +++++++++++++++---- .../recipes/sdl3_mixer/__init__.py | 1 - 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/ci/rebuild_updated_recipes.py b/ci/rebuild_updated_recipes.py index 26cba3bc7e..4161914b67 100755 --- a/ci/rebuild_updated_recipes.py +++ b/ci/rebuild_updated_recipes.py @@ -18,7 +18,6 @@ the list of recipes was huge and result was: [ERROR]: Didn't find any valid dependency graphs. [ERROR]: This means that some of your requirements pull in conflicting dependencies. -- only rebuilds on sdl2 bootstrap """ import sh import os @@ -57,14 +56,29 @@ def build(target_python, requirements, archs): android_sdk_home = os.environ['ANDROID_SDK_HOME'] android_ndk_home = os.environ['ANDROID_NDK_HOME'] requirements.add(target_python.name) - requirements = ','.join(requirements) - logger.info('requirements: {}'.format(requirements)) + requirements_str = ','.join(requirements) + logger.info('requirements: {}'.format(requirements_str)) + + # Detect bootstrap based on requirements + # SDL3 recipes conflict with SDL2, so we need the sdl3 bootstrap + # when any SDL3-related recipe (sdl3, sdl3_image, sdl3_mixer, sdl3_ttf) is present + bootstrap = None + if any(r.startswith('sdl3') for r in requirements): + bootstrap = 'sdl3' + logger.info('Detected sdl3 recipe in requirements, using sdl3 bootstrap') + build_command = [ 'setup.py', 'apk', '--sdk-dir', android_sdk_home, '--ndk-dir', android_ndk_home, - '--requirements', requirements - ] + [f"--arch={arch}" for arch in archs] + '--requirements', requirements_str + ] + + if bootstrap: + build_command.extend(['--bootstrap', bootstrap]) + + build_command.extend([f"--arch={arch}" for arch in archs]) + build_command_str = " ".join(build_command) logger.info(f"Build command: {build_command_str}") diff --git a/pythonforandroid/recipes/sdl3_mixer/__init__.py b/pythonforandroid/recipes/sdl3_mixer/__init__.py index c60c5bc157..56fb2c7518 100644 --- a/pythonforandroid/recipes/sdl3_mixer/__init__.py +++ b/pythonforandroid/recipes/sdl3_mixer/__init__.py @@ -7,7 +7,6 @@ class LibSDL3Mixer(BootstrapNDKRecipe): version = "72a73339731a12c1002f9caca64f1ab924938102" - # url = "https://github.com/libsdl-org/SDL_ttf/releases/download/release-{version}/SDL3_ttf-{version}.tar.gz" url = "https://github.com/libsdl-org/SDL_mixer/archive/{version}.tar.gz" dir_name = "SDL3_mixer" From 81f185e7baaccd84ae57511854c8be9a513ae282 Mon Sep 17 00:00:00 2001 From: Leonid <87101242+GvozdevLeonid@users.noreply.github.com> Date: Sun, 22 Feb 2026 15:05:04 +0100 Subject: [PATCH 11/82] fixed flake8 issues --- pythonforandroid/recipes/python3/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pythonforandroid/recipes/python3/__init__.py b/pythonforandroid/recipes/python3/__init__.py index a215a99ea2..c3fab0738a 100644 --- a/pythonforandroid/recipes/python3/__init__.py +++ b/pythonforandroid/recipes/python3/__init__.py @@ -190,17 +190,17 @@ def apply_patches(self, arch, build_dir=None): 'patches/py3.7.1_fix-ctypes-util-find-library.patch', 'patches/py3.7.1_fix-zlib-version.patch', ] - + if 8 <= _p_version.minor <= 10: self.patches.append('patches/py3.8.1.patch') - + if _p_version.minor >= 11: self.patches.append('patches/cpython-311-ctypes-find-library.patch') - + if _p_version.minor >= 14: self.patches.append('patches/3.14_armv7l_fix.patch') self.patches.append('patches/3.14_fix_remote_debug.patch') - + if shutil.which('lld') is not None: if _p_version.minor == 7: self.patches.append("patches/py3.7.1_fix_cortex_a8.patch") From c681ef99f9f8b3ab787c7f4bdc90d59496045c4e Mon Sep 17 00:00:00 2001 From: Leonid <87101242+GvozdevLeonid@users.noreply.github.com> Date: Sun, 22 Feb 2026 22:29:14 +0100 Subject: [PATCH 12/82] Increased the minimum python version to 3.8 --- .../build/src/main/java/org/kivy/android/PythonUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonUtil.java b/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonUtil.java index e8aee768cd..42f4debb53 100644 --- a/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonUtil.java +++ b/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonUtil.java @@ -59,8 +59,8 @@ protected static ArrayList getLibraries(File libsDir) { addLibraryIfExists(libsList, name, libsDir); } - for (int v = 14; v >= 5; v--) { - libsList.add("python3." + v + (v <= 7 ? "m" : "")); + for (int v = 14; v >= 8; v--) { + libsList.add("python3." + v); } libsList.add("main"); @@ -85,7 +85,7 @@ public static void loadLibraries(File filesDir, File libsDir) { // load, and it has failed, give a more // general error Log.v(TAG, "Library loading error: " + e.getMessage()); - if (lib.startsWith("python3.5") && !foundPython) { + if (lib.startsWith("python3.8") && !foundPython) { throw new RuntimeException("Could not load any libpythonXXX.so"); } else if (lib.startsWith("python")) { continue; From 89bb823ed1f80f187bdf47b0cc0c2b5a6ec4de96 Mon Sep 17 00:00:00 2001 From: Leonid <87101242+GvozdevLeonid@users.noreply.github.com> Date: Sun, 22 Feb 2026 22:35:33 +0100 Subject: [PATCH 13/82] simple solution to remove duplicates from patches and configure_args Ensure patches and configure arguments are unique. --- pythonforandroid/recipes/python3/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pythonforandroid/recipes/python3/__init__.py b/pythonforandroid/recipes/python3/__init__.py index c3fab0738a..e36e0b28ad 100644 --- a/pythonforandroid/recipes/python3/__init__.py +++ b/pythonforandroid/recipes/python3/__init__.py @@ -206,6 +206,8 @@ def apply_patches(self, arch, build_dir=None): self.patches.append("patches/py3.7.1_fix_cortex_a8.patch") elif _p_version.minor >= 8: self.patches.append("patches/py3.8.1_fix_cortex_a8.patch") + + self.patches = list(set(self.patches)) super().apply_patches(arch, build_dir) def include_root(self, arch_name): @@ -322,6 +324,8 @@ def add_flags(include_flags, link_dirs, link_libs): if _p_version.minor >= 13 and self.disable_gil: self.configure_args.append("--disable-gil") + self.configure_args = list(set(self.configure_args)) + return env def build_arch(self, arch): From a9b902be53f679cb3585db8b3366f2805ad7bb76 Mon Sep 17 00:00:00 2001 From: Leonid <87101242+GvozdevLeonid@users.noreply.github.com> Date: Thu, 5 Mar 2026 22:20:37 +0100 Subject: [PATCH 14/82] Fixed Python version support. (#3283) * Fixed a bug with Python version selection and library loading. * Fixed Python version support. * Remove conditional build argument for Python version >= 11 * Increased the minimum python version to 3.8 * Ensure patches and configure arguments are unique. --- .../java/org/kivy/android/PythonUtil.java | 6 +- pythonforandroid/recipes/python3/__init__.py | 64 ++++++++++--------- 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonUtil.java b/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonUtil.java index b406942605..42f4debb53 100644 --- a/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonUtil.java +++ b/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonUtil.java @@ -59,8 +59,8 @@ protected static ArrayList getLibraries(File libsDir) { addLibraryIfExists(libsList, name, libsDir); } - for (int v = 14; v >= 5; v--) { - libsList.add("python3." + v + (v <= 7 ? "m" : "")); + for (int v = 14; v >= 8; v--) { + libsList.add("python3." + v); } libsList.add("main"); @@ -85,7 +85,7 @@ public static void loadLibraries(File filesDir, File libsDir) { // load, and it has failed, give a more // general error Log.v(TAG, "Library loading error: " + e.getMessage()); - if (lib.startsWith("python3.14") && !foundPython) { + if (lib.startsWith("python3.8") && !foundPython) { throw new RuntimeException("Could not load any libpythonXXX.so"); } else if (lib.startsWith("python")) { continue; diff --git a/pythonforandroid/recipes/python3/__init__.py b/pythonforandroid/recipes/python3/__init__.py index 3ff1f147b0..e36e0b28ad 100644 --- a/pythonforandroid/recipes/python3/__init__.py +++ b/pythonforandroid/recipes/python3/__init__.py @@ -55,7 +55,6 @@ class Python3Recipe(TargetPythonRecipe): ''' version = '3.14.2' - _p_version = Version(version) url = 'https://github.com/python/cpython/archive/refs/tags/v{version}.tar.gz' name = 'python3' @@ -64,28 +63,6 @@ class Python3Recipe(TargetPythonRecipe): 'patches/reproducible-buildinfo.diff', ] - if _p_version.major == 3 and _p_version.minor == 7: - patches += [ - 'patches/py3.7.1_fix-ctypes-util-find-library.patch', - 'patches/py3.7.1_fix-zlib-version.patch', - ] - - if 8 <= _p_version.minor <= 10: - patches.append('patches/py3.8.1.patch') - - if _p_version.minor >= 11: - patches.append('patches/cpython-311-ctypes-find-library.patch') - - if _p_version.minor >= 14: - patches.append('patches/3.14_armv7l_fix.patch') - patches.append('patches/3.14_fix_remote_debug.patch') - - if shutil.which('lld') is not None: - if _p_version.minor == 7: - patches.append("patches/py3.7.1_fix_cortex_a8.patch") - elif _p_version.minor >= 8: - patches.append("patches/py3.8.1_fix_cortex_a8.patch") - depends = ['hostpython3', 'sqlite3', 'openssl', 'libffi'] # those optional depends allow us to build python compression modules: # - _bz2.so @@ -116,11 +93,6 @@ class Python3Recipe(TargetPythonRecipe): 'ac_cv_header_bzlib_h=no', ] - if _p_version.minor >= 11: - configure_args.extend([ - '--with-build-python={python_host_bin}', - ]) - '''The configure arguments needed to build the python recipe. Those are used in method :meth:`build_arch` (if not overwritten like python3's recipe does). @@ -210,6 +182,34 @@ def link_version(self): flags=flags ) + def apply_patches(self, arch, build_dir=None): + + _p_version = Version(self.version) + if _p_version.major == 3 and _p_version.minor == 7: + self.patches += [ + 'patches/py3.7.1_fix-ctypes-util-find-library.patch', + 'patches/py3.7.1_fix-zlib-version.patch', + ] + + if 8 <= _p_version.minor <= 10: + self.patches.append('patches/py3.8.1.patch') + + if _p_version.minor >= 11: + self.patches.append('patches/cpython-311-ctypes-find-library.patch') + + if _p_version.minor >= 14: + self.patches.append('patches/3.14_armv7l_fix.patch') + self.patches.append('patches/3.14_fix_remote_debug.patch') + + if shutil.which('lld') is not None: + if _p_version.minor == 7: + self.patches.append("patches/py3.7.1_fix_cortex_a8.patch") + elif _p_version.minor >= 8: + self.patches.append("patches/py3.8.1_fix_cortex_a8.patch") + + self.patches = list(set(self.patches)) + super().apply_patches(arch, build_dir) + def include_root(self, arch_name): return join(self.get_build_dir(arch_name), 'Include') @@ -317,9 +317,15 @@ def add_flags(include_flags, link_dirs, link_libs): env['ZLIB_VERSION'] = line.replace('#define ZLIB_VERSION ', '') add_flags(' -I' + zlib_includes, ' -L' + zlib_lib_path, ' -lz') - if self._p_version.minor >= 13 and self.disable_gil: + _p_version = Version(self.version) + if _p_version.minor >= 11: + self.configure_args.append('--with-build-python={python_host_bin}') + + if _p_version.minor >= 13 and self.disable_gil: self.configure_args.append("--disable-gil") + self.configure_args = list(set(self.configure_args)) + return env def build_arch(self, arch): From a4a8b28144249f6f4865e6186af71a1385f84f7d Mon Sep 17 00:00:00 2001 From: Dexer <73297572+DexerBR@users.noreply.github.com> Date: Fri, 13 Mar 2026 11:52:51 -0300 Subject: [PATCH 15/82] fix kivy recipe; bump sdl3 and sdl3_image (#3198) --- pythonforandroid/recipes/kivy/__init__.py | 23 ++++++++++++++----- pythonforandroid/recipes/sdl3/__init__.py | 4 ++-- .../recipes/sdl3_image/__init__.py | 2 +- .../recipes/sdl3_image/enable-webp.patch | 18 +++++++++++---- 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/pythonforandroid/recipes/kivy/__init__.py b/pythonforandroid/recipes/kivy/__init__.py index c545bbc4c1..5f59457a7d 100644 --- a/pythonforandroid/recipes/kivy/__init__.py +++ b/pythonforandroid/recipes/kivy/__init__.py @@ -7,17 +7,25 @@ from pythonforandroid.toolchain import current_directory, shprint -def is_kivy_affected_by_deadlock_issue(recipe=None, arch=None): +def get_kivy_version(recipe, arch): with current_directory(join(recipe.get_build_dir(arch.arch), "kivy")): - kivy_version = shprint( + return shprint( sh.Command(sys.executable), "-c", "import _version; print(_version.__version__)", ) - return packaging.version.parse( - str(kivy_version) - ) < packaging.version.Version("2.2.0.dev0") + +def is_kivy_affected_by_deadlock_issue(recipe=None, arch=None): + return packaging.version.parse( + str(get_kivy_version(recipe, arch)) + ) < packaging.version.Version("2.2.0.dev0") + + +def is_kivy_less_than_3(recipe=None, arch=None): + return packaging.version.parse( + str(get_kivy_version(recipe, arch)) + ) < packaging.version.Version("3.0.0") class KivyRecipe(PyProjectRecipe): @@ -34,7 +42,7 @@ class KivyRecipe(PyProjectRecipe): # WARNING: Remove this patch when a new Kivy version is released. patches = [ ("sdl-gl-swapwindow-nogil.patch", is_kivy_affected_by_deadlock_issue), - "use_cython.patch", + ("use_cython.patch", is_kivy_less_than_3), "no-ast-str.patch" ] @@ -59,6 +67,9 @@ def get_recipe_env(self, arch, **kwargs): # NDKPLATFORM is our switch for detecting Android platform, so can't be None env['NDKPLATFORM'] = "NOTNONE" + if not is_kivy_less_than_3(self, arch): + env['KIVY_CROSS_PLATFORM'] = 'android' + if 'sdl2' in self.ctx.recipe_build_order: env['USE_SDL2'] = '1' env['KIVY_SPLIT_EXAMPLES'] = '1' diff --git a/pythonforandroid/recipes/sdl3/__init__.py b/pythonforandroid/recipes/sdl3/__init__.py index 139509c3e8..b4735664d8 100644 --- a/pythonforandroid/recipes/sdl3/__init__.py +++ b/pythonforandroid/recipes/sdl3/__init__.py @@ -6,9 +6,9 @@ class LibSDL3Recipe(BootstrapNDKRecipe): - version = "3.2.18" + version = "3.4.2" url = "https://github.com/libsdl-org/SDL/releases/download/release-{version}/SDL3-{version}.tar.gz" - md5sum = "c7808ef624b74e2ac69cf531e78e0c6e" + md5sum = "b488ea1ede947c06855588314effe905" conflicts = ["sdl2"] diff --git a/pythonforandroid/recipes/sdl3_image/__init__.py b/pythonforandroid/recipes/sdl3_image/__init__.py index f6d705b168..0a09dff97c 100644 --- a/pythonforandroid/recipes/sdl3_image/__init__.py +++ b/pythonforandroid/recipes/sdl3_image/__init__.py @@ -6,7 +6,7 @@ class LibSDL3Image(BootstrapNDKRecipe): - version = "3.2.4" + version = "3.4.0" url = "https://github.com/libsdl-org/SDL_image/releases/download/release-{version}/SDL3_image-{version}.tar.gz" dir_name = "SDL3_image" diff --git a/pythonforandroid/recipes/sdl3_image/enable-webp.patch b/pythonforandroid/recipes/sdl3_image/enable-webp.patch index 98d72f2017..b623542833 100644 --- a/pythonforandroid/recipes/sdl3_image/enable-webp.patch +++ b/pythonforandroid/recipes/sdl3_image/enable-webp.patch @@ -1,12 +1,22 @@ -diff -Naur SDL2_image.orig/Android.mk SDL2_image/Android.mk ---- SDL2_image.orig/Android.mk 2022-10-03 20:51:52.000000000 +0200 -+++ SDL2_image/Android.mk 2022-10-03 20:52:48.000000000 +0200 -@@ -32,7 +32,7 @@ +--- a/Android.mk ++++ b/Android.mk +@@ -33,8 +33,8 @@ # Enable this if you want to support loading WebP images # The library path should be a relative path to this directory. -SUPPORT_WEBP ?= false +-SUPPORT_SAVE_WEBP ?= true +SUPPORT_WEBP := true ++SUPPORT_SAVE_WEBP := true WEBP_LIBRARY_PATH := external/libwebp +@@ -160,7 +160,7 @@ + ifeq ($(SUPPORT_WEBP),true) + LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(WEBP_LIBRARY_PATH)/src + LOCAL_CFLAGS += -DLOAD_WEBP +- LOCAL_STATIC_LIBRARIES += webpdemux ++ LOCAL_STATIC_LIBRARIES += webpmux webpdemux + LOCAL_STATIC_LIBRARIES += webp + ifeq ($(SUPPORT_SAVE_WEBP),true) + LOCAL_CFLAGS += -DSAVE_WEBP=1 \ No newline at end of file From 208ab265693251a8b6a5bf315d2d2f1447f98b65 Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 24 Mar 2026 14:08:31 +0100 Subject: [PATCH 16/82] chore: Update README to include PySDL3 support --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 21cf3bc3ee..e4d3062b37 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ It supports multiple CPU architectures. It supports apps developed with [Kivy framework](http://kivy.org), but was built to be flexible about the backend libraries (through "bootstraps"), and -also supports [PySDL2](https://pypi.org/project/PySDL2/), and a +also supports [PySDL2](https://pypi.org/project/PySDL2/), [PySDL3](https://github.com/Aermoss/PySDL3) and a [WebView](https://developer.android.com/reference/android/webkit/WebView) with a Python web server. From 2f107b154062afec1587f2ceeab8ac6fc56c8854 Mon Sep 17 00:00:00 2001 From: Ansh Dadwal Date: Sat, 28 Mar 2026 17:51:13 +0530 Subject: [PATCH 17/82] Add support for prebuilt wheels (#3280) Add support for prebuilt wheels --- pythonforandroid/build.py | 58 ++++++++-- pythonforandroid/recipe.py | 101 +++++++++++++++--- .../recipes/hostpython3/__init__.py | 9 ++ pythonforandroid/toolchain.py | 44 ++++++++ tests/test_build.py | 30 +++++- 5 files changed, 219 insertions(+), 23 deletions(-) diff --git a/pythonforandroid/build.py b/pythonforandroid/build.py index 7758bcfd8c..c8259c8bb0 100644 --- a/pythonforandroid/build.py +++ b/pythonforandroid/build.py @@ -11,6 +11,7 @@ import re import shutil import subprocess +import sys import sh @@ -21,7 +22,7 @@ from pythonforandroid.archs import ArchARM, ArchARMv7_a, ArchAarch_64, Archx86, Archx86_64 from pythonforandroid.logger import (info, warning, info_notify, info_main, shprint, Out_Style, Out_Fore) from pythonforandroid.pythonpackage import get_package_name -from pythonforandroid.recipe import CythonRecipe, Recipe +from pythonforandroid.recipe import CythonRecipe, Recipe, PyProjectRecipe from pythonforandroid.recommendations import ( check_ndk_version, check_target_api, check_ndk_api, RECOMMENDED_NDK_API, RECOMMENDED_TARGET_API) @@ -101,6 +102,14 @@ class Context: java_build_tool = 'auto' + skip_prebuilt = False + + extra_index_urls = [] + + use_prebuilt_version_for = [] + + save_wheel_dir = '' + @property def packages_path(self): '''Where packages are downloaded before being unpacked''' @@ -503,6 +512,10 @@ def build_recipes(build_order, python_modules, ctx, project_dir, recipe.prepare_build_dir(arch.arch) info_main('# Prebuilding recipes') + # ensure we have `ctx.python_recipe` and `ctx.hostpython` + Recipe.get_recipe("python3", ctx).prebuild_arch(arch) + ctx.hostpython = Recipe.get_recipe("hostpython3", ctx).python_exe + # 2) prebuild packages for recipe in recipes: info_main('Prebuilding {} for {}'.format(recipe.name, arch.arch)) @@ -667,7 +680,17 @@ def is_wheel_platform_independent(whl_name): return all(tag.platform == "any" for tag in tags) -def process_python_modules(ctx, modules): +def is_wheel_compatible(whl_name, arch, ctx): + name, version, build, tags = parse_wheel_filename(whl_name) + supported_tags = PyProjectRecipe.get_wheel_platform_tags(arch.arch, ctx) + supported_tags.append("any") + result = all(tag.platform in supported_tags for tag in tags) + if not result: + warning(f"Incompatible module : {whl_name}") + return result + + +def process_python_modules(ctx, modules, arch): """Use pip --dry-run to resolve dependencies and filter for pure-Python packages """ modules = list(modules) @@ -702,6 +725,7 @@ def process_python_modules(ctx, modules): # setup hostpython recipe env = environ.copy() + host_recipe = None try: host_recipe = Recipe.get_recipe("hostpython3", ctx) _python_path = host_recipe.get_path_to_python() @@ -710,14 +734,32 @@ def process_python_modules(ctx, modules): _python_path, "Modules") + ":" + (libdir[0] if libdir else "") pip = host_recipe.pip except Exception: - # hostpython3 non available so we use system pip (like in tests) + # hostpython3 is unavailable, so fall back to system pip pip = sh.Command("pip") + # add platform tags + platforms = [] + tags = PyProjectRecipe.get_wheel_platform_tags(arch.arch, ctx) + for tag in tags: + platforms.append(f"--platform={tag}") + + if host_recipe is not None: + platforms.extend(["--python-version", host_recipe.version]) + else: + # use the version of the currently running Python interpreter + current_version = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}" + platforms.extend(["--python-version", current_version]) + + indices = [] + # add extra index urls + for index in ctx.extra_index_urls: + indices.extend(["--extra-index-url", index]) try: shprint( pip, 'install', *modules, '--dry-run', '--break-system-packages', '--ignore-installed', - '--report', path, '-q', _env=env + '--disable-pip-version-check', '--only-binary=:all:', + '--report', path, '-q', *platforms, *indices, _env=env ) except Exception as e: warning(f"Auto module resolution failed: {e}") @@ -751,7 +793,9 @@ def process_python_modules(ctx, modules): filename = basename(module["download_info"]["url"]) pure_python = True - if (filename.endswith(".whl") and not is_wheel_platform_independent(filename)): + if ( + filename.endswith(".whl") and not is_wheel_compatible(filename, arch, ctx) + ): any_not_pure_python = True pure_python = False @@ -769,7 +813,7 @@ def process_python_modules(ctx, modules): ) if pure_python: - processed_modules.append(f"{mname}=={mver}") + processed_modules.append(module["download_info"]["url"]) info(" ") if any_not_pure_python: @@ -793,7 +837,7 @@ def run_pymodules_install(ctx, arch, modules, project_dir=None, info('*** PYTHON PACKAGE / PROJECT INSTALL STAGE FOR ARCH: {} ***'.format(arch)) - modules = process_python_modules(ctx, modules) + modules = process_python_modules(ctx, modules, arch) modules = [m for m in modules if ctx.not_has_package(m, arch)] diff --git a/pythonforandroid/recipe.py b/pythonforandroid/recipe.py index 32bc2ec2b0..6aa558778e 100644 --- a/pythonforandroid/recipe.py +++ b/pythonforandroid/recipe.py @@ -923,8 +923,7 @@ def real_hostpython_location(self): if host_name == 'hostpython3': return self._host_recipe.python_exe else: - python_recipe = self.ctx.python_recipe - return 'python{}'.format(python_recipe.version) + return 'python{}'.format(self.ctx.python_recipe.version) @property def hostpython_location(self): @@ -1248,6 +1247,59 @@ class PyProjectRecipe(PythonRecipe): extra_build_args = [] call_hostpython_via_targetpython = False + def get_pip_name(self): + name_str = self.name + if self.name not in self.ctx.use_prebuilt_version_for and self.version is not None: + # Like: v2.3.0 -> 2.3.0 + cleaned_version = self.version.lstrip("v") + name_str += f"=={cleaned_version}" + return name_str + + def get_pip_install_args(self, arch): + python_recipe = Recipe.get_recipe("python3", self.ctx) + opts = [ + "install", + self.get_pip_name(), + "--ignore-installed", + "--disable-pip-version-check", + "--python-version", + python_recipe.version, + "--only-binary=:all:", + "--no-deps", + ] + # add platform tags + tags = PyProjectRecipe.get_wheel_platform_tags(arch.arch, self.ctx) + for tag in tags: + opts.append(f"--platform={tag}") + + # add extra index urls + for index in self.ctx.extra_index_urls: + opts.extend(["--extra-index-url", index]) + + return opts + + def lookup_prebuilt(self, arch): + pip_options = self.get_pip_install_args(arch) + # do not install + pip_options.extend(["--dry-run", "-q"]) + pip_env = self.get_hostrecipe_env() + try: + shprint(self._host_recipe.pip, *pip_options, _env=pip_env) + except Exception: + return False + return True + + def check_prebuilt(self, arch, msg=""): + if self.ctx.skip_prebuilt: + return False + + if self.lookup_prebuilt(arch): + if msg != "": + info(f"Prebuilt pip wheel found, {msg}") + return True + + return False + def get_recipe_env(self, arch, **kwargs): # Custom hostpython self.ctx.python_recipe.python_exe = join( @@ -1259,24 +1311,42 @@ def get_recipe_env(self, arch, **kwargs): with open(build_opts, "w") as file: file.write("[bdist_wheel]\nplat_name={}".format( - self.get_wheel_platform_tag(arch) + self.get_wheel_platform_tag(arch.arch) )) file.close() env["DIST_EXTRA_CONFIG"] = build_opts return env - def get_wheel_platform_tag(self, arch): + @staticmethod + def get_wheel_platform_tags(arch, ctx): # https://peps.python.org/pep-0738/#packaging # official python only supports 64 bit: # android_21_arm64_v8a # android_21_x86_64 - return f"android_{self.ctx.ndk_api}_" + { - "arm64-v8a": "arm64_v8a", - "x86_64": "x86_64", - "armeabi-v7a": "arm", - "x86": "i686", - }[arch.arch] + _suffix = { + "arm64-v8a": ["arm64_v8a", "aarch64"], + "x86_64": ["x86_64"], + "armeabi-v7a": ["arm"], + "x86": ["i686"], + }[arch] + return [f"android_{ctx.ndk_api}_" + _ for _ in _suffix] + + def get_wheel_platform_tag(self, arch): + return PyProjectRecipe.get_wheel_platform_tags(arch, self.ctx)[0] + + def install_prebuilt_wheel(self, arch): + info("Installing prebuilt wheel") + destination = self.ctx.get_python_install_dir(arch.arch) + pip_options = self.get_pip_install_args(arch) + pip_options.extend(["--target", destination]) + pip_options.append("--upgrade") + pip_env = self.get_hostrecipe_env() + try: + shprint(self._host_recipe.pip, *pip_options, _env=pip_env) + except Exception: + return False + return True def install_wheel(self, arch, built_wheels): with patch_wheel_setuptools_logging(): @@ -1287,16 +1357,18 @@ def install_wheel(self, arch, built_wheels): # Fix wheel platform tag wheel_tag = wheel_tags( _wheel, - platform_tags=self.get_wheel_platform_tag(arch), + platform_tags=self.get_wheel_platform_tag(arch.arch), remove=True, ) selected_wheel = join(built_wheel_dir, wheel_tag) - _dev_wheel_dir = environ.get("P4A_WHEEL_DIR", False) if _dev_wheel_dir: ensure_dir(_dev_wheel_dir) shprint(sh.cp, selected_wheel, _dev_wheel_dir) + if exists(self.ctx.save_wheel_dir): + shprint(sh.cp, selected_wheel, self.ctx.save_wheel_dir) + info(f"Installing built wheel: {wheel_tag}") destination = self.ctx.get_python_install_dir(arch.arch) with WheelFile(selected_wheel) as wf: @@ -1305,6 +1377,11 @@ def install_wheel(self, arch, built_wheels): wf.close() def build_arch(self, arch): + if self.check_prebuilt(arch, "skipping build_arch"): + result = self.install_prebuilt_wheel(arch) + if result: + return + warning("Failed to install prebuilt wheel, falling back to build_arch") build_dir = self.get_build_dir(arch.arch) if not (isfile(join(build_dir, "pyproject.toml")) or isfile(join(build_dir, "setup.py"))): diff --git a/pythonforandroid/recipes/hostpython3/__init__.py b/pythonforandroid/recipes/hostpython3/__init__.py index 199cdb50c3..7dc28d00f1 100644 --- a/pythonforandroid/recipes/hostpython3/__init__.py +++ b/pythonforandroid/recipes/hostpython3/__init__.py @@ -48,6 +48,15 @@ class HostPython3Recipe(Recipe): patches = ["fix_ensurepip.patch"] + # apply version guard + def download(self): + python_recipe = Recipe.get_recipe("python3", self.ctx) + if python_recipe.version != self.version: + raise BuildInterruptingException( + f"python3 should have same version as hostpython3, {python_recipe.version} != {self.version}" + ) + super().download() + @property def _exe_name(self): ''' diff --git a/pythonforandroid/toolchain.py b/pythonforandroid/toolchain.py index 3987647f9b..2fec092640 100644 --- a/pythonforandroid/toolchain.py +++ b/pythonforandroid/toolchain.py @@ -188,6 +188,7 @@ class NoAbbrevParser(argparse.ArgumentParser): This subclass alternative is follows the suggestion at https://bugs.python.org/issue14910. """ + def _get_option_tuples(self, option_string): return [] @@ -267,6 +268,44 @@ def __init__(self): '--arch', help='The archs to build for.', action='append', default=[]) + generic_parser.add_argument( + '--extra-index-url', + help=( + 'Extra package indexes to look for prebuilt Android wheels. ' + 'Can be used multiple times.' + ), + action='append', + default=[], + dest="extra_index_urls", + ) + + generic_parser.add_argument( + '--skip-prebuilt', + help='Always build from source; do not use prebuilt wheels.', + action='store_true', + default=False, + dest="skip_prebuilt", + ) + + generic_parser.add_argument( + '--use-prebuilt-version-for', + help=( + 'For these packages, ignore pinned versions and use the latest ' + 'prebuilt version from the extra index if available. ' + 'Only applies to packages with a recipe.' + ), + action='append', + default=[], + dest="use_prebuilt_version_for", + ) + + generic_parser.add_argument( + '--save-wheel-dir', + dest='save_wheel_dir', + default='', + help='Directory to store wheels built by PyProjectRecipe.', + ) + # Options for specifying the Distribution generic_parser.add_argument( '--dist-name', '--dist_name', @@ -672,6 +711,11 @@ def add_parser(subparsers, *args, **kwargs): self.ctx.activity_class_name = args.activity_class_name self.ctx.service_class_name = args.service_class_name + self.ctx.extra_index_urls = args.extra_index_urls + self.ctx.skip_prebuilt = args.skip_prebuilt + self.ctx.use_prebuilt_version_for = args.use_prebuilt_version_for + self.ctx.save_wheel_dir = args.save_wheel_dir + # Each subparser corresponds to a method command = args.subparser_name.replace('-', '_') getattr(self, command)(args) diff --git a/tests/test_build.py b/tests/test_build.py index 92055400e6..e0583e750f 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -5,7 +5,7 @@ import jinja2 from pythonforandroid.build import ( - Context, RECOMMENDED_TARGET_API, run_pymodules_install, process_python_modules + Context, RECOMMENDED_TARGET_API, run_pymodules_install, process_python_modules, is_wheel_compatible ) from pythonforandroid.archs import ArchARMv7_a, ArchAarch_64 @@ -29,20 +29,42 @@ def test_run_pymodules_install_optional_project_dir(self): def test_python_module_parser(self): ctx = mock.Mock(recipe_build_order=[]) ctx.archs = [ArchARMv7_a(ctx), ArchAarch_64(ctx)] + ctx.extra_index_urls = [] + ctx.ndk_api = 24 + arch = ctx.archs[0] + # should not alter original module name (like with adding version number) - assert "kivy_garden.frostedglass" in process_python_modules(ctx, ["kivy_garden.frostedglass"]) + assert "kivy_garden.frostedglass" in process_python_modules(ctx, ["kivy_garden.frostedglass"], arch) # should skip urls and other unsupported format modules = ["https://example.com/some.zip", "git+https://github.com/kivy/python-for-android@develop"] - result = process_python_modules(ctx, modules) + result = process_python_modules(ctx, modules, arch) assert modules == result + def test_is_wheel_compatible(self): + ctx = mock.Mock(recipe_build_order=[]) + ctx.archs = [ArchARMv7_a(ctx), ArchAarch_64(ctx)] + ctx.ndk_api = 24 + arch = ctx.archs[0] + + assert is_wheel_compatible("test-7.1.0-0-cp314-cp314-android_24_aarch64.whl", ctx.archs[1], ctx) + assert is_wheel_compatible("test-7.1.0-0-cp314-cp314-android_24_arm.whl", ctx.archs[0], ctx) + assert is_wheel_compatible("certifi-2026.1.4-py3-none-any.whl", arch, ctx) + + # arches are diff + assert not is_wheel_compatible("test-7.1.0-0-cp314-cp314-android_24_aarch64.whl", ctx.archs[0], ctx) + + # other os + assert not is_wheel_compatible("test-7.1.0-0-cp313-cp313-some_other_os.whl", arch, ctx) + assert not is_wheel_compatible("mmh3-5.2.0-cp314-cp314t-win_amd64.whl", arch, ctx) + def test_strip_if_with_debug_symbols(self): ctx = mock.Mock(recipe_build_order=[]) ctx.python_recipe.major_minor_version_string = "3.6" ctx.get_site_packages_dir.return_value = "test-doesntexist" ctx.build_dir = "nonexistant_directory" - ctx.archs = ["arm64"] + ctx.extra_index_urls = [] + ctx.archs = [ArchAarch_64(ctx)] modules = ["mymodule"] project_dir = None From 869c74bbab79ae4f93955862b641d5169a93f92a Mon Sep 17 00:00:00 2001 From: Ansh Dadwal Date: Sat, 25 Apr 2026 17:28:07 +0530 Subject: [PATCH 18/82] fix PYTHONPATH hacks (#3301) * fix PYTHONPATH hacks * fix android recipe * fix numpy and matplotlib build * no shebang patching required now * fix kivy master build * fix numpy build * more wrappers for meson recipe * flake8 fix * add back pandas host preq * fix bug in logger * add back cython for pandas --- pythonforandroid/build.py | 4 - pythonforandroid/logger.py | 12 ++ pythonforandroid/meson_python.py | 76 ++++++++++ pythonforandroid/recipe.py | 137 ++++++++++++++---- .../recipes/android/src/pyproject.toml | 7 + .../recipes/hostpython3/__init__.py | 88 ++++++----- pythonforandroid/recipes/kivy/__init__.py | 2 +- .../recipes/matplotlib/__init__.py | 30 ++-- .../recipes/matplotlib/meson.patch | 21 --- pythonforandroid/recipes/numpy/__init__.py | 37 ++--- pythonforandroid/recipes/pandas/__init__.py | 2 +- pythonforandroid/recipes/python3/__init__.py | 27 ++-- pythonforandroid/recipes/scipy/__init__.py | 1 - tests/recipes/test_hostpython3.py | 8 +- tests/recipes/test_python3.py | 18 +-- 15 files changed, 310 insertions(+), 160 deletions(-) create mode 100644 pythonforandroid/meson_python.py create mode 100644 pythonforandroid/recipes/android/src/pyproject.toml delete mode 100644 pythonforandroid/recipes/matplotlib/meson.patch diff --git a/pythonforandroid/build.py b/pythonforandroid/build.py index c8259c8bb0..d88fdb1fef 100644 --- a/pythonforandroid/build.py +++ b/pythonforandroid/build.py @@ -728,10 +728,6 @@ def process_python_modules(ctx, modules, arch): host_recipe = None try: host_recipe = Recipe.get_recipe("hostpython3", ctx) - _python_path = host_recipe.get_path_to_python() - libdir = glob.glob(join(_python_path, "build", "lib*")) - env['PYTHONPATH'] = host_recipe.site_dir + ":" + join( - _python_path, "Modules") + ":" + (libdir[0] if libdir else "") pip = host_recipe.pip except Exception: # hostpython3 is unavailable, so fall back to system pip diff --git a/pythonforandroid/logger.py b/pythonforandroid/logger.py index 8bcf85c2ee..af252a2697 100644 --- a/pythonforandroid/logger.py +++ b/pythonforandroid/logger.py @@ -135,6 +135,13 @@ def shprint(command, *args, **kwargs): kwargs["_out_bufsize"] = 1 kwargs["_err_to_out"] = True kwargs["_bg"] = True + + # silent mode + silent = kwargs.get("silent", False) + kwargs.pop("silent", False) + if silent: + kwargs["_out"] = None + is_critical = kwargs.pop('_critical', False) tail_n = kwargs.pop('_tail', None) full_debug = False @@ -190,6 +197,11 @@ def shprint(command, *args, **kwargs): Err_Style.RESET_ALL, ' ', width=(columns - 1))) stdout.flush() except sh.ErrorReturnCode as err: + if silent: + if is_critical: + exit(1) + else: + raise if need_closing_newline: stdout.write('{}\r{:>{width}}\r'.format( Err_Style.RESET_ALL, ' ', width=(columns - 1))) diff --git a/pythonforandroid/meson_python.py b/pythonforandroid/meson_python.py new file mode 100644 index 0000000000..cd3ed9d508 --- /dev/null +++ b/pythonforandroid/meson_python.py @@ -0,0 +1,76 @@ +import sys +import json +import subprocess +import importlib.util +from os.path import join +from glob import glob + + +class C: + TARGET_PYTHON_PREFIX = globals().get("TARGET_PYTHON_PREFIX") + PYTHON_MAJOR_VERSION = globals().get("PYTHON_MAJOR_VERSION", sys.version_info.major) + PYTHON_MINOR_VERSION = globals().get("PYTHON_MINOR_VERSION", sys.version_info.minor) + PLATFORM_TAG = globals().get("PLATFORM_TAG", sys.platform) + PYTHON_SUFFIX = globals().get("PYTHON_SUFFIX", "") + + +def handle_python_info(): + + prefix = C.TARGET_PYTHON_PREFIX + + sysconfig_file = glob(join(prefix, "lib/python3.14/_sysconfigdata*.py"))[0] + + spec = importlib.util.spec_from_file_location("_android_cfg", sysconfig_file) + cfg = importlib.util.module_from_spec(spec) + spec.loader.exec_module(cfg) + + ver_python = f"python{C.PYTHON_MAJOR_VERSION}.{C.PYTHON_MINOR_VERSION}" + + site_path = join(prefix, f"lib/{ver_python}/site-packages") + + android_paths = { + "stdlib": join(prefix, "lib"), + "platstdlib": join(prefix, "lib"), + "purelib": site_path, + "platlib": site_path, + "include": join(prefix, f"include/{ver_python}/"), + "platinclude": join(prefix, f"include/{ver_python}/"), + "scripts": join(prefix, "bin"), + "data": prefix, + } + + print( + json.dumps( + { + "variables": cfg.build_time_vars, + "paths": android_paths, + "sysconfig_paths": android_paths, + "install_paths": android_paths, + "version": f"{C.PYTHON_MAJOR_VERSION}.{C.PYTHON_MINOR_VERSION}", + "platform": C.PLATFORM_TAG, + "is_pypy": False, + "is_venv": False, + "link_libpython": True, + "suffix": C.PYTHON_SUFFIX, + "limited_api_suffix": ".abi3.so", + "is_freethreaded": False, + } + ) + ) + + +WHITELIST = { + "python_info.py": handle_python_info, +} + + +args = sys.argv[1:] + +if args: + cmd = args[0] + name = cmd.split("/")[-1] + + if name in WHITELIST: + sys.exit(WHITELIST[name]()) + +sys.exit(subprocess.run([sys.executable] + args).returncode) diff --git a/pythonforandroid/recipe.py b/pythonforandroid/recipe.py index 6aa558778e..55db2bc194 100644 --- a/pythonforandroid/recipe.py +++ b/pythonforandroid/recipe.py @@ -5,13 +5,15 @@ from re import match import sh +import subprocess import shutil import fnmatch import zipfile import urllib.request from urllib.request import urlretrieve -from os import listdir, unlink, environ, curdir, walk +from os import listdir, unlink, environ, curdir, walk, chmod from sys import stdout +from packaging.version import Version from multiprocessing import cpu_count import time try: @@ -966,7 +968,8 @@ def patch_shebangs(self, path, original_bin): # set correct shebang for file in listdir(path): _file = join(path, file) - self.patch_shebang(_file, original_bin) + if isfile(_file): + self.patch_shebang(_file, original_bin) def get_recipe_env(self, arch=None, with_flags_in_cc=True): if self._host_recipe is None: @@ -976,11 +979,7 @@ def get_recipe_env(self, arch=None, with_flags_in_cc=True): # Set the LANG, this isn't usually important but is a better default # as it occasionally matters how Python e.g. reads files env['LANG'] = "en_GB.UTF-8" - - # Binaries made by packages installed by pip - self.patch_shebangs(self._host_recipe.local_bin, self._host_recipe.python_exe) env["PATH"] = self._host_recipe.local_bin + ":" + self._host_recipe.site_bin + ":" + env["PATH"] - host_env = self.get_hostrecipe_env(arch) env['PYTHONPATH'] = host_env["PYTHONPATH"] @@ -1031,10 +1030,8 @@ def install_python_package(self, arch, name=None, env=None, is_dir=True): def get_hostrecipe_env(self, arch=None): env = environ.copy() - _python_path = self._host_recipe.get_path_to_python() - libdir = glob.glob(join(_python_path, "build", "lib*")) - env['PYTHONPATH'] = self._host_recipe.site_dir + ":" + join( - _python_path, "Modules") + ":" + (libdir[0] if libdir else "") + env['PYTHONPATH'] = '' + env['HOME'] = '/tmp' return env @property @@ -1063,14 +1060,10 @@ def install_hostpython_prerequisites(self, packages=None, force_upgrade=True): pip_options = [ "install", *packages, - "--target", self._host_recipe.site_dir, "--python-version", - self.ctx.python_recipe.version, - # Don't use sources, instead wheels - "--only-binary=:all:", + "-q", ] if force_upgrade: pip_options.append("--upgrade") - # Use system's pip pip_env = self.get_hostrecipe_env() shprint(self._host_recipe.pip, *pip_options, _env=pip_env) @@ -1284,7 +1277,7 @@ def lookup_prebuilt(self, arch): pip_options.extend(["--dry-run", "-q"]) pip_env = self.get_hostrecipe_env() try: - shprint(self._host_recipe.pip, *pip_options, _env=pip_env) + shprint(self._host_recipe.pip, *pip_options, _env=pip_env, silent=True) except Exception: return False return True @@ -1301,9 +1294,6 @@ def check_prebuilt(self, arch, msg=""): return False def get_recipe_env(self, arch, **kwargs): - # Custom hostpython - self.ctx.python_recipe.python_exe = join( - self.ctx.python_recipe.get_build_dir(arch), "android-build", "python3") env = super().get_recipe_env(arch, **kwargs) build_dir = self.get_build_dir(arch) ensure_dir(build_dir) @@ -1316,6 +1306,8 @@ def get_recipe_env(self, arch, **kwargs): file.close() env["DIST_EXTRA_CONFIG"] = build_opts + python_recipe = Recipe.get_recipe("python3", self.ctx) + env["INCLUDEPY"] = python_recipe.include_root(arch.arch) return env @staticmethod @@ -1387,18 +1379,14 @@ def build_arch(self, arch): if not (isfile(join(build_dir, "pyproject.toml")) or isfile(join(build_dir, "setup.py"))): warning("Skipping build because it does not appear to be a Python project.") return - self.install_hostpython_prerequisites( packages=["build[virtualenv]", "pip", "setuptools", "patchelf"] + self.hostpython_prerequisites ) - self.patch_shebangs(self._host_recipe.site_bin, self.real_hostpython_location) env = self.get_recipe_env(arch, with_flags_in_cc=True) # make build dir separately sub_build_dir = join(build_dir, "p4a_android_build") ensure_dir(sub_build_dir) - # copy hostpython to built python to ensure correct selection of libs and includes - shprint(sh.cp, self.real_hostpython_location, self.ctx.python_recipe.python_exe) build_args = [ "-m", @@ -1411,7 +1399,7 @@ def build_arch(self, arch): built_wheels = [] with current_directory(build_dir): shprint( - sh.Command(self.ctx.python_recipe.python_exe), *build_args, _env=env + sh.Command(self.real_hostpython_location), *build_args, _env=env ) built_wheels = [realpath(whl) for whl in glob.glob("dist/*.whl")] self.install_wheel(arch, built_wheels) @@ -1421,7 +1409,7 @@ class MesonRecipe(PyProjectRecipe): '''Recipe for projects which uses meson as build system''' meson_version = "1.4.0" - ninja_version = "1.11.1.1" + pybind_version = "3.3.0" skip_python = False '''If true, skips all Python build and installation steps. @@ -1430,10 +1418,98 @@ class MesonRecipe(PyProjectRecipe): def sanitize_flags(self, *flag_strings): return " ".join(flag_strings).strip().split(" ") + def get_wrapper_dir(self, arch): + return join(self.get_build_dir(arch.arch), "p4a_wrappers") + + def write_wrapper(self, arch, name, content): + wrapper_dir = self.get_wrapper_dir(arch) + ensure_dir(wrapper_dir) + wrapper_path = join(wrapper_dir, name) + with open(wrapper_path, "w") as f: + f.write(content) + chmod(wrapper_path, 0o755) + return wrapper_path + + def get_python_wrapper(self, arch): + """ + Meson Python introspection runs on the host interpreter, but the + target Python (Android) cannot be executed on the build machine. + + We therefore run host Python and override sysconfig data to emulate + the target Android Python environment during Meson introspection. + """ + python_recipe = Recipe.get_recipe('python3', self.ctx) + target_prefix = python_recipe.get_python_root(arch) + python_file = join(self.ctx.root_dir, 'meson_python.py') + _arch = { + "arm64-v8a": ["aarch64"], + "x86_64": ["x86_64"], + "armeabi-v7a": ["arm"], + "x86": ["i686"], + }[arch.arch][0] + + # Real values pulled from android + # PYTHON_MAJOR_VERSION -> 3 + # PYTHON_MINOR_VERSION -> 14 + # PLATFORM_TAG eg -> 'android-24-arm64_v8a' + # PYTHON_SUFFIX eg -> '.cpython-314-aarch64-linux-android.so' + + _p_version = Version(python_recipe.version) + file_data = f"#!{self.real_hostpython_location}" + file_data += f"\nTARGET_PYTHON_PREFIX='{target_prefix}'" + file_data += f"\nPYTHON_MAJOR_VERSION='{_p_version.major}'" + file_data += f"\nPYTHON_MINOR_VERSION='{_p_version.minor}'" + file_data += f"\nPLATFORM_TAG='{self.get_wheel_platform_tags(arch.arch, self.ctx)[0]}'" + file_data += f"\nPYTHON_SUFFIX='.cpython-{_p_version.major}{_p_version.minor}-{_arch}-linux-android.so'" + + with open(python_file, "r") as f: + file_data += "\n" + f.read() + + return self.write_wrapper(arch, "python", file_data) + + def get_config_wrappers(self, arch, w_type: str): + wrapper_name = "" + version = "" + include_path = "" + + if w_type == "pybind11": + wrapper_name = "pybind11-config" + include_path = join(self._host_recipe.site_dir, "pybind11/include") + + version = None + try: + command = [self._host_recipe.real_hostpython_location, "-c", "import pybind11; print(pybind11.__version__)"] + version = subprocess.check_output(command).decode('utf-8').strip() + except Exception: + warning("Unable to get pybind11 version") + if version is None: + version = self.pybind_version + + elif w_type == "numpy": + wrapper_name = "numpy-config" + recipe = Recipe.get_recipe("numpy", self.ctx) + include_path = recipe.get_include(arch) + version = recipe.version + else: + raise ValueError(f"Unknown wrapper type: {w_type}") + + content = ( + f"#!/bin/sh\n" + f"if [ \"$1\" = \"--version\" ]; then\n" + f" echo '{version}'\n" + f"else\n" + f" echo '-I{include_path}'\n" + f"fi\n" + ) + return self.write_wrapper(arch, wrapper_name, content) + def get_recipe_meson_options(self, arch): env = self.get_recipe_env(arch, with_flags_in_cc=True) return { "binaries": { + "pybind11-config": self.get_config_wrappers(arch, "pybind11"), + "numpy-config": self.get_config_wrappers(arch, "numpy"), + "python": self.get_python_wrapper(arch), "c": arch.get_clang_exe(with_target=True), "cpp": arch.get_clang_exe(with_target=True, plus_plus=True), "ar": self.ctx.ndk.llvm_ar, @@ -1504,13 +1580,18 @@ def build_arch(self, arch): self.ensure_args('-Csetup-args=--cross-file', '-Csetup-args={}'.format(cross_file)) # ensure ninja and meson for dep in [ - "ninja=={}".format(self.ninja_version), + "ninja", "meson=={}".format(self.meson_version), ]: if dep not in self.hostpython_prerequisites: self.hostpython_prerequisites.append(dep) + if not self.skip_python: super().build_arch(arch) + else: + self.install_hostpython_prerequisites( + packages=["build[virtualenv]", "pip", "setuptools", "patchelf"] + self.hostpython_prerequisites + ) class RustCompiledComponentsRecipe(PyProjectRecipe): @@ -1523,8 +1604,6 @@ class RustCompiledComponentsRecipe(PyProjectRecipe): "x86": "i686-linux-android", } - call_hostpython_via_targetpython = False - def get_recipe_env(self, arch, **kwargs): env = super().get_recipe_env(arch, **kwargs) @@ -1563,7 +1642,7 @@ def get_recipe_env(self, arch, **kwargs): env["PATH"] = ("{hostpython_dir}:{old_path}").format( hostpython_dir=Recipe.get_recipe( "hostpython3", self.ctx - ).get_path_to_python(), + ).local_bin, old_path=env["PATH"], ) return env diff --git a/pythonforandroid/recipes/android/src/pyproject.toml b/pythonforandroid/recipes/android/src/pyproject.toml new file mode 100644 index 0000000000..bb5f8b4fa4 --- /dev/null +++ b/pythonforandroid/recipes/android/src/pyproject.toml @@ -0,0 +1,7 @@ +[build-system] +requires = [ + "setuptools", + "wheel", + "Cython>=0.29,<3.1" +] +build-backend = "setuptools.build_meta" diff --git a/pythonforandroid/recipes/hostpython3/__init__.py b/pythonforandroid/recipes/hostpython3/__init__.py index 7dc28d00f1..e44dba605f 100644 --- a/pythonforandroid/recipes/hostpython3/__init__.py +++ b/pythonforandroid/recipes/hostpython3/__init__.py @@ -15,17 +15,13 @@ ) from pythonforandroid.prerequisites import OpenSSLPrerequisite -HOSTPYTHON_VERSION_UNSET_MESSAGE = ( - 'The hostpython recipe must have set version' -) +HOSTPYTHON_VERSION_UNSET_MESSAGE = "The hostpython recipe must have set version" -SETUP_DIST_NOT_FIND_MESSAGE = ( - 'Could not find Setup.dist or Setup in Python build' -) +SETUP_DIST_NOT_FIND_MESSAGE = "Could not find Setup.dist or Setup in Python build" class HostPython3Recipe(Recipe): - ''' + """ The hostpython3's recipe. .. versionchanged:: 2019.10.06.post0 @@ -34,17 +30,17 @@ class HostPython3Recipe(Recipe): .. versionchanged:: 0.6.0 Refactored into the new class :class:`~pythonforandroid.python.HostPythonRecipe` - ''' + """ - version = '3.14.2' + version = "3.14.2" - url = 'https://github.com/python/cpython/archive/refs/tags/v{version}.tar.gz' - '''The default url to download our host python recipe. This url will - change depending on the python version set in attribute :attr:`version`.''' + url = "https://github.com/python/cpython/archive/refs/tags/v{version}.tar.gz" + """The default url to download our host python recipe. This url will + change depending on the python version set in attribute :attr:`version`.""" - build_subdir = 'native-build' - '''Specify the sub build directory for the hostpython3 recipe. Defaults - to ``native-build``.''' + build_subdir = "native-build" + """Specify the sub build directory for the hostpython3 recipe. Defaults + to ``native-build``.""" patches = ["fix_ensurepip.patch"] @@ -59,17 +55,17 @@ def download(self): @property def _exe_name(self): - ''' + """ Returns the name of the python executable depending on the version. - ''' + """ if not self.version: raise BuildInterruptingException(HOSTPYTHON_VERSION_UNSET_MESSAGE) - return f'python{self.version.split(".")[0]}' + return "python" @property def python_exe(self): - '''Returns the full path of the hostpython executable.''' - return join(self.get_path_to_python(), self._exe_name) + """Returns the full path of the hostpython executable.""" + return join(self.local_bin, self._exe_name) def get_recipe_env(self, arch=None): env = os.environ.copy() @@ -91,14 +87,14 @@ def should_build(self, arch): def get_build_container_dir(self, arch=None): choices = self.check_recipe_choices() - dir_name = '-'.join([self.name] + choices) - return join(self.ctx.build_dir, 'other_builds', dir_name, 'desktop') + dir_name = "-".join([self.name] + choices) + return join(self.ctx.build_dir, "other_builds", dir_name, "desktop") def get_build_dir(self, arch=None): - ''' + """ .. note:: Unlike other recipes, the hostpython build dir doesn't depend on the target arch - ''' + """ return join(self.get_build_container_dir(), self.name) def get_path_to_python(self): @@ -112,16 +108,20 @@ def site_root(self): def site_bin(self): return join(self.site_root, self.site_dir, "bin") + @property + def local_dir(self): + return join(self.site_root, "usr/local/") + @property def local_bin(self): - return join(self.site_root, "usr/local/bin/") + return join(self.local_dir, "bin") @property def site_dir(self): p_version = Version(self.version) return join( self.site_root, - f"usr/local/lib/python{p_version.major}.{p_version.minor}/site-packages/" + f"usr/local/lib/python{p_version.major}.{p_version.minor}/site-packages/", ) @property @@ -163,34 +163,40 @@ def build_arch(self, arch): # Configure the build build_configured = False with current_directory(build_dir): - if not Path('config.status').exists(): - shprint(sh.Command(join(recipe_build_dir, 'configure')), _env=env) + if not Path("config.status").exists(): + shprint( + sh.Command(join(recipe_build_dir, "configure")), + "--prefix", + self.local_dir, + _env=env, + ) build_configured = True with current_directory(recipe_build_dir): # Create the Setup file. This copying from Setup.dist is # the normal and expected procedure before Python 3.8, but # after this the file with default options is already named "Setup" - setup_dist_location = join('Modules', 'Setup.dist') + setup_dist_location = join("Modules", "Setup.dist") if Path(setup_dist_location).exists(): - shprint(sh.cp, setup_dist_location, - join(build_dir, 'Modules', 'Setup')) + shprint(sh.cp, setup_dist_location, join(build_dir, "Modules", "Setup")) else: # Check the expected file does exist - setup_location = join('Modules', 'Setup') + setup_location = join("Modules", "Setup") if not Path(setup_location).exists(): - raise BuildInterruptingException( - SETUP_DIST_NOT_FIND_MESSAGE - ) + raise BuildInterruptingException(SETUP_DIST_NOT_FIND_MESSAGE) - shprint(sh.make, '-j', str(cpu_count()), '-C', build_dir, _env=env) + shprint(sh.make, "-j", str(cpu_count()), "-C", build_dir, _env=env) + with current_directory(build_dir): + shprint(sh.make, "install", _env=env) + + with current_directory(recipe_build_dir): # make a copy of the python executable giving it the name we want, # because we got different python's executable names depending on # the fs being case-insensitive (Mac OS X, Cygwin...) or # case-sensitive (linux)...so this way we will have an unique name # for our hostpython, regarding the used fs - for exe_name in ['python.exe', 'python']: + for exe_name in ["python.exe", "python"]: exe = join(self.get_path_to_python(), exe_name) if Path(exe).is_file(): shprint(sh.cp, exe, self.python_exe) @@ -200,10 +206,12 @@ def build_arch(self, arch): self.ctx.hostpython = self.python_exe if build_configured: - shprint( - sh.Command(self.python_exe), "-m", "ensurepip", "--root", self.site_root, "-U", - _env={"HOME": "/tmp", "PATH": self.local_bin} + sh.Command(self.python_exe), + "-m", + "ensurepip", + "-U", + _env={"HOME": "/tmp", "PATH": self.local_bin}, ) self.fix_pip_shebangs() diff --git a/pythonforandroid/recipes/kivy/__init__.py b/pythonforandroid/recipes/kivy/__init__.py index 5f59457a7d..2446c2101b 100644 --- a/pythonforandroid/recipes/kivy/__init__.py +++ b/pythonforandroid/recipes/kivy/__init__.py @@ -25,7 +25,7 @@ def is_kivy_affected_by_deadlock_issue(recipe=None, arch=None): def is_kivy_less_than_3(recipe=None, arch=None): return packaging.version.parse( str(get_kivy_version(recipe, arch)) - ) < packaging.version.Version("3.0.0") + ) < packaging.version.Version("3.0.0.dev0") class KivyRecipe(PyProjectRecipe): diff --git a/pythonforandroid/recipes/matplotlib/__init__.py b/pythonforandroid/recipes/matplotlib/__init__.py index f3ac80bddc..0257dbec31 100644 --- a/pythonforandroid/recipes/matplotlib/__init__.py +++ b/pythonforandroid/recipes/matplotlib/__init__.py @@ -1,29 +1,25 @@ from pythonforandroid.recipe import MesonRecipe -from pythonforandroid.logger import shprint - -from os.path import join -import sh class MatplotlibRecipe(MesonRecipe): - version = '3.10.7' - url = 'https://github.com/matplotlib/matplotlib/archive/v{version}.zip' - depends = ['kiwisolver', 'numpy', 'pillow'] - python_depends = ['cycler', 'fonttools', 'packaging', 'pyparsing', 'python-dateutil'] - hostpython_prerequisites = ["setuptools_scm>=7"] - patches = ["meson.patch"] + version = "3.10.7" + url = "https://github.com/matplotlib/matplotlib/archive/v{version}.zip" + depends = ["kiwisolver", "numpy", "pillow"] + python_depends = [ + "cycler", + "fonttools", + "packaging", + "pyparsing", + "python-dateutil", + ] + pybind_version = "2.13.4" + hostpython_prerequisites = ["meson-python>=0.13.1,<0.17.0", "pybind11>=2.13.2,!=2.13.3", "setuptools_scm>=7"] need_stl_shared = True def get_recipe_env(self, arch, **kwargs): env = super().get_recipe_env(arch, **kwargs) - env['CXXFLAGS'] += ' -Wno-c++11-narrowing' + env["CXXFLAGS"] += " -Wno-c++11-narrowing" return env - def build_arch(self, arch): - python_path = join(self.ctx.python_recipe.get_build_dir(arch), "android-build", "python3") - self.extra_build_args += [f'-Csetup-args=-Dpython3_program={python_path}'] - shprint(sh.cp, self.real_hostpython_location, python_path) - super().build_arch(arch) - recipe = MatplotlibRecipe() diff --git a/pythonforandroid/recipes/matplotlib/meson.patch b/pythonforandroid/recipes/matplotlib/meson.patch deleted file mode 100644 index babab09002..0000000000 --- a/pythonforandroid/recipes/matplotlib/meson.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff '--color=auto' -uNr matplotlib-3.10.7/meson.build matplotlib-3.10.7.mod/meson.build ---- matplotlib-3.10.7/meson.build 2025-10-09 04:16:31.000000000 +0530 -+++ matplotlib-3.10.7.mod/meson.build 2025-10-12 10:19:29.664280049 +0530 -@@ -36,7 +36,7 @@ - - # https://mesonbuild.com/Python-module.html - py_mod = import('python') --py3 = py_mod.find_installation(pure: false) -+py3 = py_mod.find_installation(get_option('python3_program'), pure: false) - py3_dep = py3.dependency() - - pybind11_dep = dependency('pybind11', version: '>=2.13.2') -diff '--color=auto' -uNr matplotlib-3.10.7/meson.options matplotlib-3.10.7.mod/meson.options ---- matplotlib-3.10.7/meson.options 2025-10-09 04:16:31.000000000 +0530 -+++ matplotlib-3.10.7.mod/meson.options 2025-10-12 10:19:23.762042521 +0530 -@@ -28,3 +28,5 @@ - # default is determined by fallback. - option('rcParams-backend', type: 'string', value: 'auto', - description: 'Set default backend at runtime') -+ -+option('python3_program', type : 'string', value : '', description : 'Path to Python 3 executable') diff --git a/pythonforandroid/recipes/numpy/__init__.py b/pythonforandroid/recipes/numpy/__init__.py index 140ff849d8..df1d294438 100644 --- a/pythonforandroid/recipes/numpy/__init__.py +++ b/pythonforandroid/recipes/numpy/__init__.py @@ -2,24 +2,28 @@ from os.path import join import shutil -NUMPY_NDK_MESSAGE = "In order to build numpy, you must set minimum ndk api (minapi) to `24`.\n" +NUMPY_NDK_MESSAGE = ( + "In order to build numpy, you must set minimum ndk api (minapi) to `24`.\n" +) class NumpyRecipe(MesonRecipe): - version = 'v2.3.0' - url = 'git+https://github.com/numpy/numpy' - hostpython_prerequisites = ["Cython>=3.0.6", "numpy"] # meson does not detects venv's cython - extra_build_args = ['-Csetup-args=-Dblas=none', '-Csetup-args=-Dlapack=none'] + version = "v2.3.0" + url = "git+https://github.com/numpy/numpy" + extra_build_args = ["-Csetup-args=-Dblas=none", "-Csetup-args=-Dlapack=none"] need_stl_shared = True min_ndk_api_support = 24 + def get_include(self, arch): + return join( + self.ctx.get_python_install_dir(arch.arch), "numpy/_core/include", + ) + def get_recipe_meson_options(self, arch): options = super().get_recipe_meson_options(arch) - # Custom python is required, so that meson - # gets libs and config files properly - options["binaries"]["python"] = self.ctx.python_recipe.python_exe - options["binaries"]["python3"] = self.ctx.python_recipe.python_exe - options["properties"]["longdouble_format"] = "IEEE_DOUBLE_LE" if arch.arch in ["armeabi-v7a", "x86"] else "IEEE_QUAD_LE" + options["properties"]["longdouble_format"] = ( + "IEEE_DOUBLE_LE" if arch.arch in ["armeabi-v7a", "x86"] else "IEEE_QUAD_LE" + ) return options def get_recipe_env(self, arch, **kwargs): @@ -32,17 +36,16 @@ def get_recipe_env(self, arch, **kwargs): # NPY_DISABLE_SVML=1 allows numpy to build for non-AVX512 CPUs # See: https://github.com/numpy/numpy/issues/21196 env["NPY_DISABLE_SVML"] = "1" - env["TARGET_PYTHON_EXE"] = join(Recipe.get_recipe( - "python3", self.ctx).get_build_dir(arch.arch), "android-build", "python") + env["TARGET_PYTHON_EXE"] = join( + Recipe.get_recipe("python3", self.ctx).get_build_dir(arch.arch), + "android-build", + "python", + ) return env - def build_arch(self, arch): - super().build_arch(arch) - self.restore_hostpython_prerequisites(["cython"]) - def get_hostrecipe_env(self, arch=None): env = super().get_hostrecipe_env(arch=arch) - env['RANLIB'] = shutil.which('ranlib') + env["RANLIB"] = shutil.which("ranlib") return env diff --git a/pythonforandroid/recipes/pandas/__init__.py b/pythonforandroid/recipes/pandas/__init__.py index 6986e9efbe..de937fd1a3 100644 --- a/pythonforandroid/recipes/pandas/__init__.py +++ b/pythonforandroid/recipes/pandas/__init__.py @@ -6,7 +6,7 @@ class PandasRecipe(MesonRecipe): version = 'v2.3.0' url = 'git+https://github.com/pandas-dev/pandas' depends = ['numpy', 'libbz2', 'liblzma'] - hostpython_prerequisites = ["Cython<4.0.0a0", "versioneer", "numpy"] # meson does not detects venv's cython + hostpython_prerequisites = ["versioneer[toml]", "numpy>=2.0", "Cython<4.0.0a0"] # meson does not detects venv's cython patches = ['fix_numpy_includes.patch'] python_depends = ['python-dateutil', 'pytz'] need_stl_shared = True diff --git a/pythonforandroid/recipes/python3/__init__.py b/pythonforandroid/recipes/python3/__init__.py index e36e0b28ad..f3d52ef4c3 100644 --- a/pythonforandroid/recipes/python3/__init__.py +++ b/pythonforandroid/recipes/python3/__init__.py @@ -82,7 +82,6 @@ class Python3Recipe(TargetPythonRecipe): # Android prefix '--prefix={prefix}', - '--exec-prefix={exec_prefix}', '--enable-loadable-sqlite-extensions', # Special cross compile args @@ -211,11 +210,21 @@ def apply_patches(self, arch, build_dir=None): super().apply_patches(arch, build_dir) def include_root(self, arch_name): - return join(self.get_build_dir(arch_name), 'Include') + _p_version = Version(self.version) + return join( + self.get_build_dir(arch_name), 'android-build', 'android-root', + 'include', f'python{_p_version.major}.{_p_version.minor}' + ) def link_root(self, arch_name): return join(self.get_build_dir(arch_name), 'android-build') + def get_python_root(self, arch): + return join(self.get_build_dir(arch.arch), 'android-build', 'android-root') + + def get_android_python_exe(self, arch): + return join(self.get_python_root(arch), 'bin', self.name) + def should_build(self, arch): return not isfile(join(self.link_root(arch.arch), self._libpython)) @@ -342,9 +351,8 @@ def build_arch(self, arch): build_dir = join(recipe_build_dir, 'android-build') ensure_dir(build_dir) - # TODO: Get these dynamically, like bpo-30386 does - sys_prefix = '/usr/local' - sys_exec_prefix = '/usr/local' + sys_prefix = join(build_dir, "android-root") + ensure_dir(sys_prefix) env = self.get_recipe_env(arch) env = self.set_libs_flags(env, arch) @@ -360,11 +368,10 @@ def build_arch(self, arch): *(' '.join(self.configure_args).format( android_host=env['HOSTARCH'], android_build=android_build, - python_host_bin=join(self.get_recipe( + python_host_bin=self.get_recipe( 'host' + self.name, self.ctx - ).get_path_to_python(), "python3"), - prefix=sys_prefix, - exec_prefix=sys_exec_prefix)).split(' '), + ).python_exe, + prefix=sys_prefix).split(' ')), _env=env) shprint( @@ -373,6 +380,8 @@ def build_arch(self, arch): 'INSTSONAME={lib_name}'.format(lib_name=self._libpython), _env=env ) + shprint(sh.make, 'install', _env=env) + # rename executable if isfile("python"): sh.cp('python', 'libpythonbin.so') diff --git a/pythonforandroid/recipes/scipy/__init__.py b/pythonforandroid/recipes/scipy/__init__.py index 8cf46dab11..4406b354a7 100644 --- a/pythonforandroid/recipes/scipy/__init__.py +++ b/pythonforandroid/recipes/scipy/__init__.py @@ -17,7 +17,6 @@ class ScipyRecipe(MesonRecipe): def get_recipe_meson_options(self, arch): options = super().get_recipe_meson_options(arch) - options["binaries"]["python"] = self.ctx.python_recipe.python_exe options["binaries"]["fortran"] = self.place_wrapper(arch) options["properties"]["numpy-include-dir"] = join( self.ctx.get_python_install_dir(arch.arch), "numpy/_core/include" diff --git a/tests/recipes/test_hostpython3.py b/tests/recipes/test_hostpython3.py index df0c5cac05..111cda0b85 100644 --- a/tests/recipes/test_hostpython3.py +++ b/tests/recipes/test_hostpython3.py @@ -27,13 +27,7 @@ def test_property__exe_name_no_version(self): self.recipe._version = hostpython_version def test_property__exe_name(self): - self.assertEqual(self.recipe._exe_name, 'python3') - - def test_property_python_exe(self): - self.assertEqual( - self.recipe.python_exe, - join(self.recipe.get_path_to_python(), 'python3') - ) + self.assertEqual(self.recipe._exe_name, 'python') @mock.patch("pythonforandroid.recipes.hostpython3.Path.exists") def test_should_build(self, mock_exists): diff --git a/tests/recipes/test_python3.py b/tests/recipes/test_python3.py index 57b7ef8e01..e3b69e4bcb 100644 --- a/tests/recipes/test_python3.py +++ b/tests/recipes/test_python3.py @@ -26,14 +26,6 @@ def test_property__libpython(self): f'libpython{self.recipe.link_version}.so' ) - def test_include_root(self): - expected_include_dir = join( - self.recipe.get_build_dir(self.arch.arch), 'Include', - ) - self.assertEqual( - expected_include_dir, self.recipe.include_root(self.arch.arch) - ) - def test_link_root(self): expected_link_root = join( self.recipe.get_build_dir(self.arch.arch), 'android-build', @@ -116,11 +108,11 @@ def test_build_arch( mock_sh_command.mock_calls, ) mock_open_zlib.assert_called() - self.assertEqual(mock_make.call_count, 1) - for make_call, kw in mock_make.call_args_list: - self.assertIn( - f'INSTSONAME={self.recipe._libpython}', make_call - ) + self.assertEqual(mock_make.call_count, 2) + make_call, kw = mock_make.call_args_list[0] + self.assertIn( + f'INSTSONAME={self.recipe._libpython}', make_call + ) mock_cp.assert_called_with( "pyconfig.h", join(recipe_build_dir, 'Include'), ) From b9fc5c7b3e57a856fe85a57085942251f37910e9 Mon Sep 17 00:00:00 2001 From: Kenechukwu Akubue Date: Wed, 29 Apr 2026 23:55:30 +0100 Subject: [PATCH 19/82] Update SDL3_mixer recipe to version 3.2.0 and remove libgme patch --- pythonforandroid/recipes/sdl3_mixer/__init__.py | 6 ++---- .../recipes/sdl3_mixer/disable-libgme.patch | 12 ------------ 2 files changed, 2 insertions(+), 16 deletions(-) delete mode 100644 pythonforandroid/recipes/sdl3_mixer/disable-libgme.patch diff --git a/pythonforandroid/recipes/sdl3_mixer/__init__.py b/pythonforandroid/recipes/sdl3_mixer/__init__.py index 56fb2c7518..b3369c0de9 100644 --- a/pythonforandroid/recipes/sdl3_mixer/__init__.py +++ b/pythonforandroid/recipes/sdl3_mixer/__init__.py @@ -6,12 +6,10 @@ class LibSDL3Mixer(BootstrapNDKRecipe): - version = "72a73339731a12c1002f9caca64f1ab924938102" - url = "https://github.com/libsdl-org/SDL_mixer/archive/{version}.tar.gz" + version = "3.2.0" + url = "https://github.com/libsdl-org/SDL_mixer/releases/download/release-{version}/SDL3_mixer-{version}.tar.gz" dir_name = "SDL3_mixer" - patches = ["disable-libgme.patch"] - def get_include_dirs(self, arch): return [ os.path.join( diff --git a/pythonforandroid/recipes/sdl3_mixer/disable-libgme.patch b/pythonforandroid/recipes/sdl3_mixer/disable-libgme.patch deleted file mode 100644 index 233808e7db..0000000000 --- a/pythonforandroid/recipes/sdl3_mixer/disable-libgme.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -Naur SDL3_mixer.orig/Android.mk SDL3_mixer/Android.mk ---- SDL3_mixer.orig/Android.mk 2025-03-16 21:05:19 -+++ SDL3_mixer/Android.mk 2025-03-16 21:06:33 -@@ -31,7 +31,7 @@ - WAVPACK_LIBRARY_PATH := external/wavpack - - # Enable this if you want to support loading music via libgme --SUPPORT_GME ?= true -+SUPPORT_GME ?= false - GME_LIBRARY_PATH := external/libgme - - # Enable this if you want to support loading MOD music via XMP-lite From f93e9553ef8199a2283d238a7d164ad0854fdd61 Mon Sep 17 00:00:00 2001 From: lanmao Date: Thu, 30 Apr 2026 09:45:38 +0800 Subject: [PATCH 20/82] Fix tflite-runtime numpy include path --- pythonforandroid/recipes/tflite-runtime/__init__.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pythonforandroid/recipes/tflite-runtime/__init__.py b/pythonforandroid/recipes/tflite-runtime/__init__.py index 1d208866c2..436bb26f41 100644 --- a/pythonforandroid/recipes/tflite-runtime/__init__.py +++ b/pythonforandroid/recipes/tflite-runtime/__init__.py @@ -1,7 +1,7 @@ from pythonforandroid.recipe import PythonRecipe, current_directory, \ shprint, info_main, warning from pythonforandroid.logger import error -from os.path import join +from os.path import exists, join import sh @@ -61,7 +61,10 @@ def build_arch(self, arch): pybind11_recipe = self.get_recipe('pybind11', self.ctx) pybind11_include_dir = pybind11_recipe.get_include_dir(arch) numpy_include_dir = join(self.ctx.get_site_packages_dir(arch), - 'numpy', 'core', 'include') + 'numpy', '_core', 'include') + if not exists(numpy_include_dir): + numpy_include_dir = join(self.ctx.get_site_packages_dir(arch), + 'numpy', 'core', 'include') includes = ' -I' + python_include_dir + \ ' -I' + numpy_include_dir + \ ' -I' + pybind11_include_dir From 72f79003460710bcbab158f04a5fde59ca36a80a Mon Sep 17 00:00:00 2001 From: lanmao Date: Thu, 30 Apr 2026 09:29:11 +0800 Subject: [PATCH 21/82] Fix Meson pybind11 wrapper for SciPy --- pythonforandroid/recipes/scipy/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pythonforandroid/recipes/scipy/__init__.py b/pythonforandroid/recipes/scipy/__init__.py index 4406b354a7..d3157347f3 100644 --- a/pythonforandroid/recipes/scipy/__init__.py +++ b/pythonforandroid/recipes/scipy/__init__.py @@ -12,7 +12,11 @@ class ScipyRecipe(MesonRecipe): depends = ["numpy", "libopenblas", "fortran"] need_stl_shared = True meson_version = "1.5.0" - hostpython_prerequisites = ["numpy", "Cython>=3.0.8"] + hostpython_prerequisites = [ + "numpy", + "Cython>=3.0.8", + "pybind11>=2.13.2,<3.1.0", + ] patches = ["meson.patch"] def get_recipe_meson_options(self, arch): From fa3a269916c0191780ecb0dbee111b49dd412bfc Mon Sep 17 00:00:00 2001 From: lanmao Date: Mon, 27 Apr 2026 17:29:15 +0800 Subject: [PATCH 22/82] Fix pyjnius linking with Qt bootstrap libmain --- pythonforandroid/recipes/pyjnius/__init__.py | 24 ++++++++++++++----- .../genericndkbuild_jnienv_getter.patch | 2 +- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/pythonforandroid/recipes/pyjnius/__init__.py b/pythonforandroid/recipes/pyjnius/__init__.py index 86d8803f18..4d55d3434f 100644 --- a/pythonforandroid/recipes/pyjnius/__init__.py +++ b/pythonforandroid/recipes/pyjnius/__init__.py @@ -2,7 +2,7 @@ from pythonforandroid.toolchain import shprint, current_directory, info from pythonforandroid.patching import will_build import sh -from os.path import join +from os.path import exists, join class PyjniusRecipe(PyProjectRecipe): @@ -21,12 +21,24 @@ class PyjniusRecipe(PyProjectRecipe): def get_recipe_env(self, arch, **kwargs): env = super().get_recipe_env(arch, **kwargs) + generic_main_libs = ( + join(self.ctx.bootstrap.build_dir, 'libs', arch.arch, + 'libmain_{}.so'.format(arch.arch)), + join(self.ctx.bootstrap.build_dir, 'obj', 'local', arch.arch, + 'libmain_{}.so'.format(arch.arch)), + ) + if any(exists(lib) for lib in generic_main_libs): + env['PYJNIUS_ANDROID_LIBMAIN'] = 'main_{}'.format(arch.arch) + # Taken from CythonRecipe - env['LDFLAGS'] = env['LDFLAGS'] + ' -L{} '.format( - self.ctx.get_libs_dir(arch.arch) + - ' -L{} '.format(self.ctx.libs_dir) + - ' -L{}'.format(join(self.ctx.bootstrap.build_dir, 'obj', 'local', - arch.arch))) + env['LDFLAGS'] = env['LDFLAGS'] + ' ' + ' '.join([ + '-L{}'.format(self.ctx.get_libs_dir(arch.arch)), + '-L{}'.format(self.ctx.libs_dir), + '-L{}'.format(join(self.ctx.bootstrap.build_dir, 'libs', + arch.arch)), + '-L{}'.format(join(self.ctx.bootstrap.build_dir, 'obj', 'local', + arch.arch)), + ]) env['LDSHARED'] = env['CC'] + ' -shared' env['LIBLINK'] = 'NOTNONE' diff --git a/pythonforandroid/recipes/pyjnius/genericndkbuild_jnienv_getter.patch b/pythonforandroid/recipes/pyjnius/genericndkbuild_jnienv_getter.patch index fcd5387110..fdf3f42812 100644 --- a/pythonforandroid/recipes/pyjnius/genericndkbuild_jnienv_getter.patch +++ b/pythonforandroid/recipes/pyjnius/genericndkbuild_jnienv_getter.patch @@ -6,7 +6,7 @@ diff -Naur pyjnius.orig/jnius/env.py pyjnius/jnius/env.py class AndroidJavaLocation(UnixJavaLocation): def get_libraries(self): - return ['SDL2', 'log'] -+ return ['main', 'log'] ++ return [getenv('PYJNIUS_ANDROID_LIBMAIN', 'main'), 'log'] def get_include_dirs(self): # When cross-compiling for Android, we should not use the include dirs From 1b0066c3193a649b19605179a9ad9fb44b34193a Mon Sep 17 00:00:00 2001 From: lanmao Date: Fri, 1 May 2026 11:55:30 +0800 Subject: [PATCH 23/82] Avoid rebuilding pybind11 for tflite-runtime --- pythonforandroid/recipes/tflite-runtime/__init__.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pythonforandroid/recipes/tflite-runtime/__init__.py b/pythonforandroid/recipes/tflite-runtime/__init__.py index 436bb26f41..456ba28761 100644 --- a/pythonforandroid/recipes/tflite-runtime/__init__.py +++ b/pythonforandroid/recipes/tflite-runtime/__init__.py @@ -25,7 +25,8 @@ class TFLiteRuntimeRecipe(PythonRecipe): version = '2.8.0' url = 'https://github.com/tensorflow/tensorflow/archive/refs/tags/v{version}.zip' - depends = ['pybind11', 'numpy'] + depends = ['numpy'] + hostpython_prerequisites = ['pybind11==2.11.1'] patches = ['CMakeLists.patch', 'build_with_cmake.patch'] site_packages_name = 'tflite-runtime' call_hostpython_via_targetpython = False @@ -49,6 +50,7 @@ def build_arch(self, arch): return env = self.get_recipe_env(arch) + self.install_hostpython_prerequisites() # Directories root_dir = self.get_build_dir(arch.arch) @@ -58,8 +60,9 @@ def build_arch(self, arch): # Includes python_include_dir = self.ctx.python_recipe.include_root(arch.arch) - pybind11_recipe = self.get_recipe('pybind11', self.ctx) - pybind11_include_dir = pybind11_recipe.get_include_dir(arch) + pybind11_include_dir = sh.Command(self.real_hostpython_location)( + '-c', 'import pybind11; print(pybind11.get_include())' + ).strip() numpy_include_dir = join(self.ctx.get_site_packages_dir(arch), 'numpy', '_core', 'include') if not exists(numpy_include_dir): From e58f7336cd72d067ec933e51d7c5e3574abcaf3a Mon Sep 17 00:00:00 2001 From: lanmao Date: Fri, 1 May 2026 12:17:13 +0800 Subject: [PATCH 24/82] Fix tflite-runtime build with CMake 4 --- .../recipes/tflite-runtime/build_with_cmake.patch | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pythonforandroid/recipes/tflite-runtime/build_with_cmake.patch b/pythonforandroid/recipes/tflite-runtime/build_with_cmake.patch index 9670e1865f..e2678bef3d 100644 --- a/pythonforandroid/recipes/tflite-runtime/build_with_cmake.patch +++ b/pythonforandroid/recipes/tflite-runtime/build_with_cmake.patch @@ -18,7 +18,7 @@ # Build python interpreter_wrapper. mkdir -p "${BUILD_DIR}/cmake_build" -@@ -111,6 +111,18 @@ +@@ -111,6 +111,19 @@ -DCMAKE_CXX_FLAGS="${BUILD_FLAGS}" \ "${TENSORFLOW_LITE_DIR}" ;; @@ -29,6 +29,7 @@ + -DANDROID_ARM_NEON=ON \ + -DCMAKE_CXX_FLAGS="${BUILD_FLAGS}" \ + -DCMAKE_SHARED_LINKER_FLAGS="${CMAKE_SHARED_LINKER_FLAGS}" \ ++ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ + -DCMAKE_TOOLCHAIN_FILE="${CMAKE_TOOLCHAIN_FILE}" \ + -DANDROID_PLATFORM="${ANDROID_PLATFORM}" \ + -DANDROID_ABI="${ANDROID_ABI}" \ @@ -37,7 +38,7 @@ *) BUILD_FLAGS=${BUILD_FLAGS:-"-I${PYTHON_INCLUDE} -I${PYBIND11_INCLUDE}"} cmake \ -@@ -162,7 +174,7 @@ +@@ -162,7 +175,7 @@ ${PYTHON} setup.py bdist --plat-name=${WHEEL_PLATFORM_NAME} \ bdist_wheel --plat-name=${WHEEL_PLATFORM_NAME} else From 375c20d2d1e1a7acbb39c7fe637138924eecd454 Mon Sep 17 00:00:00 2001 From: lanmao Date: Fri, 1 May 2026 12:41:53 +0800 Subject: [PATCH 25/82] Propagate CMake policy minimum to tflite dependencies --- pythonforandroid/recipes/tflite-runtime/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pythonforandroid/recipes/tflite-runtime/__init__.py b/pythonforandroid/recipes/tflite-runtime/__init__.py index 456ba28761..952782dfb9 100644 --- a/pythonforandroid/recipes/tflite-runtime/__init__.py +++ b/pythonforandroid/recipes/tflite-runtime/__init__.py @@ -87,6 +87,7 @@ def build_arch(self, arch): 'ANDROID_ABI': arch.arch, 'WRAPPER_INCLUDES': includes, 'CMAKE_SHARED_LINKER_FLAGS': env['LDFLAGS'], + 'CMAKE_POLICY_VERSION_MINIMUM': '3.5', }) try: From 5b2a4bad793ba20f3016c41f58a1d59d989514a6 Mon Sep 17 00:00:00 2001 From: Kartavya Shukla <87070473+Novfensec@users.noreply.github.com> Date: Sun, 3 May 2026 13:47:00 +0530 Subject: [PATCH 26/82] Add VideoNativeRecipe --- .../recipes/videonative/__init__.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 pythonforandroid/recipes/videonative/__init__.py diff --git a/pythonforandroid/recipes/videonative/__init__.py b/pythonforandroid/recipes/videonative/__init__.py new file mode 100644 index 0000000000..be774dfe46 --- /dev/null +++ b/pythonforandroid/recipes/videonative/__init__.py @@ -0,0 +1,47 @@ +from pythonforandroid.recipe import PyProjectRecipe +from os.path import join + + +class VideoNativeRecipe(PyProjectRecipe): + version = "1.0.0" + url = "https://github.com/Novfensec/VideoNative/archive/{version}.zip" + name = "videonative" + site_packages_name = "videonative" + + hostpython_prerequisites = ["scikit-build-core", "pybind11", "cmake", "ninja"] + depends = ["python3", "ffmpeg", "numpy"] + + def get_recipe_env(self, arch, **kwargs): + env = super().get_recipe_env(arch, **kwargs) + + ffmpeg_recipe = self.get_recipe("ffmpeg", self.ctx) + ffmpeg_build_dir = ffmpeg_recipe.get_build_dir(arch.arch) + + python_recipe = self.get_recipe("python3", self.ctx) + py_include_dir = python_recipe.include_root(arch.arch) + py_lib_file = join( + python_recipe.get_build_dir(arch.arch), + "android-build", + f"libpython{python_recipe.major_minor_version_string}.so", + ) + + toolchain_file = join( + self.ctx.ndk_dir, "build", "cmake", "android.toolchain.cmake" + ) + + env["SKBUILD_STRICT_CONFIG"] = "false" + env["SKBUILD_CMAKE_ARGS"] = ( + f"-DCMAKE_TOOLCHAIN_FILE={toolchain_file};" + f"-DANDROID_ABI={arch.arch};" + f"-DANDROID_PLATFORM=android-{self.ctx.ndk_api};" + f"-DANDROID_FFMPEG_INCLUDE={join(ffmpeg_build_dir, 'include')};" + f"-DANDROID_FFMPEG_LIB={join(ffmpeg_build_dir, 'lib')};" + f"-DPython_EXECUTABLE={self.ctx.hostpython};" + f"-DPython_INCLUDE_DIR={py_include_dir};" + f"-DPython_LIBRARY={py_lib_file};" + ) + + return env + + +recipe = VideoNativeRecipe() From 150faf765f21baa8b5e9e36191017d71cccc1748 Mon Sep 17 00:00:00 2001 From: lanmao Date: Wed, 6 May 2026 15:06:37 +0800 Subject: [PATCH 27/82] Add Vosk recipe --- pythonforandroid/recipes/vosk/__init__.py | 102 ++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 pythonforandroid/recipes/vosk/__init__.py diff --git a/pythonforandroid/recipes/vosk/__init__.py b/pythonforandroid/recipes/vosk/__init__.py new file mode 100644 index 0000000000..b677e09753 --- /dev/null +++ b/pythonforandroid/recipes/vosk/__init__.py @@ -0,0 +1,102 @@ +from os.path import basename, dirname, exists, join +import zipfile + +from pythonforandroid.logger import info +from pythonforandroid.recipe import PythonRecipe, current_directory, shprint +from pythonforandroid.util import BuildInterruptingException, ensure_dir + + +class VoskRecipe(PythonRecipe): + version = "0.3.45" + url = "https://github.com/alphacep/vosk-api/archive/refs/tags/v{version}.tar.gz" + site_packages_name = "vosk" + depends = ["cffi"] + python_depends = ["requests", "tqdm", "srt", "websockets"] + hostpython_prerequisites = [ + "setuptools", + "wheel", + "cffi", + "requests", + "tqdm", + "srt", + "websockets", + ] + call_hostpython_via_targetpython = False + + android_aar_url = ( + "https://repo.maven.apache.org/maven2/com/alphacephei/" + "vosk-android/{version}/vosk-android-{version}.aar" + ) + android_aar_abis = { + "arm64-v8a": "arm64-v8a", + "armeabi-v7a": "armeabi-v7a", + "x86": "x86", + "x86_64": "x86_64", + } + + def build_arch(self, arch): + self.install_hostpython_prerequisites() + + env = self.get_recipe_env(arch) + python_dir = join(self.get_build_dir(arch.arch), "python") + install_dir = self.ctx.get_python_install_dir(arch.arch) + + info("Installing Vosk Python bindings into site-packages") + with current_directory(python_dir): + shprint( + self._host_recipe.pip, + "install", + ".", + "--compile", + "--no-deps", + "--target", + install_dir, + _env=env, + ) + + self.install_android_libvosk(arch) + + def install_android_libvosk(self, arch): + aar_abi = self.android_aar_abis.get(arch.arch) + if aar_abi is None: + supported = ", ".join(sorted(self.android_aar_abis)) + raise BuildInterruptingException( + f"Vosk does not provide an Android library for {arch.arch}. " + f"Supported ABIs: {supported}" + ) + + aar_path = self.download_android_aar() + aar_lib_path = f"jni/{aar_abi}/libvosk.so" + target_path = join( + self.ctx.get_python_install_dir(arch.arch), + self.site_packages_name, + "libvosk.so", + ) + ensure_dir(dirname(target_path)) + + info(f"Installing Android {arch.arch} libvosk.so") + try: + with zipfile.ZipFile(aar_path) as aar: + with aar.open(aar_lib_path) as source, open(target_path, "wb") as target: + target.write(source.read()) + except KeyError as exc: + raise BuildInterruptingException( + f"{basename(aar_path)} does not contain {aar_lib_path}" + ) from exc + + def download_android_aar(self): + aar_dir = join(self.ctx.packages_path, "vosk-android") + ensure_dir(aar_dir) + + aar_name = f"vosk-android-{self.version}.aar" + aar_path = join(aar_dir, aar_name) + if not exists(aar_path): + self.download_file( + self.android_aar_url.format(version=self.version), + aar_name, + cwd=aar_dir, + ) + return aar_path + + +recipe = VoskRecipe() From cccf8f25573afaeca64e2217bf4f328befe34be3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 May 2026 19:38:46 +0000 Subject: [PATCH 28/82] Bump the github-actions group with 8 updates Bumps the github-actions group with 8 updates: | Package | From | To | | --- | --- | --- | | [actions/checkout](https://github.com/actions/checkout) | `4` | `6` | | [actions/upload-artifact](https://github.com/actions/upload-artifact) | `4` | `7` | | [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `3` | `4` | | [actions/setup-python](https://github.com/actions/setup-python) | `5` | `6` | | [actions/setup-java](https://github.com/actions/setup-java) | `4` | `5` | | [gradle/actions](https://github.com/gradle/actions) | `4` | `6` | | [actions/download-artifact](https://github.com/actions/download-artifact) | `5` | `8` | | [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` | Updates `actions/checkout` from 4 to 6 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v6) Updates `actions/upload-artifact` from 4 to 7 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v4...v7) Updates `docker/setup-buildx-action` from 3 to 4 - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/v3...v4) Updates `actions/setup-python` from 5 to 6 - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v5...v6) Updates `actions/setup-java` from 4 to 5 - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v4...v5) Updates `gradle/actions` from 4 to 6 - [Release notes](https://github.com/gradle/actions/releases) - [Commits](https://github.com/gradle/actions/compare/v4...v6) Updates `actions/download-artifact` from 5 to 8 - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v5...v8) Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0 - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.13.0...v1.14.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: docker/setup-buildx-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/setup-python dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/setup-java dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: gradle/actions dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/download-artifact dependency-version: '8' dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: pypa/gh-action-pypi-publish dependency-version: 1.14.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/custom-build.yml | 4 ++-- .github/workflows/docker.yml | 4 ++-- .github/workflows/push.yml | 28 ++++++++++++++-------------- .github/workflows/pypi-release.yml | 6 +++--- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/custom-build.yml b/.github/workflows/custom-build.yml index 8cc381a29e..e69035a82d 100644 --- a/.github/workflows/custom-build.yml +++ b/.github/workflows/custom-build.yml @@ -60,7 +60,7 @@ jobs: runs-on: ${{ github.event.inputs.os }} steps: - name: Checkout python-for-android - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Pull the python-for-android docker image run: make docker/pull - name: Build python-for-android docker image @@ -85,7 +85,7 @@ jobs: if [ -f dist/${{ env.AAB_ARTIFACT_FILENAME }} ]; then mv dist/${{ env.AAB_ARTIFACT_FILENAME }} dist/${{ github.event.inputs.os }}-${{ github.event.inputs.bootstrap }}-${{ env.AAB_ARTIFACT_FILENAME }}; fi if [ -f dist/${{ env.AAR_ARTIFACT_FILENAME }} ]; then mv dist/${{ env.AAR_ARTIFACT_FILENAME }} dist/${{ github.event.inputs.os }}-${{ github.event.inputs.bootstrap }}-${{ env.AAR_ARTIFACT_FILENAME }}; fi - name: Upload artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ github.event.inputs.os }}-${{ github.event.inputs.bootstrap }}-artifacts path: dist diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 903737eff9..6434a9ad3e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -13,8 +13,8 @@ jobs: docker: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: docker/setup-buildx-action@v3 + - uses: actions/checkout@v6 + - uses: docker/setup-buildx-action@v4 - run: make docker/build - name: docker login if: github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/tags/') diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 041a762589..c0bb2db3d2 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout python-for-android - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Set up Python 3.x uses: actions/setup-python@v6 with: @@ -35,14 +35,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout python-for-android - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Set up Java 17 - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'temurin' java-version: '17' - name: Set up Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v6 - name: Run Spotless check working-directory: pythonforandroid/bootstraps run: ./common/build/gradlew spotlessCheck @@ -58,7 +58,7 @@ jobs: os: [ubuntu-latest, macos-latest] steps: - name: Checkout python-for-android - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v6 with: @@ -106,7 +106,7 @@ jobs: remove-codeql: 'true' remove-docker-images: 'true' - name: Checkout python-for-android - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Relocate Docker data directory run: | sudo systemctl stop docker @@ -137,7 +137,7 @@ jobs: if [ -f dist/${{ env.AAB_ARTIFACT_FILENAME }} ]; then mv dist/${{ env.AAB_ARTIFACT_FILENAME }} dist/${{ matrix.runs_on }}-${{ matrix.bootstrap.name }}-${{ env.AAB_ARTIFACT_FILENAME }}; fi if [ -f dist/${{ env.AAR_ARTIFACT_FILENAME }} ]; then mv dist/${{ env.AAR_ARTIFACT_FILENAME }} dist/${{ matrix.runs_on }}-${{ matrix.bootstrap.name }}-${{ env.AAR_ARTIFACT_FILENAME }}; fi - name: Upload artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ matrix.runs_on }}-${{ matrix.bootstrap.name }}-artifacts path: dist @@ -163,7 +163,7 @@ jobs: ANDROID_NDK_HOME: ${HOME}/.android/android-ndk steps: - name: Checkout python-for-android - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Set up Python 3.x uses: actions/setup-python@v6 with: @@ -191,7 +191,7 @@ jobs: if [ -f dist/${{ env.APK_ARTIFACT_FILENAME }} ]; then mv dist/${{ env.APK_ARTIFACT_FILENAME }} dist/${{ matrix.runs_on }}-${{ matrix.bootstrap.name }}-${{ env.APK_ARTIFACT_FILENAME }}; fi if [ -f dist/${{ env.AAB_ARTIFACT_FILENAME }} ]; then mv dist/${{ env.AAB_ARTIFACT_FILENAME }} dist/${{ matrix.runs_on }}-${{ matrix.bootstrap.name }}-${{ env.AAB_ARTIFACT_FILENAME }}; fi - name: Upload artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ matrix.runs_on }}-${{ matrix.bootstrap.name }}-artifacts path: dist @@ -202,9 +202,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Download Artifacts - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v8 with: name: ubuntu-latest-sdl2-artifacts path: dist/ @@ -239,7 +239,7 @@ jobs: remove-codeql: 'true' remove-docker-images: 'true' - name: Checkout python-for-android (all-history) - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 - name: Relocate Docker data directory @@ -276,7 +276,7 @@ jobs: REBUILD_UPDATED_RECIPES_EXTRA_ARGS: --arch=${{ matrix.android_arch }} steps: - name: Checkout python-for-android (all-history) - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 - name: Set up Python 3.x @@ -308,7 +308,7 @@ jobs: documentation: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Requirements run: | python -m pip install --upgrade pip diff --git a/.github/workflows/pypi-release.yml b/.github/workflows/pypi-release.yml index 7f06df83c2..5e48a154bb 100644 --- a/.github/workflows/pypi-release.yml +++ b/.github/workflows/pypi-release.yml @@ -5,9 +5,9 @@ jobs: pypi_release: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Python 3.x - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.x' - name: Install dependencies @@ -19,7 +19,7 @@ jobs: twine check dist/* - name: Publish package if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') - uses: pypa/gh-action-pypi-publish@v1.13.0 + uses: pypa/gh-action-pypi-publish@v1.14.0 with: user: __token__ password: ${{ secrets.pypi_password }} From 02ff950f31407654e859e82f838e9a3dce651b47 Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Fri, 8 May 2026 13:50:35 +0200 Subject: [PATCH 29/82] added msgspec recipe --- pythonforandroid/recipes/msgspec/__init__.py | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 pythonforandroid/recipes/msgspec/__init__.py diff --git a/pythonforandroid/recipes/msgspec/__init__.py b/pythonforandroid/recipes/msgspec/__init__.py new file mode 100644 index 0000000000..7ec2b8442a --- /dev/null +++ b/pythonforandroid/recipes/msgspec/__init__.py @@ -0,0 +1,21 @@ +from typing import Any + +from pythonforandroid.archs import Arch +from pythonforandroid.recipe import PyProjectRecipe + + +class MsgspecRecipe(PyProjectRecipe): + url = 'https://github.com/jcrist/msgspec/archive/refs/tags/{version}.tar.gz' + depends = ['python3', 'setuptools'] + site_packages_name = 'msgspec' + name = 'msgspec' + version = '0.21.1' + + def get_recipe_env(self, arch: Arch, **kwargs) -> dict[str, Any]: + env: dict[str, Any] = super().get_recipe_env(arch, **kwargs) + env['SETUPTOOLS_SCM_PRETEND_VERSION_FOR_MSGSPEC'] = self.version + + return env + + +recipe = MsgspecRecipe() From ccf59d25d76debb0bd3380a6573a2cb285154d33 Mon Sep 17 00:00:00 2001 From: DreamNik Date: Sat, 9 May 2026 22:52:42 +0300 Subject: [PATCH 30/82] Fix numpy compilation when Python != 3.14 --- pythonforandroid/meson_python.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pythonforandroid/meson_python.py b/pythonforandroid/meson_python.py index cd3ed9d508..4c0b7005bb 100644 --- a/pythonforandroid/meson_python.py +++ b/pythonforandroid/meson_python.py @@ -18,7 +18,7 @@ def handle_python_info(): prefix = C.TARGET_PYTHON_PREFIX - sysconfig_file = glob(join(prefix, "lib/python3.14/_sysconfigdata*.py"))[0] + sysconfig_file = glob(join(prefix, f"lib/python{C.PYTHON_MAJOR_VERSION}.{C.PYTHON_MINOR_VERSION}/_sysconfigdata*.py"))[0] spec = importlib.util.spec_from_file_location("_android_cfg", sysconfig_file) cfg = importlib.util.module_from_spec(spec) From 9150fab8376fa0a7ab06cef22d27c23bc74b016c Mon Sep 17 00:00:00 2001 From: DreamNik Date: Sun, 10 May 2026 00:21:46 +0300 Subject: [PATCH 31/82] Fix hostpython dependencies not installed for CythonRecipe --- pythonforandroid/recipe.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pythonforandroid/recipe.py b/pythonforandroid/recipe.py index 55db2bc194..7450e09910 100644 --- a/pythonforandroid/recipe.py +++ b/pythonforandroid/recipe.py @@ -1133,6 +1133,7 @@ def build_arch(self, arch): '''Build any cython components, then install the Python module by calling pip install with the target Python dir. ''' + self.install_hostpython_prerequisites() Recipe.build_arch(self, arch) self.build_cython_components(arch) self.install_python_package(arch) From 2188782a094ce98f3ce76a8656b7b1363815d4ba Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Sat, 9 May 2026 21:34:22 +0000 Subject: [PATCH 32/82] :white_check_mark: tests: drop stale setuptools assertion setuptools was added to setup.py install_reqs in #3007 (May 2024), so it now appears as a direct (non-recursive) dependency. The assertion at test_pythonpackage.py:46 ("setuptools not in deps_nonrecursive") has been wrong since then but went unnoticed because the file is skipped in CI (`make test` uses `--ignore tests/test_pythonpackage.py`). The remaining `include_build_requirements=True` assertion still exercises the build-deps code path. Note this test is skipped by the CI but was ran manually upon during pre-release checks. This can be reproduced via: ``` pytest tests/test_pythonpackage.py::test_get_package_dependencies ``` The error was: ```` > assert "setuptools" not in deps_nonrecursive E AssertionError: assert 'setuptools' not in {'appdirs', 'build', 'colorama>=0.3.3', 'jinja2', 'meson', 'ninja', ...} ``` --- tests/test_pythonpackage.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/test_pythonpackage.py b/tests/test_pythonpackage.py index 21412e9258..ca94c89518 100644 --- a/tests/test_pythonpackage.py +++ b/tests/test_pythonpackage.py @@ -41,11 +41,8 @@ def test_get_package_dependencies(): dep for dep in deps_recursive if "MarkupSafe" in dep ] - # Check setuptools not being in non-recursive deps: - # (It will be in recursive ones due to p4a's build dependency) - assert "setuptools" not in deps_nonrecursive - # Check setuptools is present in non-recursive deps, - # if we also add build requirements: + # Check setuptools is present in non-recursive deps when we add + # build requirements: assert "setuptools" in get_package_dependencies( local_repo_folder(), recursive=False, include_build_requirements=True, From 7f3d872d0c2420d54e65eca3383c67eb1bf4334f Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Sat, 9 May 2026 21:34:55 +0000 Subject: [PATCH 33/82] :bug: Fix msgspec recipe import on Python 3.8/3.9 The msgspec recipe added in #3316 uses PEP 585 generic syntax (dict[str, Any]) in function signatures. Python 3.8 raises "TypeError: 'type' object is not subscriptable" at import time because dict only became subscriptable at runtime in Python 3.9. Adding `from __future__ import annotations` defers annotation evaluation to strings (PEP 563), restoring 3.8 compatibility. This release still officially supports Python 3.8 / 3.9. --- pythonforandroid/recipes/msgspec/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pythonforandroid/recipes/msgspec/__init__.py b/pythonforandroid/recipes/msgspec/__init__.py index 7ec2b8442a..87b24cd5f1 100644 --- a/pythonforandroid/recipes/msgspec/__init__.py +++ b/pythonforandroid/recipes/msgspec/__init__.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Any from pythonforandroid.archs import Arch From 0d1977c40e4cd43b31b003128cbb48ab1bcaf8eb Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Sat, 9 May 2026 20:26:47 +0000 Subject: [PATCH 34/82] Prepare release 2026.05.09 - Bump __version__ to 2026.05.09 and regenerate CHANGELOG.md. - Add Python 3.12 / 3.13 / 3.14 classifiers in setup.py to match the CI test matrix. Last release with 3.8 / 3.9 classifiers. - Replace the stale .travis.yml link in CONTRIBUTING.md with the actual release workflow at .github/workflows/pypi-release.yml. --- CHANGELOG.md | 999 ++++++++++++++++++++++++++++++----- CONTRIBUTING.md | 2 +- pythonforandroid/__init__.py | 2 +- setup.py | 3 + 4 files changed, 881 insertions(+), 125 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60f3137ae3..2ca47716b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,345 @@ # Changelog -## [v2024.01.21](https://github.com/kivy/python-for-android/tree/v2024.01.21) +## [v2026.05.09](https://github.com/kivy/python-for-android/tree/v2026.05.09) (2026-05-09) + +[Full Changelog](https://github.com/kivy/python-for-android/compare/v2024.01.21...v2026.05.09) + +**Fixed bugs:** + +- script.py without "\(" print command [\#3068](https://github.com/kivy/python-for-android/issues/3068) +- Mock assertion issue with ICU recipe under Python 3.12 [\#3002](https://github.com/kivy/python-for-android/issues/3002) +- sympy recipe build fail [\#2820](https://github.com/kivy/python-for-android/issues/2820) +- libzmq recipy build fail [\#2811](https://github.com/kivy/python-for-android/issues/2811) +- libmysqlclient recipe build fail [\#2808](https://github.com/kivy/python-for-android/issues/2808) +- greenlet recipe build fail [\#2806](https://github.com/kivy/python-for-android/issues/2806) +- gevent recipe build fail [\#2805](https://github.com/kivy/python-for-android/issues/2805) +- atom recipe build fail [\#2802](https://github.com/kivy/python-for-android/issues/2802) +- dlopen failed: cannot locate symbol "\_ZNSt12length\_errorD1Ev" while loading matplotlib/\_path.so on Android 12 [\#2675](https://github.com/kivy/python-for-android/issues/2675) +- Changing android.arch or android.api does not trigger the appropriate re-build. [\#1917](https://github.com/kivy/python-for-android/issues/1917) +- TypeError: must be str, not bytes [\#1885](https://github.com/kivy/python-for-android/issues/1885) +- PythonActivity.java is calling considerLoadingScreenRemoval too early [\#1884](https://github.com/kivy/python-for-android/issues/1884) +- apk build error: libtinfo.so.5: cannot open shared object file: No such file or directory [\#1858](https://github.com/kivy/python-for-android/issues/1858) +- fix for non standard path for libraries. [\#1261](https://github.com/kivy/python-for-android/issues/1261) + +**Closed issues:** + +- Build my Kivy app [\#3307](https://github.com/kivy/python-for-android/issues/3307) +- x [\#3304](https://github.com/kivy/python-for-android/issues/3304) +- Could not find a version that satisfies the requirement pyjnius==1.7.0 \(from versions: none\) [\#3303](https://github.com/kivy/python-for-android/issues/3303) +- ERROR Backend 'setuptools.build\_meta:\_\_legacy\_\_' is not available. [\#3300](https://github.com/kivy/python-for-android/issues/3300) +- SDL2\_ttf / Harfbuzz build failure with NDK r26b despite local recipes [\#3295](https://github.com/kivy/python-for-android/issues/3295) +- Проблема сборки Pyside6.10.2 [\#3294](https://github.com/kivy/python-for-android/issues/3294) +- Please tag a new release [\#3292](https://github.com/kivy/python-for-android/issues/3292) +- AttributeError: 'str' object has no attribute 'stdout' [\#3291](https://github.com/kivy/python-for-android/issues/3291) +- PySDL3 support [\#3290](https://github.com/kivy/python-for-android/issues/3290) +- `sdl3_image`: add `SUPPORT_SAVE_WEBP` support for Android \(SDL\_image 3.4.0+\) [\#3287](https://github.com/kivy/python-for-android/issues/3287) +- Cannot use python version lower than 3.14 [\#3281](https://github.com/kivy/python-for-android/issues/3281) +- Python 3.14 Android build failures: `_remote_debugging_module` and SDL2 bootstrap \(`pyconfig.h` missing\) [\#3274](https://github.com/kivy/python-for-android/issues/3274) +- WSL buildozer long undeclared name [\#3261](https://github.com/kivy/python-for-android/issues/3261) +- 16kb memory requirement build failure [\#3260](https://github.com/kivy/python-for-android/issues/3260) +- Proposal: Add windowOptOutEdgeToEdgeEnforcement option [\#3245](https://github.com/kivy/python-for-android/issues/3245) +- com.google.android.gms:play-services-ads has added this note for play-services-ads:21.4.0 [\#3240](https://github.com/kivy/python-for-android/issues/3240) +- App window overflows under navigation buttons & notification bar with `API: 35` [\#3239](https://github.com/kivy/python-for-android/issues/3239) +- CFFI android crash pycryptodomex [\#3238](https://github.com/kivy/python-for-android/issues/3238) +- ModuleNotFoundError: No module named 'distutils' when building setuptools for arm64-v8a [\#3237](https://github.com/kivy/python-for-android/issues/3237) +- cffi fails to build, setuptools issue [\#3235](https://github.com/kivy/python-for-android/issues/3235) +- CFFI Broken in recent develop updates [\#3228](https://github.com/kivy/python-for-android/issues/3228) +- numpy won't build in P4A develop [\#3226](https://github.com/kivy/python-for-android/issues/3226) +- Matplotlib won't build in P4A develop [\#3225](https://github.com/kivy/python-for-android/issues/3225) +- Pillow recipe is causing errors [\#3219](https://github.com/kivy/python-for-android/issues/3219) +- PyJnius 1.7.0 build fails from p4a develop branch [\#3215](https://github.com/kivy/python-for-android/issues/3215) +- https://github.com/kivy/python-for-android.git + cd python-for-android [\#3214](https://github.com/kivy/python-for-android/issues/3214) +- Cannot import 'scikit\_build\_core.build [\#3205](https://github.com/kivy/python-for-android/issues/3205) +- opencv 4.5.1 build fails with numpy 2.3.0 \(all from current develop branch\) [\#3203](https://github.com/kivy/python-for-android/issues/3203) +- Aidl not found [\#3195](https://github.com/kivy/python-for-android/issues/3195) +- Aidl not found [\#3194](https://github.com/kivy/python-for-android/issues/3194) +- Shahan [\#3190](https://github.com/kivy/python-for-android/issues/3190) +- pybind11 ModuleNotFoundError: No module named 'cmake' [\#3188](https://github.com/kivy/python-for-android/issues/3188) +- Patch is not being applied. [\#3185](https://github.com/kivy/python-for-android/issues/3185) +- twisted verion 20.3.0 does not play well with recent python croptography that was updated in kivy, patches don't work with newer version [\#3184](https://github.com/kivy/python-for-android/issues/3184) +- Mm [\#3176](https://github.com/kivy/python-for-android/issues/3176) +- Numpy recipe [\#3163](https://github.com/kivy/python-for-android/issues/3163) +- Adding Sympy fails [\#3162](https://github.com/kivy/python-for-android/issues/3162) +- Error in debug, install platform, Indexerror. [\#3160](https://github.com/kivy/python-for-android/issues/3160) +- Command failed and i can't find a single reason [\#3159](https://github.com/kivy/python-for-android/issues/3159) +- `android` package is not included by default with bootstrap sdl3. Is this intentional? [\#3155](https://github.com/kivy/python-for-android/issues/3155) +- `queue.Queue` repeats items sometimes [\#3153](https://github.com/kivy/python-for-android/issues/3153) +- numpy build fails for lack of `numpy.math` [\#3150](https://github.com/kivy/python-for-android/issues/3150) +- hostpython can't spawn processes, update fails [\#3145](https://github.com/kivy/python-for-android/issues/3145) +- Kivy app crashes silently while playing video on andriod api level 28 while using ffpyplayer [\#3141](https://github.com/kivy/python-for-android/issues/3141) +- Is there a way to include ffmpeg in an Android app? [\#3137](https://github.com/kivy/python-for-android/issues/3137) +- 2d [\#3134](https://github.com/kivy/python-for-android/issues/3134) +- PyProjectRecipe containing install\_in\_hostpython, does not install in hostpython [\#3123](https://github.com/kivy/python-for-android/issues/3123) +- kiwisolver error ld: error: undefined symbol: main [\#3122](https://github.com/kivy/python-for-android/issues/3122) +- Issue Compiling Matplotlib for Android \(Buildozer\) [\#3120](https://github.com/kivy/python-for-android/issues/3120) +- Kiwisolver build fails, Python.h not found [\#3115](https://github.com/kivy/python-for-android/issues/3115) +- the buildozer always show error [\#3114](https://github.com/kivy/python-for-android/issues/3114) +- Contact us link broken. [\#3109](https://github.com/kivy/python-for-android/issues/3109) +- Operation only allowed in c++ when compiling with Buildozer [\#3107](https://github.com/kivy/python-for-android/issues/3107) +- call p4a recipes get error [\#3105](https://github.com/kivy/python-for-android/issues/3105) +- `Gradlew._path` seems to be a regular string [\#3104](https://github.com/kivy/python-for-android/issues/3104) +- Kivy 2.3.1 now requires filetype package [\#3098](https://github.com/kivy/python-for-android/issues/3098) +- jpeg recipe error - rm cannot remove 'CMakeFiles/': Is a directory [\#3089](https://github.com/kivy/python-for-android/issues/3089) +- RuntimeError: failed to get api PyCell\_Get [\#3060](https://github.com/kivy/python-for-android/issues/3060) +- kiwisolver build fails, and depreciation warning [\#3056](https://github.com/kivy/python-for-android/issues/3056) +- Tiktoken is for EM\_X86\_64 | ImportError: dlopen failed \(\) [\#3050](https://github.com/kivy/python-for-android/issues/3050) +- Build FastAPI app as an Android Service [\#3033](https://github.com/kivy/python-for-android/issues/3033) +- М [\#3032](https://github.com/kivy/python-for-android/issues/3032) +- freetype recipe cannot download [\#3031](https://github.com/kivy/python-for-android/issues/3031) +- pydantic\_core makes all build fails [\#3024](https://github.com/kivy/python-for-android/issues/3024) +- Numpy failing on development branch [\#3021](https://github.com/kivy/python-for-android/issues/3021) +- `ValueError: unsupported hash type blake2s` / `code for hash blake2b was not found.` [\#3020](https://github.com/kivy/python-for-android/issues/3020) +- Upgrade Pillow recipe to a version newer than 8.4.0 [\#3019](https://github.com/kivy/python-for-android/issues/3019) +- Add recipe `pyreqwest_impersonate` [\#3012](https://github.com/kivy/python-for-android/issues/3012) +- error: command '/home/lumina/.buildozer/android/platform/android-ndk-r25b/toolchains/llvm/prebuilt/linux-x86\_64/bin/clang' failed with exit code 1 [\#3009](https://github.com/kivy/python-for-android/issues/3009) +- \#error "LONG\_BIT definition appears wrong for platform \(bad gcc/glibc config?\)." [\#3008](https://github.com/kivy/python-for-android/issues/3008) +- please add uvloop to recipes! [\#2997](https://github.com/kivy/python-for-android/issues/2997) +- ask [\#2996](https://github.com/kivy/python-for-android/issues/2996) +- Questions about Copilot + Open Source Software Hierarchy [\#2992](https://github.com/kivy/python-for-android/issues/2992) +- Didn't find class "org.kivy.android.PythonActivity$PermissionsCallback" [\#2991](https://github.com/kivy/python-for-android/issues/2991) +- push notification for android? need permission ACTION\_APP\_NOTIFICATION\_SETTINGS [\#2989](https://github.com/kivy/python-for-android/issues/2989) +- How to build a pyside6 project into an apk [\#2988](https://github.com/kivy/python-for-android/issues/2988) +- com.android.build.gradle.internal.tasks.CompressAssetsWorkAction: Java heap space [\#2984](https://github.com/kivy/python-for-android/issues/2984) +- buildozer rjnius/jnius.c:196:12: fatal error: 'longintrepr.h' file not found [\#2977](https://github.com/kivy/python-for-android/issues/2977) +- chromaprint recipe [\#2970](https://github.com/kivy/python-for-android/issues/2970) +- p4a psycopg recipe error: expression is not assignable [\#2967](https://github.com/kivy/python-for-android/issues/2967) +- Unable to create flet app [\#2963](https://github.com/kivy/python-for-android/issues/2963) +- How to use multithreading in flask [\#2961](https://github.com/kivy/python-for-android/issues/2961) +- How can I add ```pydantic-core``` recipe [\#2955](https://github.com/kivy/python-for-android/issues/2955) +- Feature Request: Pandas\>=1.3.0. [\#2904](https://github.com/kivy/python-for-android/issues/2904) +- Fix sqlalchemy recipe [\#2882](https://github.com/kivy/python-for-android/issues/2882) +- ERROR: Could not build wheels for pycairo [\#2851](https://github.com/kivy/python-for-android/issues/2851) +- Enhancement request: lapack recipe using OpenBLAS [\#2824](https://github.com/kivy/python-for-android/issues/2824) +- Error compiling Cython file: "config.pxi" and "JNIUS\_PYTHON3" not found [\#2790](https://github.com/kivy/python-for-android/issues/2790) +- Ability to use newer version of pandas [\#2776](https://github.com/kivy/python-for-android/issues/2776) +- building pydantic failed [\#2661](https://github.com/kivy/python-for-android/issues/2661) +- `gradle` and java increase RAM with each build [\#2632](https://github.com/kivy/python-for-android/issues/2632) +- SDL2 built APK not seeming to work [\#2621](https://github.com/kivy/python-for-android/issues/2621) +- my python file closes once it opens after converting to apk [\#2604](https://github.com/kivy/python-for-android/issues/2604) +- Deploying PySide6 application [\#2601](https://github.com/kivy/python-for-android/issues/2601) +- \[Recipe Request\]:Panda3d,Ursina [\#2600](https://github.com/kivy/python-for-android/issues/2600) +- gRPC Recipe Error [\#2498](https://github.com/kivy/python-for-android/issues/2498) +- New dependency "python3-venv" not documentented [\#2315](https://github.com/kivy/python-for-android/issues/2315) +- sympy build failed with buildozer \(target Android\). [\#2303](https://github.com/kivy/python-for-android/issues/2303) +- opencv build failed with buildozer \(target Android\). [\#2302](https://github.com/kivy/python-for-android/issues/2302) +- Failed to make a webview application using flask [\#2271](https://github.com/kivy/python-for-android/issues/2271) +- Possible bug in new P4a opencv contrib build [\#2252](https://github.com/kivy/python-for-android/issues/2252) +- Don't assume that a "pyproject.toml" file is used for building [\#2197](https://github.com/kivy/python-for-android/issues/2197) +- Add libssl as host installation requirement [\#2178](https://github.com/kivy/python-for-android/issues/2178) +- Recipes are always rebuilt if they were not given in lowercase. [\#2062](https://github.com/kivy/python-for-android/issues/2062) +- ImportError: dlopen failed: cannot locate symbol "\_Py\_NoneStruct" referenced by \[...\]/gevent/\_\_hub\_local.so" [\#2037](https://github.com/kivy/python-for-android/issues/2037) +- can't use opencv, "dlopen failed: cannot locate symbol" [\#2026](https://github.com/kivy/python-for-android/issues/2026) +- UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe6 in position 77317: invalid continuation byte [\#2023](https://github.com/kivy/python-for-android/issues/2023) +- Docker image size optimization [\#2012](https://github.com/kivy/python-for-android/issues/2012) +- Scrypt recipe on arm64 crash [\#2007](https://github.com/kivy/python-for-android/issues/2007) +- Can't compile for x86\_64, only x86 [\#2004](https://github.com/kivy/python-for-android/issues/2004) +- Allow adding ContentProviders [\#1964](https://github.com/kivy/python-for-android/issues/1964) +- Discussion: introducing Black code formatter [\#1950](https://github.com/kivy/python-for-android/issues/1950) +- Core dump on loading python3.7 when using futures in requirements [\#1945](https://github.com/kivy/python-for-android/issues/1945) +- Android NFC intent not being “called” [\#1940](https://github.com/kivy/python-for-android/issues/1940) +- \[packaging discussion\] Establishing communication with pip maintainers [\#1932](https://github.com/kivy/python-for-android/issues/1932) +- Allow to reuse existing dist without rebuild [\#1920](https://github.com/kivy/python-for-android/issues/1920) +- What's up with lld? [\#1919](https://github.com/kivy/python-for-android/issues/1919) +- Kivy app crash immediately \(SIGABRT\) [\#1890](https://github.com/kivy/python-for-android/issues/1890) +- existing distribution always rebuilds when requirements has pinned python package version [\#1882](https://github.com/kivy/python-for-android/issues/1882) +- cannot find local recipe [\#1861](https://github.com/kivy/python-for-android/issues/1861) +- gradle "versionCode" overflows [\#1843](https://github.com/kivy/python-for-android/issues/1843) +- Add tests for `p4a create` etc. [\#1811](https://github.com/kivy/python-for-android/issues/1811) +- Missing symbols when using numpy on older android [\#1805](https://github.com/kivy/python-for-android/issues/1805) +- Suggestion: getting rid of some things [\#1782](https://github.com/kivy/python-for-android/issues/1782) +- Importing the multiarray numpy extension module failed. [\#1778](https://github.com/kivy/python-for-android/issues/1778) +- Python3 Numpy fails on np.save\(\) [\#1776](https://github.com/kivy/python-for-android/issues/1776) +- System requirements checks proposal [\#1750](https://github.com/kivy/python-for-android/issues/1750) +- SDL2 bootstrap pulls in SDL2, pulls in SDL\_mixer, which currently compiles with timidity which has artistic license [\#1743](https://github.com/kivy/python-for-android/issues/1743) +- Build continue despites libffi.la compilation failing. [\#1737](https://github.com/kivy/python-for-android/issues/1737) +- Macro redefined warnings from pyjniusjni.c [\#1703](https://github.com/kivy/python-for-android/issues/1703) +- Investigate runtime APK automated CI testing [\#1637](https://github.com/kivy/python-for-android/issues/1637) +- Minor legacy code smell: Context.dist\_dir is a quite different place to Bootstrap.dist\_dir [\#1626](https://github.com/kivy/python-for-android/issues/1626) +- apk create failed when --storage-dir used [\#1611](https://github.com/kivy/python-for-android/issues/1611) +- Issue \#1414 resolution no working. Pinning pyjnius does not fix. [\#1589](https://github.com/kivy/python-for-android/issues/1589) +- Enhancement Request - Custom Java [\#1563](https://github.com/kivy/python-for-android/issues/1563) +- Let user choose how many jobs the build will use [\#1558](https://github.com/kivy/python-for-android/issues/1558) +- Conditional builds skip conflicting dependencies [\#1454](https://github.com/kivy/python-for-android/issues/1454) +- pythonforandroid/bootstraps/sdl2/build/build.py when numerical version computation fails won't provide helpful info, especially no hint for --numeric-version [\#1421](https://github.com/kivy/python-for-android/issues/1421) +- p4a apk --help doesn't list all options, and has no URL / read further / ... link resource for a full list [\#1420](https://github.com/kivy/python-for-android/issues/1420) +- file:// urls in a recipe are not processed correctly [\#1407](https://github.com/kivy/python-for-android/issues/1407) +- Unable to open a zip on Android: zipfile.BadZipfile: File is not a zip file [\#1388](https://github.com/kivy/python-for-android/issues/1388) +- Recipe graph finder can enter an infinite loop if no bootstrap fits the requirements [\#1385](https://github.com/kivy/python-for-android/issues/1385) +- p4a signing doesn't work for python 3 app - my mistake or a bug? [\#1350](https://github.com/kivy/python-for-android/issues/1350) +- Name with apostrophe breaks build [\#1349](https://github.com/kivy/python-for-android/issues/1349) +- Build fails, says I need to configure a larger heap for gradle [\#1327](https://github.com/kivy/python-for-android/issues/1327) +- Android Dropdown and Windows disable multitouch. [\#1300](https://github.com/kivy/python-for-android/issues/1300) +- Check proxy support [\#1181](https://github.com/kivy/python-for-android/issues/1181) +- Including Java sources broke after moving to Gradle [\#1136](https://github.com/kivy/python-for-android/issues/1136) +- Multiple bugs with Android immersive mode, especially after pause/resume [\#1117](https://github.com/kivy/python-for-android/issues/1117) +- Service notification launch intent causes app crash [\#1099](https://github.com/kivy/python-for-android/issues/1099) +- python-for-android fails to write project.properties if the dist name has a space [\#1079](https://github.com/kivy/python-for-android/issues/1079) +- Please fix android.activity.bind\(on\_new\_intent=callback\) [\#1076](https://github.com/kivy/python-for-android/issues/1076) +- SoundLoader not working in a new toolchain service [\#1027](https://github.com/kivy/python-for-android/issues/1027) +- uses-feature tag in AndroidManifest file [\#958](https://github.com/kivy/python-for-android/issues/958) +- Presplash size \(inconsistency\) [\#946](https://github.com/kivy/python-for-android/issues/946) +- Add doc about how to develop on p4a [\#929](https://github.com/kivy/python-for-android/issues/929) +- requirements: need to provide a docs about git+url schema for custom pure python requirements [\#880](https://github.com/kivy/python-for-android/issues/880) +- Documentation improvements: Explicit versions for Ubuntu, JDK, Android [\#867](https://github.com/kivy/python-for-android/issues/867) +- Issues with Explicit Relative Imports [\#840](https://github.com/kivy/python-for-android/issues/840) +- Bug/Feature request: Check paths from arguments first, build then [\#832](https://github.com/kivy/python-for-android/issues/832) +- hostpython should not be a dynamic attribute of Context [\#825](https://github.com/kivy/python-for-android/issues/825) +- Numeric keyboard doesn't work with SDL2 [\#796](https://github.com/kivy/python-for-android/issues/796) +- Window pans after calling activity [\#759](https://github.com/kivy/python-for-android/issues/759) +- Wrong bootstrap export\_dist [\#755](https://github.com/kivy/python-for-android/issues/755) +- Issue with Android example [\#1816](https://github.com/kivy/python-for-android/issues/1816) +- bootstrap recipes are not differentiated by arch [\#598](https://github.com/kivy/python-for-android/issues/598) +- Bootstrap copying creates nested copies [\#593](https://github.com/kivy/python-for-android/issues/593) +- empty bootstrap missing build folder [\#547](https://github.com/kivy/python-for-android/issues/547) +- The argparse structure needs redoing [\#504](https://github.com/kivy/python-for-android/issues/504) +- Additional options for the manifest [\#406](https://github.com/kivy/python-for-android/issues/406) +- Expose Galaxy Note S-Pen touch information [\#353](https://github.com/kivy/python-for-android/issues/353) +- on\_new\_intent not firing at app 'cold' start [\#1672](https://github.com/kivy/python-for-android/issues/1672) +- on\_resume vs on\_new\_intent firing [\#1671](https://github.com/kivy/python-for-android/issues/1671) +- run\_on\_ui\_thread crashes with local reference table overflow when called multiple times [\#164](https://github.com/kivy/python-for-android/issues/164) +- Create a one-time splash screen for initial start-up [\#52](https://github.com/kivy/python-for-android/issues/52) + +**Merged pull requests:** + +- :bug: Fix msgspec recipe import on Python 3.8/3.9 [\#3324](https://github.com/kivy/python-for-android/pull/3324) ([AndreMiras](https://github.com/AndreMiras)) +- :white\_check\_mark: tests: drop stale setuptools assertion [\#3323](https://github.com/kivy/python-for-android/pull/3323) ([AndreMiras](https://github.com/AndreMiras)) +- Fix numpy compilation when Python != 3.14 [\#3319](https://github.com/kivy/python-for-android/pull/3319) ([DreamNik](https://github.com/DreamNik)) +- Added msgspec recipe [\#3316](https://github.com/kivy/python-for-android/pull/3316) ([GvozdevLeonid](https://github.com/GvozdevLeonid)) +- Bump the github-actions group with 8 updates [\#3315](https://github.com/kivy/python-for-android/pull/3315) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Add Vosk recipe [\#3314](https://github.com/kivy/python-for-android/pull/3314) ([lazycat11](https://github.com/lazycat11)) +- Add videonative Recipe [\#3313](https://github.com/kivy/python-for-android/pull/3313) ([Novfensec](https://github.com/Novfensec)) +- Fix SciPy pybind11 build dependency [\#3311](https://github.com/kivy/python-for-android/pull/3311) ([lazycat11](https://github.com/lazycat11)) +- Fix tflite-runtime numpy include path [\#3310](https://github.com/kivy/python-for-android/pull/3310) ([lazycat11](https://github.com/lazycat11)) +- Update SDL3\_mixer recipe to version 3.2.0, remove libgme patch \(not needed as SDL3\_mixer disables it by default\) and fix compilation crash [\#3309](https://github.com/kivy/python-for-android/pull/3309) ([kengoon](https://github.com/kengoon)) +- Fix pyjnius linking with Qt bootstrap libmain [\#3308](https://github.com/kivy/python-for-android/pull/3308) ([lazycat11](https://github.com/lazycat11)) +- fix PYTHONPATH hacks [\#3301](https://github.com/kivy/python-for-android/pull/3301) ([T-Dynamos](https://github.com/T-Dynamos)) +- Update README to include PySDL3 support [\#3297](https://github.com/kivy/python-for-android/pull/3297) ([C0rn3j](https://github.com/C0rn3j)) +- :bug: Fix sdl2/sdl3 bootstrap conflict in CI [\#3284](https://github.com/kivy/python-for-android/pull/3284) ([AndreMiras](https://github.com/AndreMiras)) +- Fixed Python version support. [\#3283](https://github.com/kivy/python-for-android/pull/3283) ([GvozdevLeonid](https://github.com/GvozdevLeonid)) +- :construction\_worker: Relocate Docker storage to LVM volume in CI [\#3282](https://github.com/kivy/python-for-android/pull/3282) ([AndreMiras](https://github.com/AndreMiras)) +- Add support for prebuilt wheels [\#3280](https://github.com/kivy/python-for-android/pull/3280) ([T-Dynamos](https://github.com/T-Dynamos)) +- `ffmpeg`, `python3`: include executable [\#3276](https://github.com/kivy/python-for-android/pull/3276) ([T-Dynamos](https://github.com/T-Dynamos)) +- `toolchain`: auto resolve deps [\#3271](https://github.com/kivy/python-for-android/pull/3271) ([T-Dynamos](https://github.com/T-Dynamos)) +- :memo: Fix documentation linkcheck failures [\#3270](https://github.com/kivy/python-for-android/pull/3270) ([AndreMiras](https://github.com/AndreMiras)) +- :construction\_worker: CI disk cleanup via maximize-build-space [\#3269](https://github.com/kivy/python-for-android/pull/3269) ([AndreMiras](https://github.com/AndreMiras)) +- :construction\_worker: Add Spotless Java linting to CI pipeline [\#3268](https://github.com/kivy/python-for-android/pull/3268) ([AndreMiras](https://github.com/AndreMiras)) +- :recycle: Consolidate GenericBroadcastReceiver to common/ [\#3267](https://github.com/kivy/python-for-android/pull/3267) ([AndreMiras](https://github.com/AndreMiras)) +- :recycle: Consolidate assemble\_distribution\(\) into base Bootstrap [\#3266](https://github.com/kivy/python-for-android/pull/3266) ([AndreMiras](https://github.com/AndreMiras)) +- :construction\_worker: Fix CI disk space issue in ubuntu\_build job [\#3265](https://github.com/kivy/python-for-android/pull/3265) ([AndreMiras](https://github.com/AndreMiras)) +- Add foregroundServiceType support to AndroidManifest templates [\#3262](https://github.com/kivy/python-for-android/pull/3262) ([kengoon](https://github.com/kengoon)) +- Add android.touch module to support touch interception via SDLSurface [\#3259](https://github.com/kivy/python-for-android/pull/3259) ([kengoon](https://github.com/kengoon)) +- Fix `libm` linkage for Pillow recipe builds [\#3256](https://github.com/kivy/python-for-android/pull/3256) ([DexerBR](https://github.com/DexerBR)) +- :white\_check\_mark: Increase test coverage for logger, prerequisites, and pythonpackage [\#3255](https://github.com/kivy/python-for-android/pull/3255) ([AndreMiras](https://github.com/AndreMiras)) +- :white\_check\_mark: Tests for entrypoints, bdistapk, and util modules [\#3254](https://github.com/kivy/python-for-android/pull/3254) ([AndreMiras](https://github.com/AndreMiras)) +- :white\_check\_mark: unit test patching & checkdependencies modules [\#3253](https://github.com/kivy/python-for-android/pull/3253) ([AndreMiras](https://github.com/AndreMiras)) +- `pydantic`: update to 2.41.4 [\#3252](https://github.com/kivy/python-for-android/pull/3252) ([T-Dynamos](https://github.com/T-Dynamos)) +- `materialyoucolor`: shift to `PPR` [\#3251](https://github.com/kivy/python-for-android/pull/3251) ([T-Dynamos](https://github.com/T-Dynamos)) +- remove patchelf dependency [\#3250](https://github.com/kivy/python-for-android/pull/3250) ([T-Dynamos](https://github.com/T-Dynamos)) +- `pycryptodome`: update to 3.23.0 [\#3249](https://github.com/kivy/python-for-android/pull/3249) ([T-Dynamos](https://github.com/T-Dynamos)) +- Update to Python 3.14, remove distutils [\#3242](https://github.com/kivy/python-for-android/pull/3242) ([clayote](https://github.com/clayote)) +- Patch out the `ast.Str` reference in Kivy, for Python 3.14 compatibility [\#3241](https://github.com/kivy/python-for-android/pull/3241) ([clayote](https://github.com/clayote)) +- `cffi`: fix build [\#3233](https://github.com/kivy/python-for-android/pull/3233) ([T-Dynamos](https://github.com/T-Dynamos)) +- `matplotlib`: fix build [\#3230](https://github.com/kivy/python-for-android/pull/3230) ([T-Dynamos](https://github.com/T-Dynamos)) +- `cffi`: fix build [\#3229](https://github.com/kivy/python-for-android/pull/3229) ([T-Dynamos](https://github.com/T-Dynamos)) +- Bump pypa/gh-action-pypi-publish from 1.4.2 to 1.13.0 in /.github/workflows [\#3222](https://github.com/kivy/python-for-android/pull/3222) ([dependabot[bot]](https://github.com/apps/dependabot)) +- :construction\_worker: Runtime test the app from the CI [\#3221](https://github.com/kivy/python-for-android/pull/3221) ([AndreMiras](https://github.com/AndreMiras)) +- `opencv`: fix build [\#3218](https://github.com/kivy/python-for-android/pull/3218) ([T-Dynamos](https://github.com/T-Dynamos)) +- fix plat-name [\#3217](https://github.com/kivy/python-for-android/pull/3217) ([T-Dynamos](https://github.com/T-Dynamos)) +- pynacl-recipe [\#3212](https://github.com/kivy/python-for-android/pull/3212) ([gonatienza](https://github.com/gonatienza)) +- `pillow`: update to `11.3.0` [\#3211](https://github.com/kivy/python-for-android/pull/3211) ([T-Dynamos](https://github.com/T-Dynamos)) +- `pyjnius`: update to 1.7.0 [\#3210](https://github.com/kivy/python-for-android/pull/3210) ([T-Dynamos](https://github.com/T-Dynamos)) +- `kivy`: depend on android [\#3209](https://github.com/kivy/python-for-android/pull/3209) ([T-Dynamos](https://github.com/T-Dynamos)) +- `android`: shift to PPR [\#3208](https://github.com/kivy/python-for-android/pull/3208) ([T-Dynamos](https://github.com/T-Dynamos)) +- `flask`: update to `3.1.1` [\#3207](https://github.com/kivy/python-for-android/pull/3207) ([T-Dynamos](https://github.com/T-Dynamos)) +- Remove redundant sympy recipe [\#3206](https://github.com/kivy/python-for-android/pull/3206) ([Novfensec](https://github.com/Novfensec)) +- Commented out the os.environ so we are seeing less spam [\#3204](https://github.com/kivy/python-for-android/pull/3204) ([kuzeyron](https://github.com/kuzeyron)) +- Bump SDL3 \(`3.4.2`\) and SDL3\_image \(`3.4.0`\) to the latest stable releases; fix `kivy` recipe when based on the `master` branch. [\#3198](https://github.com/kivy/python-for-android/pull/3198) ([DexerBR](https://github.com/DexerBR)) +- Fix `md5sum` for SDL3 recipe version `3.2.18` [\#3183](https://github.com/kivy/python-for-android/pull/3183) ([DexerBR](https://github.com/DexerBR)) +- Bump SDL3 recipe version to the latest stable release \(`3.2.18`\) [\#3182](https://github.com/kivy/python-for-android/pull/3182) ([DexerBR](https://github.com/DexerBR)) +- Require `c++` stl for Kivy when `sdl3` is used \(Kivy 3.0.0\) [\#3181](https://github.com/kivy/python-for-android/pull/3181) ([misl6](https://github.com/misl6)) +- `python`: add `3.14` support [\#3180](https://github.com/kivy/python-for-android/pull/3180) ([T-Dynamos](https://github.com/T-Dynamos)) +- `recipes`: new pycairo recipe [\#3174](https://github.com/kivy/python-for-android/pull/3174) ([T-Dynamos](https://github.com/T-Dynamos)) +- Update Android Gradle Plugin to `8.11.0` and Gradle Wrapper to `8.14.3` + update default API target to `35` in tests [\#3172](https://github.com/kivy/python-for-android/pull/3172) ([FilipeMarch](https://github.com/FilipeMarch)) +- \[Display-Cutout\] Added missing features due to limitations [\#3171](https://github.com/kivy/python-for-android/pull/3171) ([kuzeyron](https://github.com/kuzeyron)) +- \[Display-Cutout\] More tools for the developer + minor changes [\#3170](https://github.com/kivy/python-for-android/pull/3170) ([kuzeyron](https://github.com/kuzeyron)) +- Fix broadcast receiver [\#3168](https://github.com/kivy/python-for-android/pull/3168) ([Novfensec](https://github.com/Novfensec)) +- Update: `numpy`, `pandas`, `sdl2` to newer versions which support `ndk28c` [\#3164](https://github.com/kivy/python-for-android/pull/3164) ([T-Dynamos](https://github.com/T-Dynamos)) +- Patch SDLSurface to allow touch to be intercepted by python application [\#3157](https://github.com/kivy/python-for-android/pull/3157) ([kengoon](https://github.com/kengoon)) +- `pyjnius`: pin cython version [\#3151](https://github.com/kivy/python-for-android/pull/3151) ([T-Dynamos](https://github.com/T-Dynamos)) +- Fix Cmake compatibility issue on jpeg recipe [\#3147](https://github.com/kivy/python-for-android/pull/3147) ([Huyston](https://github.com/Huyston)) +- `kivy` and `pyjnius`: switch to `PyProjectRecipe` [\#3139](https://github.com/kivy/python-for-android/pull/3139) ([T-Dynamos](https://github.com/T-Dynamos)) +- `primp`: update to `0.14.0` [\#3138](https://github.com/kivy/python-for-android/pull/3138) ([T-Dynamos](https://github.com/T-Dynamos)) +- scipy: update to v1.16.2 [\#3136](https://github.com/kivy/python-for-android/pull/3136) ([T-Dynamos](https://github.com/T-Dynamos)) +- `sdl2_image`: fix downloading [\#3135](https://github.com/kivy/python-for-android/pull/3135) ([T-Dynamos](https://github.com/T-Dynamos)) +- :bug: Update the greenlet recipe, closes \#2806 [\#3132](https://github.com/kivy/python-for-android/pull/3132) ([AndreMiras](https://github.com/AndreMiras)) +- :bug: Update and fix atom recipe, closes \#2802 [\#3131](https://github.com/kivy/python-for-android/pull/3131) ([AndreMiras](https://github.com/AndreMiras)) +- :fire: Drop libmysqlclient recipe, closes \#2808 [\#3130](https://github.com/kivy/python-for-android/pull/3130) ([AndreMiras](https://github.com/AndreMiras)) +- :bug: Upgrade and fix gevent recipe, closes \#2805 [\#3129](https://github.com/kivy/python-for-android/pull/3129) ([AndreMiras](https://github.com/AndreMiras)) +- :bug: Fix the kiwisolver build on macOS, fixes \#3122 [\#3128](https://github.com/kivy/python-for-android/pull/3128) ([AndreMiras](https://github.com/AndreMiras)) +- Proxy environment variables passthrough to recipes [\#3126](https://github.com/kivy/python-for-android/pull/3126) ([broccoliboy](https://github.com/broccoliboy)) +- Add `SDL3` bootstrap \(alongside `SDL3`, `SDL3_ttf`, `SDL3_mixer`, `SDL3_image` recipes\) for Kivy `3.0.0` [\#3125](https://github.com/kivy/python-for-android/pull/3125) ([misl6](https://github.com/misl6)) +- :arrow\_up: Migrate to actions/upload-artifact@v4 [\#3119](https://github.com/kivy/python-for-android/pull/3119) ([AndreMiras](https://github.com/AndreMiras)) +- Fix kiwisolver recipe fatal error: 'Python.h' file not found [\#3118](https://github.com/kivy/python-for-android/pull/3118) ([mriscoc](https://github.com/mriscoc)) +- update kivy to 2.3.1 [\#3103](https://github.com/kivy/python-for-android/pull/3103) ([Fak3](https://github.com/Fak3)) +- Add `httpx` recipe [\#3100](https://github.com/kivy/python-for-android/pull/3100) ([DexerBR](https://github.com/DexerBR)) +- kivy recipe: add filetype dependency [\#3099](https://github.com/kivy/python-for-android/pull/3099) ([Fak3](https://github.com/Fak3)) +- Update sdl2\_ttf from 2.20.2 to 2.22.0 [\#3096](https://github.com/kivy/python-for-android/pull/3096) ([Fak3](https://github.com/Fak3)) +- Add hardware acceleration codecs to ffmpeg recipe [\#3092](https://github.com/kivy/python-for-android/pull/3092) ([brentpicasso](https://github.com/brentpicasso)) +- :green\_heart: Fix sphinx documentation build errors [\#3091](https://github.com/kivy/python-for-android/pull/3091) ([AndreMiras](https://github.com/AndreMiras)) +- Fix rm: cannot remove 'CMakeFiles/': Is a directory [\#3090](https://github.com/kivy/python-for-android/pull/3090) ([Fak3](https://github.com/Fak3)) +- Update pyopenssl version [\#3087](https://github.com/kivy/python-for-android/pull/3087) ([rnixx](https://github.com/rnixx)) +- bump openssl to 3 [\#3086](https://github.com/kivy/python-for-android/pull/3086) ([HyTurtle](https://github.com/HyTurtle)) +- Add bitarray recipe [\#3084](https://github.com/kivy/python-for-android/pull/3084) ([Novfensec](https://github.com/Novfensec)) +- Fix typos discovered by codespell [\#3079](https://github.com/kivy/python-for-android/pull/3079) ([cclauss](https://github.com/cclauss)) +- Keep GitHub Actions up to date with GitHub's Dependabot [\#3078](https://github.com/kivy/python-for-android/pull/3078) ([cclauss](https://github.com/cclauss)) +- GitHub Actions: comment out the failing sdl2\_scipy test [\#3077](https://github.com/kivy/python-for-android/pull/3077) ([cclauss](https://github.com/cclauss)) +- GitHub Actions: Add Python 3.12, 3.13, 3.14, and 3.14t to the testing [\#3076](https://github.com/kivy/python-for-android/pull/3076) ([cclauss](https://github.com/cclauss)) +- Add ability to use private github repos for recipes [\#3074](https://github.com/kivy/python-for-android/pull/3074) ([brentpicasso](https://github.com/brentpicasso)) +- :construction\_worker: On-demand CI custom build [\#3073](https://github.com/kivy/python-for-android/pull/3073) ([AndreMiras](https://github.com/AndreMiras)) +- :construction\_worker: Docker workflow fixes [\#3067](https://github.com/kivy/python-for-android/pull/3067) ([AndreMiras](https://github.com/AndreMiras)) +- Bump `FFMpegRecipe` and `PyAVRecipe` versions [\#3065](https://github.com/kivy/python-for-android/pull/3065) ([DexerBR](https://github.com/DexerBR)) +- :recycle: Minor code cleaning [\#3054](https://github.com/kivy/python-for-android/pull/3054) ([AndreMiras](https://github.com/AndreMiras)) +- :bug: Fix rebuild updated recipes [\#3053](https://github.com/kivy/python-for-android/pull/3053) ([AndreMiras](https://github.com/AndreMiras)) +- :construction\_worker: Fix docker login [\#3052](https://github.com/kivy/python-for-android/pull/3052) ([AndreMiras](https://github.com/AndreMiras)) +- Add tiktoken recipe [\#3051](https://github.com/kivy/python-for-android/pull/3051) ([RobertFlatt](https://github.com/RobertFlatt)) +- :arrow\_up: Bump sh module to v2, refs \#2746 [\#3049](https://github.com/kivy/python-for-android/pull/3049) ([AndreMiras](https://github.com/AndreMiras)) +- :mute: Fix sh logs too verbose [\#3048](https://github.com/kivy/python-for-android/pull/3048) ([AndreMiras](https://github.com/AndreMiras)) +- :construction\_worker: Publish to DockerHub [\#3047](https://github.com/kivy/python-for-android/pull/3047) ([AndreMiras](https://github.com/AndreMiras)) +- Fix broken quickstart link [\#3046](https://github.com/kivy/python-for-android/pull/3046) ([zenoengine](https://github.com/zenoengine)) +- Add ModernGL recipe [\#3045](https://github.com/kivy/python-for-android/pull/3045) ([emersonmx](https://github.com/emersonmx)) +- aubio recipe created [\#3044](https://github.com/kivy/python-for-android/pull/3044) ([jithesh82](https://github.com/jithesh82)) +- Grpcio recipe: Fix runtime error, cannot locate symbol "getservbyport\_y" [\#3043](https://github.com/kivy/python-for-android/pull/3043) ([kengoon](https://github.com/kengoon)) +- libsodium-recipe-update to url [\#3042](https://github.com/kivy/python-for-android/pull/3042) ([gonatienza](https://github.com/gonatienza)) +- ✨Fixed wrong spelling: depelopment -\> development [\#3038](https://github.com/kivy/python-for-android/pull/3038) ([ByteJoseph](https://github.com/ByteJoseph)) +- `sqlalchemy`: update to `2.0.30` [\#3027](https://github.com/kivy/python-for-android/pull/3027) ([T-Dynamos](https://github.com/T-Dynamos)) +- `archs.py`: remove backslash logic [\#3026](https://github.com/kivy/python-for-android/pull/3026) ([T-Dynamos](https://github.com/T-Dynamos)) +- `ffpyplayer`: update to `4.5.1` [\#3025](https://github.com/kivy/python-for-android/pull/3025) ([T-Dynamos](https://github.com/T-Dynamos)) +- recipes: add new `grpcio` recipe [\#3023](https://github.com/kivy/python-for-android/pull/3023) ([kengoon](https://github.com/kengoon)) +- pillow: update to `10.3.0` [\#3022](https://github.com/kivy/python-for-android/pull/3022) ([T-Dynamos](https://github.com/T-Dynamos)) +- recipes: add new `pyreqwest_impersonate` recipe [\#3016](https://github.com/kivy/python-for-android/pull/3016) ([T-Dynamos](https://github.com/T-Dynamos)) +- recipes: add new `uvloop` recipe [\#3015](https://github.com/kivy/python-for-android/pull/3015) ([T-Dynamos](https://github.com/T-Dynamos)) +- Sunset `apple-silicon-m1` self-hosted runner, as now is supported by Github Hosted runners via `macos-latest` tag. Use `macos-13` for runs on Intel macs [\#3011](https://github.com/kivy/python-for-android/pull/3011) ([misl6](https://github.com/misl6)) +- recipe: introduce isolated builds, using `PyProjectRecipe` [\#3007](https://github.com/kivy/python-for-android/pull/3007) ([T-Dynamos](https://github.com/T-Dynamos)) +- Fix mock assertion in ICU recipe [\#3003](https://github.com/kivy/python-for-android/pull/3003) ([s-t-e-v-e-n-k](https://github.com/s-t-e-v-e-n-k)) +- \(`recipes/materialyoucolor`\): update to 2.0.9 [\#2994](https://github.com/kivy/python-for-android/pull/2994) ([T-Dynamos](https://github.com/T-Dynamos)) +- Qt Bootstrap - Adapting to Qt 6.7 release [\#2990](https://github.com/kivy/python-for-android/pull/2990) ([shyamnathp](https://github.com/shyamnathp)) +- :white\_check\_mark: Fix broken sdl2 mixer test [\#2987](https://github.com/kivy/python-for-android/pull/2987) ([AndreMiras](https://github.com/AndreMiras)) +- :loud\_sound: Improve rebuild recipes logging & bump `pyzbar` version [\#2986](https://github.com/kivy/python-for-android/pull/2986) ([AndreMiras](https://github.com/AndreMiras)) +- :fire: Remove unused Makefile variables [\#2985](https://github.com/kivy/python-for-android/pull/2985) ([AndreMiras](https://github.com/AndreMiras)) +- MANAGE\_EXTERNAL\_STORAGE [\#2983](https://github.com/kivy/python-for-android/pull/2983) ([cweilouis](https://github.com/cweilouis)) +- :white\_check\_mark: improve sh mocking reliability [\#2980](https://github.com/kivy/python-for-android/pull/2980) ([AndreMiras](https://github.com/AndreMiras)) +- :white\_check\_mark: Fix test\_get\_dep\_names\_of\_package [\#2979](https://github.com/kivy/python-for-android/pull/2979) ([AndreMiras](https://github.com/AndreMiras)) +- Arch type error when creating apk for project with setup.py [\#2978](https://github.com/kivy/python-for-android/pull/2978) ([pramodin](https://github.com/pramodin)) +- \(`recipes/materialyoucolor`\): update to 2.0.7 [\#2975](https://github.com/kivy/python-for-android/pull/2975) ([T-Dynamos](https://github.com/T-Dynamos)) +- Add support for display cutouts in manifest and add methods to retrieve data [\#2969](https://github.com/kivy/python-for-android/pull/2969) ([kuzeyron](https://github.com/kuzeyron)) +- recipes: Introduce `RustCompiledComponentsRecipe`, add `pydantic-core` and update `cryptography` [\#2962](https://github.com/kivy/python-for-android/pull/2962) ([T-Dynamos](https://github.com/T-Dynamos)) +- Merge `master` into `develop` [\#2960](https://github.com/kivy/python-for-android/pull/2960) ([misl6](https://github.com/misl6)) +- recipes: new `materialyoucolor` recipe [\#2950](https://github.com/kivy/python-for-android/pull/2950) ([T-Dynamos](https://github.com/T-Dynamos)) +- libzmq: fix build [\#2842](https://github.com/kivy/python-for-android/pull/2842) ([T-Dynamos](https://github.com/T-Dynamos)) +- recipes: new recipe `coincurve` [\#2835](https://github.com/kivy/python-for-android/pull/2835) ([T-Dynamos](https://github.com/T-Dynamos)) + +## [v2024.01.21](https://github.com/kivy/python-for-android/tree/v2024.01.21) (2024-01-23) [Full Changelog](https://github.com/kivy/python-for-android/compare/v2023.09.16...v2024.01.21) @@ -14,7 +353,7 @@ - unknown argument "fp-model" and strict is not a directory or a file [\#2359](https://github.com/kivy/python-for-android/issues/2359) - Copy past is not working on kivy mobile app [\#2270](https://github.com/kivy/python-for-android/issues/2270) - Flaky test failure in blacklist\(?\) - investigation needed [\#1781](https://github.com/kivy/python-for-android/issues/1781) -- Problem with loading gevent: BadZipfile: File is not a zip file [\#1739](https://github.com/kivy/python-for-android/issues/1739) +- Problem with loding gevent: BadZipfile: File is not a zip file [\#1739](https://github.com/kivy/python-for-android/issues/1739) - ImportError when importing files containing \N{name} escape sequence [\#1060](https://github.com/kivy/python-for-android/issues/1060) - Error with permission specification via setup.cfg [\#985](https://github.com/kivy/python-for-android/issues/985) @@ -30,28 +369,28 @@ - use build aar in kotlin app ,can't load /lib/arm64/libpybundle.so file [\#2940](https://github.com/kivy/python-for-android/issues/2940) - Feature Request: Pymssql [\#2936](https://github.com/kivy/python-for-android/issues/2936) - LXML v4.8.0 fails to build. [\#2928](https://github.com/kivy/python-for-android/issues/2928) -- Trying to apply a plugin fails [\#2926](https://github.com/kivy/python-for-android/issues/2926) +- Tryin to apply a plugin fails [\#2926](https://github.com/kivy/python-for-android/issues/2926) - ModuleNotFoundError: No module named '\_sysconfigdata\_\_darwin\_darwin' [\#2925](https://github.com/kivy/python-for-android/issues/2925) - ReadTheDocs version is unclear. [\#2920](https://github.com/kivy/python-for-android/issues/2920) - How to get real file path from uri [\#2911](https://github.com/kivy/python-for-android/issues/2911) - And [\#2910](https://github.com/kivy/python-for-android/issues/2910) - ModuleNotFoundError: No module named 'backports' [\#2909](https://github.com/kivy/python-for-android/issues/2909) -- not able to access files unless connected to adb once [\#2907](https://github.com/kivy/python-for-android/issues/2907) +- not able to acess files unless connected to adb once [\#2907](https://github.com/kivy/python-for-android/issues/2907) - opening files in other apps [\#2906](https://github.com/kivy/python-for-android/issues/2906) - ImportError: dlopen failed: cannot locate symbol "\_ZTVSt9bad\_alloc" [\#2903](https://github.com/kivy/python-for-android/issues/2903) - Fails to build pyjnius [\#2902](https://github.com/kivy/python-for-android/issues/2902) - Kivy app crashes on startup [\#2895](https://github.com/kivy/python-for-android/issues/2895) - aar file does not import properly in version v2023.09.16 [\#2894](https://github.com/kivy/python-for-android/issues/2894) - App is crashing with Pyrebase4 [\#2893](https://github.com/kivy/python-for-android/issues/2893) -- shared libs builds with 32 bit arch instead of 64 bit [\#2888](https://github.com/kivy/python-for-android/issues/2888) +- shared libs builds with 32 bit arch instaead of 64 bit [\#2888](https://github.com/kivy/python-for-android/issues/2888) - liblzma download error [\#2885](https://github.com/kivy/python-for-android/issues/2885) - Misconfiguration causing failure in compilation. [\#2879](https://github.com/kivy/python-for-android/issues/2879) - cygrpc.so is for EM\_X86\_64 \(62\) instead of EM\_AARCH64 \(183\) [\#2853](https://github.com/kivy/python-for-android/issues/2853) - Are you able to build cffi==1.15.1? [\#2847](https://github.com/kivy/python-for-android/issues/2847) - java.lang.IllegalStateException [\#2844](https://github.com/kivy/python-for-android/issues/2844) - \[BUG\]: ctypes: AttributeError: undefined symbol: PyCapsule\_New [\#2840](https://github.com/kivy/python-for-android/issues/2840) -- kivy can't load image in requesturl android [\#2832](https://github.com/kivy/python-for-android/issues/2832) +- kivy cant load image in requesturl android [\#2832](https://github.com/kivy/python-for-android/issues/2832) - Feature Request: Add Python `3.11` support [\#2798](https://github.com/kivy/python-for-android/issues/2798) - Error Build APK FIle using Flask [\#2783](https://github.com/kivy/python-for-android/issues/2783) - macOS: gwadlew fails at build tools stage \(newest build tools is 34.0.0-rc3, brew/openjdk@20\). [\#2781](https://github.com/kivy/python-for-android/issues/2781) @@ -61,7 +400,7 @@ - Background service implemented using Pyjnius does not auto-restart on Kivy APK close [\#2772](https://github.com/kivy/python-for-android/issues/2772) - \[JVM\]: FLAG\_IMMUTABLE or FLAG\_MUTABLE is required when a PendingIntent is created [\#2759](https://github.com/kivy/python-for-android/issues/2759) - there is an issue with playing video from URL on the latest p4a releases [\#2744](https://github.com/kivy/python-for-android/issues/2744) -- App crashes at launch on specific devices \(\[libpython3.9.so\] \_PyEval\_EvalFrameDefault\) \(Adreno 730?\) [\#2723](https://github.com/kivy/python-for-android/issues/2723) +- App crahes at launch on specific devices \(\[libpython3.9.so\] \_PyEval\_EvalFrameDefault\) \(Adreno 730?\) [\#2723](https://github.com/kivy/python-for-android/issues/2723) - Pandas giving error in Buildozer [\#2719](https://github.com/kivy/python-for-android/issues/2719) - buildozer -v android debug [\#2711](https://github.com/kivy/python-for-android/issues/2711) - \[proposed feature-request\] Lacking psutil recipe [\#2707](https://github.com/kivy/python-for-android/issues/2707) @@ -88,14 +427,14 @@ - libEGL : EGLNativeWindowType disconnect failed [\#2253](https://github.com/kivy/python-for-android/issues/2253) - Hao to support multiprocess Queue in Android [\#2249](https://github.com/kivy/python-for-android/issues/2249) - autoclass: Class only found when called in specific places? [\#2242](https://github.com/kivy/python-for-android/issues/2242) -- the app crash in time of import psycopg2 [\#2240](https://github.com/kivy/python-for-android/issues/2240) +- the app crach in time of import psycopg2 [\#2240](https://github.com/kivy/python-for-android/issues/2240) - env must be a dict [\#2170](https://github.com/kivy/python-for-android/issues/2170) - Pandas doesn't work [\#2157](https://github.com/kivy/python-for-android/issues/2157) - Webview bootstrap can't find 'org.jnius.NativeInvocationHandler'. [\#2140](https://github.com/kivy/python-for-android/issues/2140) - clang++: error: linker command failed with exit code 1 [\#2082](https://github.com/kivy/python-for-android/issues/2082) - ModuleNotFoundError: No module named 'setuptools' [\#2078](https://github.com/kivy/python-for-android/issues/2078) - Scraping web pages with javascript [\#2052](https://github.com/kivy/python-for-android/issues/2052) -- open webbrowser register\(\) error [\#2047](https://github.com/kivy/python-for-android/issues/2047) +- open webbrowser regsiter\(\) error [\#2047](https://github.com/kivy/python-for-android/issues/2047) - Missing javaclass when using able with previously working recipe [\#2041](https://github.com/kivy/python-for-android/issues/2041) - :Class not found b'org/kivy/android/PythonActivity$ActivityResultListener' [\#2039](https://github.com/kivy/python-for-android/issues/2039) - App\(using socket and opencv\) crash on opening [\#2038](https://github.com/kivy/python-for-android/issues/2038) @@ -121,9 +460,9 @@ - Same issue w/ -lpython2.7 not found, workaround [\#1753](https://github.com/kivy/python-for-android/issues/1753) - Several issues when installing packages via pip [\#1745](https://github.com/kivy/python-for-android/issues/1745) - Publish a new Kivy Launcher for Python 3 [\#1638](https://github.com/kivy/python-for-android/issues/1638) -- Travis conditional bootstrap build support [\#1588](https://github.com/kivy/python-for-android/issues/1588) +- Travis conditional boostrap build support [\#1588](https://github.com/kivy/python-for-android/issues/1588) - Error when execute APK only on device: ImportError: cannot import name \_htmlparser [\#1523](https://github.com/kivy/python-for-android/issues/1523) -- onSensorChanged continuously called during app execution [\#1498](https://github.com/kivy/python-for-android/issues/1498) +- onSensorChanged continuosly called during app execution [\#1498](https://github.com/kivy/python-for-android/issues/1498) - GC deadlock on subprocess [\#1461](https://github.com/kivy/python-for-android/issues/1461) - Code runs on old pygame backend but not on SDL2 [\#1411](https://github.com/kivy/python-for-android/issues/1411) - build-tools below 25 will not add jars [\#1345](https://github.com/kivy/python-for-android/issues/1345) @@ -138,6 +477,7 @@ **Merged pull requests:** +- Release 2024.01.21 [\#2959](https://github.com/kivy/python-for-android/pull/2959) ([misl6](https://github.com/misl6)) - Update OpenSSL version to `1.1.1w` [\#2958](https://github.com/kivy/python-for-android/pull/2958) ([prolenodev](https://github.com/prolenodev)) - Bump Kivy version to `2.3.0` [\#2952](https://github.com/kivy/python-for-android/pull/2952) ([misl6](https://github.com/misl6)) - `sourceCompatibility` 1.7 and `targetCompatibility` 1.7 are obsolete, use 1.8 by default [\#2942](https://github.com/kivy/python-for-android/pull/2942) ([misl6](https://github.com/misl6)) @@ -148,7 +488,7 @@ - Initial support for PySide6 and Qt [\#2918](https://github.com/kivy/python-for-android/pull/2918) ([shyamnathp](https://github.com/shyamnathp)) - Introduce FAQ [\#2917](https://github.com/kivy/python-for-android/pull/2917) ([Julian-O](https://github.com/Julian-O)) - Add \(now mandatory\) `.readthedocs.yaml` file, add docs `requirements.txt` and update sphinx conf [\#2916](https://github.com/kivy/python-for-android/pull/2916) ([misl6](https://github.com/misl6)) -- enable json1 extension in sqlite3 [\#2915](https://github.com/kivy/python-for-android/pull/2915) ([HyTurtle](https://github.com/HyTurtle)) +- enable json1 extenstion in sqlite3 [\#2915](https://github.com/kivy/python-for-android/pull/2915) ([HyTurtle](https://github.com/HyTurtle)) - Bump `pyjnius` version to `1.6.1` [\#2914](https://github.com/kivy/python-for-android/pull/2914) ([misl6](https://github.com/misl6)) - Remove `distutils` usage, as is not available anymore on Python `3.12` [\#2912](https://github.com/kivy/python-for-android/pull/2912) ([misl6](https://github.com/misl6)) - Update Lottie player version [\#2900](https://github.com/kivy/python-for-android/pull/2900) ([HugoDaniel](https://github.com/HugoDaniel)) @@ -157,8 +497,7 @@ - Update Android gradle plugin to `8.1.1` and gradle to `8.0.2` [\#2887](https://github.com/kivy/python-for-android/pull/2887) ([misl6](https://github.com/misl6)) - Add support for Python `3.11` and make it the default while building `hostpython3` and `python3` [\#2850](https://github.com/kivy/python-for-android/pull/2850) ([T-Dynamos](https://github.com/T-Dynamos)) - -## [v2023.09.16](https://github.com/kivy/python-for-android/tree/v2023.09.16) +## [v2023.09.16](https://github.com/kivy/python-for-android/tree/v2023.09.16) (2023-09-17) [Full Changelog](https://github.com/kivy/python-for-android/compare/v2023.05.21...v2023.09.16) @@ -166,12 +505,12 @@ - Microphone And Audio permissions doesn't work [\#2889](https://github.com/kivy/python-for-android/issues/2889) - Error with Scipy [\#2883](https://github.com/kivy/python-for-android/issues/2883) -- Download failed \( Downloading sqlite3 from https://www.sqlite.org/2021/sqlite-amalgamation-3350500.zip \) during buildozer -v android debug [\#2881](https://github.com/kivy/python-for-android/issues/2881) +- Download failed \( Downloading sqlite3 from https://www.sqlite.org/2021/sqlite-amalgamation-3350500.zip \) during buildozer -v andriod debug [\#2881](https://github.com/kivy/python-for-android/issues/2881) - ONNXruntime lib open failed due to 64-bit [\#2880](https://github.com/kivy/python-for-android/issues/2880) - Question: how to write a recipe to download and install\(coz build fail\) a wheel package directly? [\#2878](https://github.com/kivy/python-for-android/issues/2878) - Impossible to install python for android [\#2867](https://github.com/kivy/python-for-android/issues/2867) - scipy with kivy [\#2861](https://github.com/kivy/python-for-android/issues/2861) -- False positive parser warning. [\#2856](https://github.com/kivy/python-for-android/issues/2856) +- False positve parser warning. [\#2856](https://github.com/kivy/python-for-android/issues/2856) - After successfully building app, its crashes with this error, using firebase-admin [\#2854](https://github.com/kivy/python-for-android/issues/2854) - Kivy [\#2837](https://github.com/kivy/python-for-android/issues/2837) - not installing on windows 10 [\#2836](https://github.com/kivy/python-for-android/issues/2836) @@ -188,6 +527,7 @@ **Merged pull requests:** +- Release 2023.09.16 [\#2891](https://github.com/kivy/python-for-android/pull/2891) ([misl6](https://github.com/misl6)) - Use Python's touch\(\) rather than shelling out. [\#2886](https://github.com/kivy/python-for-android/pull/2886) ([Julian-O](https://github.com/Julian-O)) - Standardise on move [\#2884](https://github.com/kivy/python-for-android/pull/2884) ([Julian-O](https://github.com/Julian-O)) - Remove deprecated FlatDir in Gradle template [\#2876](https://github.com/kivy/python-for-android/pull/2876) ([Julian-O](https://github.com/Julian-O)) @@ -218,7 +558,7 @@ - Merge master into develop [\#2797](https://github.com/kivy/python-for-android/pull/2797) ([misl6](https://github.com/misl6)) - Use build rather than pep517 for building [\#2784](https://github.com/kivy/python-for-android/pull/2784) ([s-t-e-v-e-n-k](https://github.com/s-t-e-v-e-n-k)) -## [v2023.05.21](https://github.com/kivy/python-for-android/tree/v2023.05.21) +## [v2023.05.21](https://github.com/kivy/python-for-android/tree/v2023.05.21) (2023-05-22) [Full Changelog](https://github.com/kivy/python-for-android/compare/v2023.02.10...v2023.05.21) @@ -240,11 +580,12 @@ - c/\_cffi\_backend.c:407:23: error: expression is not assignable [\#2753](https://github.com/kivy/python-for-android/issues/2753) - not install [\#2749](https://github.com/kivy/python-for-android/issues/2749) - APK crashes upon launch. logcat error: null pointer dereference \(occurs with imported modules\) [\#2358](https://github.com/kivy/python-for-android/issues/2358) -- Error occurred while building the application using buildozer [\#2104](https://github.com/kivy/python-for-android/issues/2104) +- Error occured while building the aplication using buildozer [\#2104](https://github.com/kivy/python-for-android/issues/2104) - "Could Not Extract Public Data" Needs very explicit instructions or feedback to the user [\#260](https://github.com/kivy/python-for-android/issues/260) **Merged pull requests:** +- Release 2023.05.21 [\#2796](https://github.com/kivy/python-for-android/pull/2796) ([misl6](https://github.com/misl6)) - Update Kivy recipe for 2.2.0 [\#2793](https://github.com/kivy/python-for-android/pull/2793) ([misl6](https://github.com/misl6)) - Update `pyjnius` version to `1.5.0` [\#2791](https://github.com/kivy/python-for-android/pull/2791) ([misl6](https://github.com/misl6)) - fix tools/liblink: syntax error [\#2771](https://github.com/kivy/python-for-android/pull/2771) ([SomberNight](https://github.com/SomberNight)) @@ -257,8 +598,7 @@ - Merge master into develop [\#2748](https://github.com/kivy/python-for-android/pull/2748) ([misl6](https://github.com/misl6)) - Add support for Python 3.10 and make it the default while building hostpython3 and python3 [\#2577](https://github.com/kivy/python-for-android/pull/2577) ([misl6](https://github.com/misl6)) - -## [v2023.02.10](https://github.com/kivy/python-for-android/tree/v2023.02.10) (2023-02-10) +## [v2023.02.10](https://github.com/kivy/python-for-android/tree/v2023.02.10) (2023-02-11) [Full Changelog](https://github.com/kivy/python-for-android/compare/v2023.01.28...v2023.02.10) @@ -269,6 +609,7 @@ **Merged pull requests:** +- Release 2023.02.10 [\#2747](https://github.com/kivy/python-for-android/pull/2747) ([misl6](https://github.com/misl6)) - restrict sh version [\#2746](https://github.com/kivy/python-for-android/pull/2746) ([HyTurtle](https://github.com/HyTurtle)) - 🐛 fix: Update `pydantic` recipe [\#2742](https://github.com/kivy/python-for-android/pull/2742) ([FilipeMarch](https://github.com/FilipeMarch)) - Merge master into develop [\#2741](https://github.com/kivy/python-for-android/pull/2741) ([misl6](https://github.com/misl6)) @@ -294,13 +635,14 @@ **Merged pull requests:** +- Release 2023.01.28 [\#2740](https://github.com/kivy/python-for-android/pull/2740) ([misl6](https://github.com/misl6)) - Implements `--manifest-orientation` and changes how `--orientation` works so we can now pass the setting to the SDL orientation hint [\#2739](https://github.com/kivy/python-for-android/pull/2739) ([misl6](https://github.com/misl6)) - Update \_\_init\_\_.py from `scrypt` recipe [\#2738](https://github.com/kivy/python-for-android/pull/2738) ([FilipeMarch](https://github.com/FilipeMarch)) - Apply a patch from SDL upstream that fixes orientation settings [\#2730](https://github.com/kivy/python-for-android/pull/2730) ([misl6](https://github.com/misl6)) - Support permission properties \(`maxSdkVersion` and `usesPermissionFlags`\) + remove `WRITE_EXTERNAL_STORAGE` permission, which has been previously declared by default [\#2725](https://github.com/kivy/python-for-android/pull/2725) ([misl6](https://github.com/misl6)) - Merge master in develop [\#2721](https://github.com/kivy/python-for-android/pull/2721) ([misl6](https://github.com/misl6)) -## [v2022.12.20](https://github.com/kivy/python-for-android/tree/v2022.12.20) (2022-12-20) +## [v2022.12.20](https://github.com/kivy/python-for-android/tree/v2022.12.20) (2022-12-24) [Full Changelog](https://github.com/kivy/python-for-android/compare/v2022.09.04...v2022.12.20) @@ -317,18 +659,19 @@ - ffpyplayer recipe broken after SDL2 upgrade [\#2698](https://github.com/kivy/python-for-android/issues/2698) - ModuleNotFoundError: No module named 'android' [\#2697](https://github.com/kivy/python-for-android/issues/2697) - Error When I set android.api = 31 [\#2696](https://github.com/kivy/python-for-android/issues/2696) -- Is there any way to protect .py code [\#2695](https://github.com/kivy/python-for-android/issues/2695) +- Is threre any way to protect .py code [\#2695](https://github.com/kivy/python-for-android/issues/2695) - args.service\_class\_name results in link error [\#2679](https://github.com/kivy/python-for-android/issues/2679) - Remove `x86_64` suffix from ndk download link [\#2676](https://github.com/kivy/python-for-android/issues/2676) - Pillow 9.2.0 recipe? [\#2671](https://github.com/kivy/python-for-android/issues/2671) - `ffmpeg`: unable to find library -lvpx [\#2665](https://github.com/kivy/python-for-android/issues/2665) -- Buildozer fails while build numpy recipe 'UnixCCompiler' object has no attribute 'cxx\_compiler' [\#2664](https://github.com/kivy/python-for-android/issues/2664) +- Buildozer fails while build numpy recipie 'UnixCCompiler' object has no attribute 'cxx\_compiler' [\#2664](https://github.com/kivy/python-for-android/issues/2664) - \[PEP 517\] Relax installation-time "pep517\<0.7.0" requirement [\#2573](https://github.com/kivy/python-for-android/issues/2573) - Add support for custom resources [\#2298](https://github.com/kivy/python-for-android/issues/2298) - Auto-correct / word suggestion does not work with Swiftkey/Samsung keyboard [\#2010](https://github.com/kivy/python-for-android/issues/2010) **Merged pull requests:** +- Release 2022.12.20 [\#2718](https://github.com/kivy/python-for-android/pull/2718) ([misl6](https://github.com/misl6)) - `InputType.TYPE_TEXT_FLAG_MULTI_LINE` forces `InputType.TYPE_TEXT` even if `SDLActivity.keyboardInputType` is `NULL` [\#2716](https://github.com/kivy/python-for-android/pull/2716) ([misl6](https://github.com/misl6)) - secp256k1 Update "--host=" [\#2714](https://github.com/kivy/python-for-android/pull/2714) ([RobertFlatt](https://github.com/RobertFlatt)) - Delete pythonforandroid/recipes/cdecimal directory [\#2713](https://github.com/kivy/python-for-android/pull/2713) ([RobertFlatt](https://github.com/RobertFlatt)) @@ -352,9 +695,10 @@ - `toml` may not be available on systemwide python [\#2670](https://github.com/kivy/python-for-android/pull/2670) ([misl6](https://github.com/misl6)) - android/activity: Add Application.ActivityLifecycleCallbacks helpers [\#2669](https://github.com/kivy/python-for-android/pull/2669) ([dbnicholson](https://github.com/dbnicholson)) - Bump minimal and recommended Android NDK version to 25b [\#2668](https://github.com/kivy/python-for-android/pull/2668) ([misl6](https://github.com/misl6)) +- Merge master in develop [\#2667](https://github.com/kivy/python-for-android/pull/2667) ([misl6](https://github.com/misl6)) - Include HOME in build environment [\#2582](https://github.com/kivy/python-for-android/pull/2582) ([dbnicholson](https://github.com/dbnicholson)) -## [v2022.09.04](https://github.com/kivy/python-for-android/tree/v2022.09.04) (2022-09-04) +## [v2022.09.04](https://github.com/kivy/python-for-android/tree/v2022.09.04) (2022-09-05) [Full Changelog](https://github.com/kivy/python-for-android/compare/v2022.07.20...v2022.09.04) @@ -382,13 +726,14 @@ **Merged pull requests:** +- Release 2022.09.04 [\#2666](https://github.com/kivy/python-for-android/pull/2666) ([misl6](https://github.com/misl6)) - `liblzma`: Use `p4a_install` instead of `install`, as a file named `INSTALL` is already present. [\#2663](https://github.com/kivy/python-for-android/pull/2663) ([misl6](https://github.com/misl6)) - Force `--platform=linux/amd64` in Dockerfile [\#2660](https://github.com/kivy/python-for-android/pull/2660) ([misl6](https://github.com/misl6)) - Remove six and enum34 dependency [\#2657](https://github.com/kivy/python-for-android/pull/2657) ([misl6](https://github.com/misl6)) - Update supported Python versions [\#2656](https://github.com/kivy/python-for-android/pull/2656) ([misl6](https://github.com/misl6)) - Fixes some E275 - assert is a keyword. [\#2647](https://github.com/kivy/python-for-android/pull/2647) ([misl6](https://github.com/misl6)) - Updates matplotlib, fixes an issue related to shared libc++ [\#2645](https://github.com/kivy/python-for-android/pull/2645) ([misl6](https://github.com/misl6)) -- RTSP support for ffmpeg [\#2644](https://github.com/kivy/python-for-android/pull/2644) ([alicakici1234](https://github.com/alicakici1234)) +- RTSP support for ffmpeg [\#2644](https://github.com/kivy/python-for-android/pull/2644) ([ali-cakici-dev](https://github.com/ali-cakici-dev)) - Fixes TypeError: str.join\(\) takes exactly one argument \(2 given\) in hostpython3/\_\_init\_\_.py", line 69 [\#2642](https://github.com/kivy/python-for-android/pull/2642) ([Furtif](https://github.com/Furtif)) - Resolve absolute path to local recipes [\#2640](https://github.com/kivy/python-for-android/pull/2640) ([dbnicholson](https://github.com/dbnicholson)) - Merges master into develop after release 2022.07.20 [\#2639](https://github.com/kivy/python-for-android/pull/2639) ([misl6](https://github.com/misl6)) @@ -427,16 +772,15 @@ - "Unit test apk" + "Unit test aab" + "Test updated recipes" test jobs should be run also on macOS \(both Intel and Apple Silicon\) [\#2569](https://github.com/kivy/python-for-android/issues/2569) - unpackPyBundle\(\) on startup crashes already running service [\#2564](https://github.com/kivy/python-for-android/issues/2564) - Webview app fail to startup. [\#2559](https://github.com/kivy/python-for-android/issues/2559) -- GenericNDKBuildRecipe Not compiling with android api \> 28 [\#2555](https://github.com/kivy/python-for-android/issues/2555) +- genericndkbuild receipe Not compiling with android api \> 28 [\#2555](https://github.com/kivy/python-for-android/issues/2555) - Is there a way to build smaller apks? [\#2553](https://github.com/kivy/python-for-android/issues/2553) - Webview, icon [\#2552](https://github.com/kivy/python-for-android/issues/2552) -- SONAME header not present in libpython3.8.so [\#2548](https://github.com/kivy/python-for-android/issues/2548) - How to mention Python modules in Kivy buildozer.spec file? [\#2547](https://github.com/kivy/python-for-android/issues/2547) - Issue with pyaudio and portaudio [\#2535](https://github.com/kivy/python-for-android/issues/2535) - \[Temporary Resolved\] Python 4 android in mac os with Apple Silicon via Roseta [\#2528](https://github.com/kivy/python-for-android/issues/2528) - Scipy is not installed due to "Error: 'numpy' must be installed before running the build." [\#2509](https://github.com/kivy/python-for-android/issues/2509) - Lapack depends on arm-linux-androideabi-gfortran [\#2508](https://github.com/kivy/python-for-android/issues/2508) -- Apk file built by buildozer is large in comparison to other apks [\#2473](https://github.com/kivy/python-for-android/issues/2473) +- Apk file built by buildozer is large in comparision to other apks [\#2473](https://github.com/kivy/python-for-android/issues/2473) - p4a is not compatible with ndk \>= 22 [\#2391](https://github.com/kivy/python-for-android/issues/2391) - Sympy module. Error in buildozer: no module named sympy.testing [\#2381](https://github.com/kivy/python-for-android/issues/2381) - build.gradle 'compile' depreciated [\#2362](https://github.com/kivy/python-for-android/issues/2362) @@ -458,6 +802,7 @@ **Merged pull requests:** +- Release 2022.07.20 [\#2638](https://github.com/kivy/python-for-android/pull/2638) ([misl6](https://github.com/misl6)) - Use `shutil.which` instead of `sh.which` [\#2637](https://github.com/kivy/python-for-android/pull/2637) ([misl6](https://github.com/misl6)) - add service\_lib and aar to the docs [\#2634](https://github.com/kivy/python-for-android/pull/2634) ([mzakharo](https://github.com/mzakharo)) - Fix issue \#2630 [\#2631](https://github.com/kivy/python-for-android/pull/2631) ([Neizvestnyj](https://github.com/Neizvestnyj)) @@ -524,18 +869,20 @@ **Merged pull requests:** +- Release 2022.03.13 [\#2561](https://github.com/kivy/python-for-android/pull/2561) ([misl6](https://github.com/misl6)) - Upgrading the flask version to avoid exception at the start of webview application [\#2560](https://github.com/kivy/python-for-android/pull/2560) ([Prashanth-BC](https://github.com/Prashanth-BC)) - add recipe for freetype-py to not include the prebuilt .so for the wr… [\#2558](https://github.com/kivy/python-for-android/pull/2558) ([domedave](https://github.com/domedave)) - Update to Kivy 2.1.0 [\#2557](https://github.com/kivy/python-for-android/pull/2557) ([RobertFlatt](https://github.com/RobertFlatt)) - tflite-runtime recipe [\#2554](https://github.com/kivy/python-for-android/pull/2554) ([RobertFlatt](https://github.com/RobertFlatt)) - Update AndroidManifest.tmpl.xml [\#2551](https://github.com/kivy/python-for-android/pull/2551) ([drahba](https://github.com/drahba)) - Update recipe.py \(\#2544\) [\#2546](https://github.com/kivy/python-for-android/pull/2546) ([misl6](https://github.com/misl6)) +- refactoring code with For Else [\#2544](https://github.com/kivy/python-for-android/pull/2544) ([idiomaticrefactoring](https://github.com/idiomaticrefactoring)) - Update python versions matrix on CI [\#2534](https://github.com/kivy/python-for-android/pull/2534) ([misl6](https://github.com/misl6)) - Add ifaddr recipe [\#2527](https://github.com/kivy/python-for-android/pull/2527) ([syrykh](https://github.com/syrykh)) - Remove websocket-client recipe [\#2526](https://github.com/kivy/python-for-android/pull/2526) ([syrykh](https://github.com/syrykh)) - Fix build [\#2525](https://github.com/kivy/python-for-android/pull/2525) ([correa](https://github.com/correa)) - Add aaptOptions noCompress [\#2523](https://github.com/kivy/python-for-android/pull/2523) ([RobertFlatt](https://github.com/RobertFlatt)) -- Updated version of pygame from 2.0.1 to 2.1.0 [\#2520](https://github.com/kivy/python-for-android/pull/2520) ([CAPTAIN1947](https://github.com/CAPTAIN1947)) +- Updated version of pygame from 2.0.1 to 2.1.0 [\#2520](https://github.com/kivy/python-for-android/pull/2520) ([captain0xff](https://github.com/captain0xff)) - Bump Pillow version to 8.4.0 [\#2516](https://github.com/kivy/python-for-android/pull/2516) ([misl6](https://github.com/misl6)) - Moved support-request to v2. v1 has been shut down. [\#2515](https://github.com/kivy/python-for-android/pull/2515) ([misl6](https://github.com/misl6)) - Add support-requests configuration. [\#2514](https://github.com/kivy/python-for-android/pull/2514) ([misl6](https://github.com/misl6)) @@ -552,7 +899,7 @@ - AAB support related changes [\#2467](https://github.com/kivy/python-for-android/pull/2467) ([misl6](https://github.com/misl6)) - services: fix START\_STICKY [\#2401](https://github.com/kivy/python-for-android/pull/2401) ([mzakharo](https://github.com/mzakharo)) -## [v2021.09.05](https://github.com/kivy/python-for-android/tree/v2021.09.05) (2021-09-05) +## [v2021.09.05](https://github.com/kivy/python-for-android/tree/v2021.09.05) (2021-09-06) [Full Changelog](https://github.com/kivy/python-for-android/compare/v2020.06.02...v2021.09.05) @@ -562,13 +909,12 @@ **Closed issues:** -- Global variable/objetct isn't being shared between multiple files on Android, while the same code works normally under Windows. [\#2485](https://github.com/kivy/python-for-android/issues/2485) +- Global varible/objetct isn't being shared between multiple files on Android, while the same code works normally under Windows. [\#2485](https://github.com/kivy/python-for-android/issues/2485) - audiostream recipe does not copy .java files, leading to a crash when trying to open mic on android [\#2483](https://github.com/kivy/python-for-android/issues/2483) - Applying patches for hostpython3 fails [\#2476](https://github.com/kivy/python-for-android/issues/2476) - p4a failing to build webapp [\#2475](https://github.com/kivy/python-for-android/issues/2475) - Failed to build with recipe MySQLdb \(setuptools,libmysqlclient\) [\#2474](https://github.com/kivy/python-for-android/issues/2474) - ctypes.util.find\_library 64-bit error [\#2468](https://github.com/kivy/python-for-android/issues/2468) -- Android x86\_64 instant crash with hello world app, missing zlib [\#2460](https://github.com/kivy/python-for-android/issues/2460) - pycrypto recipe is arm7 only [\#2457](https://github.com/kivy/python-for-android/issues/2457) - lazy loading of recycleview and wa [\#2454](https://github.com/kivy/python-for-android/issues/2454) - a kivy app can not send request to any website in phone [\#2450](https://github.com/kivy/python-for-android/issues/2450) @@ -610,7 +956,7 @@ - How to add webp support to pillow? [\#2254](https://github.com/kivy/python-for-android/issues/2254) - Unable to run executable on Android [\#2251](https://github.com/kivy/python-for-android/issues/2251) - Provide a native service option [\#2243](https://github.com/kivy/python-for-android/issues/2243) -- the kivy app crash in time of import psycopg2 [\#2241](https://github.com/kivy/python-for-android/issues/2241) +- the kivy app crach in time of import psycopg2 [\#2241](https://github.com/kivy/python-for-android/issues/2241) - How can we make a camera App with zoom by Kivy [\#2238](https://github.com/kivy/python-for-android/issues/2238) - Building pycrypto for arm64-v8a fails [\#2230](https://github.com/kivy/python-for-android/issues/2230) - buildozer error Building pycrypto for arm64-v8a and x86\_64 [\#2216](https://github.com/kivy/python-for-android/issues/2216) @@ -622,6 +968,7 @@ **Merged pull requests:** +- Release 2021.09.05 [\#2488](https://github.com/kivy/python-for-android/pull/2488) ([misl6](https://github.com/misl6)) - Drop travis-ci.org and use github-actions for pypi release [\#2487](https://github.com/kivy/python-for-android/pull/2487) ([misl6](https://github.com/misl6)) - Upgrade grunt version re: CVE-2020-7729 [\#2484](https://github.com/kivy/python-for-android/pull/2484) ([Zen-CODE](https://github.com/Zen-CODE)) - Recipe for pydantic [\#2480](https://github.com/kivy/python-for-android/pull/2480) ([FilipeMarch](https://github.com/FilipeMarch)) @@ -673,7 +1020,7 @@ - :arrow\_up: Updates to Kivy2 [\#2384](https://github.com/kivy/python-for-android/pull/2384) ([kuzeyron](https://github.com/kuzeyron)) - fix travis [\#2383](https://github.com/kivy/python-for-android/pull/2383) ([obfusk](https://github.com/obfusk)) - :bug: Fixes pip command on Travis and bumps actions/setup-python [\#2382](https://github.com/kivy/python-for-android/pull/2382) ([AndreMiras](https://github.com/AndreMiras)) -- docs: fix simple typo, packaged -\> packaged [\#2377](https://github.com/kivy/python-for-android/pull/2377) ([timgates42](https://github.com/timgates42)) +- docs: fix simple typo, pacakged -\> packaged [\#2377](https://github.com/kivy/python-for-android/pull/2377) ([timgates42](https://github.com/timgates42)) - Fix master only merges [\#2376](https://github.com/kivy/python-for-android/pull/2376) ([inclement](https://github.com/inclement)) - Audiostream Fix [\#2375](https://github.com/kivy/python-for-android/pull/2375) ([xloem](https://github.com/xloem)) - Add service information for buildozer.spec [\#2372](https://github.com/kivy/python-for-android/pull/2372) ([xloem](https://github.com/xloem)) @@ -689,7 +1036,7 @@ - added few input parameters to make possible to use custom java classes and tweak AndroidManifest.xml [\#2338](https://github.com/kivy/python-for-android/pull/2338) ([vesellov](https://github.com/vesellov)) - ffmpeg and ffpyplayer improvements [\#2335](https://github.com/kivy/python-for-android/pull/2335) ([rnixx](https://github.com/rnixx)) - Add recipe for https://docs.aiohttp.org/en/stable/ [\#2332](https://github.com/kivy/python-for-android/pull/2332) ([rambo](https://github.com/rambo)) -- Update \_\_init\_\_.py for Report Lab recipe [\#2323](https://github.com/kivy/python-for-android/pull/2323) ([marcets](https://github.com/marcets)) +- Update \_\_init\_\_.py for Report Lab recipe [\#2323](https://github.com/kivy/python-for-android/pull/2323) ([mp-007](https://github.com/mp-007)) - Print patched message to stderr [\#2314](https://github.com/kivy/python-for-android/pull/2314) ([rambo](https://github.com/rambo)) - Call cython via the setuptools entrypoint, fixes \#2311 [\#2312](https://github.com/kivy/python-for-android/pull/2312) ([rambo](https://github.com/rambo)) - Allow using background color with lottie splashscreen [\#2305](https://github.com/kivy/python-for-android/pull/2305) ([tshirtman](https://github.com/tshirtman)) @@ -755,21 +1102,21 @@ **Merged pull requests:** - Release 2020.06.02 [\#2225](https://github.com/kivy/python-for-android/pull/2225) ([AndreMiras](https://github.com/AndreMiras)) -- :arrow_up: Bumps to Gradle 6.4.1 [\#2222](https://github.com/kivy/python-for-android/pull/2222) ([AndreMiras](https://github.com/AndreMiras)) +- :arrow\_up: Bumps to Gradle 6.4.1 [\#2222](https://github.com/kivy/python-for-android/pull/2222) ([AndreMiras](https://github.com/AndreMiras)) - :bug: Adds missing requests sub dependencies [\#2221](https://github.com/kivy/python-for-android/pull/2221) ([AndreMiras](https://github.com/AndreMiras)) -- :arrow_up: Bumps to Cython==0.29.19 [\#2220](https://github.com/kivy/python-for-android/pull/2220) ([AndreMiras](https://github.com/AndreMiras)) +- :arrow\_up: Bumps to Cython==0.29.19 [\#2220](https://github.com/kivy/python-for-android/pull/2220) ([AndreMiras](https://github.com/AndreMiras)) - :pencil: Updates install and troubleshooting docs [\#2219](https://github.com/kivy/python-for-android/pull/2219) ([AndreMiras](https://github.com/AndreMiras)) -- :arrow_up: Bumps to Ubuntu 20.04 [\#2218](https://github.com/kivy/python-for-android/pull/2218) ([AndreMiras](https://github.com/AndreMiras)) +- :arrow\_up: Bumps to Ubuntu 20.04 [\#2218](https://github.com/kivy/python-for-android/pull/2218) ([AndreMiras](https://github.com/AndreMiras)) - :pencil: Attempt to improve the issue template [\#2217](https://github.com/kivy/python-for-android/pull/2217) ([AndreMiras](https://github.com/AndreMiras)) - :package: Split logic for build modes & debug symbols [\#2213](https://github.com/kivy/python-for-android/pull/2213) ([opacam](https://github.com/opacam)) - :sparkles: Add `opencv_extras` recipe [\#2209](https://github.com/kivy/python-for-android/pull/2209) ([opacam](https://github.com/opacam)) - :books: Troubleshoot SSL error [\#2205](https://github.com/kivy/python-for-android/pull/2205) ([AndreMiras](https://github.com/AndreMiras)) - Remove superfluous recipes fixes \#1387 [\#2202](https://github.com/kivy/python-for-android/pull/2202) ([AndreMiras](https://github.com/AndreMiras)) -- :white_check_mark: Add tests for hostpython3 recipe [\#2196](https://github.com/kivy/python-for-android/pull/2196) ([opacam](https://github.com/opacam)) +- :white\_check\_mark: Add tests for hostpython3 recipe [\#2196](https://github.com/kivy/python-for-android/pull/2196) ([opacam](https://github.com/opacam)) - Fix for 'ImportError: No module named setuptools', encountered when building with buildozer [\#2195](https://github.com/kivy/python-for-android/pull/2195) ([atom2626](https://github.com/atom2626)) - :pencil2: Rename `Hostpython3Recipe` class to camel case [\#2194](https://github.com/kivy/python-for-android/pull/2194) ([opacam](https://github.com/opacam)) - :ambulance: Fix `test_should_build` [\#2193](https://github.com/kivy/python-for-android/pull/2193) ([opacam](https://github.com/opacam)) -- :white_check_mark: Add initial tests for python3 recipe [\#2192](https://github.com/kivy/python-for-android/pull/2192) ([opacam](https://github.com/opacam)) +- :white\_check\_mark: Add initial tests for python3 recipe [\#2192](https://github.com/kivy/python-for-android/pull/2192) ([opacam](https://github.com/opacam)) - :bug: Fixes flake8 errors post update [\#2191](https://github.com/kivy/python-for-android/pull/2191) ([AndreMiras](https://github.com/AndreMiras)) - PythonActivityUtil helper for unpacking data [\#2189](https://github.com/kivy/python-for-android/pull/2189) ([AndreMiras](https://github.com/AndreMiras)) - Share PythonUtil.java between bootstraps [\#2188](https://github.com/kivy/python-for-android/pull/2188) ([AndreMiras](https://github.com/AndreMiras)) @@ -801,7 +1148,7 @@ - BUILD FAILURE: No main.py\(o\) found in your app directory. [\#2171](https://github.com/kivy/python-for-android/issues/2171) - \[ERROR\] Building cffi for armeabi-v7a [\#2161](https://github.com/kivy/python-for-android/issues/2161) -- Setting p4a.source_dir in buildozer causes AttributeError: module 'build' has no attribute 'parse\_args\_and\_make\_package' [\#2149](https://github.com/kivy/python-for-android/issues/2149) +- Setting p4a.source\_dir in buildozer causes AttributeError: module 'build' has no attribute 'parse\_args\_and\_make\_package' [\#2149](https://github.com/kivy/python-for-android/issues/2149) - Full screen apps have significantly degraded performance [\#2148](https://github.com/kivy/python-for-android/issues/2148) - Build failed: Couldn't find executable for CC [\#2146](https://github.com/kivy/python-for-android/issues/2146) - Sign in apk is not working [\#2139](https://github.com/kivy/python-for-android/issues/2139) @@ -844,7 +1191,6 @@ - \[recipes\] Update harfbuzz to v2.6.4 [\#2069](https://github.com/kivy/python-for-android/pull/2069) ([opacam](https://github.com/opacam)) - \[recipes\] Update freetype & add zlib support [\#2068](https://github.com/kivy/python-for-android/pull/2068) ([opacam](https://github.com/opacam)) - Unify most of the test apps into `on device unit test app` [\#2046](https://github.com/kivy/python-for-android/pull/2046) ([opacam](https://github.com/opacam)) -- Fix debug build not resulting in gdb-debuggable build [\#1867](https://github.com/kivy/python-for-android/pull/1867) ([etc0de](https://github.com/etc0de)) - fix for the problem with decorator run\_on\_ui\_thread and the local ref… [\#1830](https://github.com/kivy/python-for-android/pull/1830) ([oukiar](https://github.com/oukiar)) ## [v2020.03.30](https://github.com/kivy/python-for-android/tree/v2020.03.30) (2020-04-04) @@ -855,7 +1201,6 @@ - Remove `--sysroot` from LDFLAGS for cffi and pymunk [\#1965](https://github.com/kivy/python-for-android/pull/1965) ([opacam](https://github.com/opacam)) - Fix build for case-insensitive FS and add CI test for OSX [\#1951](https://github.com/kivy/python-for-android/pull/1951) ([opacam](https://github.com/opacam)) -- Also copy the service/main.py when building with setup.py [\#1936](https://github.com/kivy/python-for-android/pull/1936) ([etc0de](https://github.com/etc0de)) **Closed issues:** @@ -873,7 +1218,7 @@ - Hadi [\#2048](https://github.com/kivy/python-for-android/issues/2048) - p4a \(2019.10.6\) project build file management [\#2045](https://github.com/kivy/python-for-android/issues/2045) - listdir of primary\_external\_storage\_path\(\) fails [\#2032](https://github.com/kivy/python-for-android/issues/2032) -- Can't use AsyncImage with HTTPS URL \(or any HTTPS url with any request\): fix is to manually load certifi [\#1827](https://github.com/kivy/python-for-android/issues/1827) +- Can't use AsyncImage with HTTPS URL \(or any HTTPS url wit any request\): fix is to manually load certifi [\#1827](https://github.com/kivy/python-for-android/issues/1827) **Merged pull requests:** @@ -881,13 +1226,13 @@ - Release 2020.03.30 [\#2111](https://github.com/kivy/python-for-android/pull/2111) ([inclement](https://github.com/inclement)) - Updates quickstart.rst "Installing Dependencies" [\#2109](https://github.com/kivy/python-for-android/pull/2109) ([AndreMiras](https://github.com/AndreMiras)) - :alien: Remove deprecated key `sudo` from `travis.yml` [\#2102](https://github.com/kivy/python-for-android/pull/2102) ([opacam](https://github.com/opacam)) -- :arrow_up: Update `pytz` to version `2019.3` [\#2101](https://github.com/kivy/python-for-android/pull/2101) ([opacam](https://github.com/opacam)) +- :arrow\_up: Update `pytz` to version `2019.3` [\#2101](https://github.com/kivy/python-for-android/pull/2101) ([opacam](https://github.com/opacam)) - :sparkles: Add `pandas` recipe [\#2100](https://github.com/kivy/python-for-android/pull/2100) ([opacam](https://github.com/opacam)) - Fixes psycopg2 URL, closes \#2098 [\#2099](https://github.com/kivy/python-for-android/pull/2099) ([AndreMiras](https://github.com/AndreMiras)) - :sparkles: Compression libraries - episode III: add support for libbz2 & liblzma to python3 [\#2097](https://github.com/kivy/python-for-android/pull/2097) ([opacam](https://github.com/opacam)) - :sparkles: Compression libraries - episode II: liblzma [\#2096](https://github.com/kivy/python-for-android/pull/2096) ([opacam](https://github.com/opacam)) - :sparkles: Compression libraries - episode I: libbz2 [\#2095](https://github.com/kivy/python-for-android/pull/2095) ([opacam](https://github.com/opacam)) -- Update quickstart.rst [\#2094](https://github.com/kivy/python-for-android/pull/2094) ([BornForFever](https://github.com/BornForFever)) +- Update quickstart.rst [\#2094](https://github.com/kivy/python-for-android/pull/2094) ([yvvt0379](https://github.com/yvvt0379)) - Fixes gevent recipe on arm64-v8a arch [\#2093](https://github.com/kivy/python-for-android/pull/2093) ([AndreMiras](https://github.com/AndreMiras)) - :bug: Add `-fPIC` to `CFLAGS` for Arch `x86_64` [\#2085](https://github.com/kivy/python-for-android/pull/2085) ([opacam](https://github.com/opacam)) - Fix Python 3.8.1 patch naming and content [\#2083](https://github.com/kivy/python-for-android/pull/2083) ([opacam](https://github.com/opacam)) @@ -987,10 +1332,6 @@ [Full Changelog](https://github.com/kivy/python-for-android/compare/v2019.07.08...v2019.08.09) -**Fixed bugs:** - -- Call Cython via `python -m Cython` rather than system-wide binary [\#1937](https://github.com/kivy/python-for-android/pull/1937) ([etc0de](https://github.com/etc0de)) - **Closed issues:** - Building an Android Library [\#1957](https://github.com/kivy/python-for-android/issues/1957) @@ -1018,7 +1359,6 @@ - Added setuptools to Kivy recipe requirements [\#1938](https://github.com/kivy/python-for-android/pull/1938) ([inclement](https://github.com/inclement)) - Bumps to Kivy==1.11.1 [\#1935](https://github.com/kivy/python-for-android/pull/1935) ([AndreMiras](https://github.com/AndreMiras)) - Increases toolchain.py test coverage [\#1933](https://github.com/kivy/python-for-android/pull/1933) ([AndreMiras](https://github.com/AndreMiras)) -- Add a document describing how p4a interacts with pip & python packages [\#1931](https://github.com/kivy/python-for-android/pull/1931) ([etc0de](https://github.com/etc0de)) - Fix pyzmq \(libunwind and arm64-v8a\) [\#1930](https://github.com/kivy/python-for-android/pull/1930) ([tito](https://github.com/tito)) - Basic toolchain.py unit tests [\#1928](https://github.com/kivy/python-for-android/pull/1928) ([AndreMiras](https://github.com/AndreMiras)) - Merge 2019.07.08 release branch to develop [\#1921](https://github.com/kivy/python-for-android/pull/1921) ([inclement](https://github.com/inclement)) @@ -1027,11 +1367,9 @@ - Drop CrystaX support and code base [\#1913](https://github.com/kivy/python-for-android/pull/1913) ([opacam](https://github.com/opacam)) - Release 2019.07.08 [\#1909](https://github.com/kivy/python-for-android/pull/1909) ([inclement](https://github.com/inclement)) - Add documentation: testing a pull request [\#1901](https://github.com/kivy/python-for-android/pull/1901) ([opacam](https://github.com/opacam)) -- Fix foreground notification being mandatory and more \(attempt 2\) [\#1888](https://github.com/kivy/python-for-android/pull/1888) ([etc0de](https://github.com/etc0de)) - Make it raise an error if an old ndk is used [\#1883](https://github.com/kivy/python-for-android/pull/1883) ([opacam](https://github.com/opacam)) - Hotfix 2019.06.06.post0: added long\_description\_content\_type to setup.py [\#1850](https://github.com/kivy/python-for-android/pull/1850) ([inclement](https://github.com/inclement)) - feat: Allows registering the onRequestPermissionsResult callback. [\#1818](https://github.com/kivy/python-for-android/pull/1818) ([gbm001](https://github.com/gbm001)) -- Add functions for obtaining the default storage paths [\#1598](https://github.com/kivy/python-for-android/pull/1598) ([etc0de](https://github.com/etc0de)) ## [v2019.07.08](https://github.com/kivy/python-for-android/tree/v2019.07.08) (2019-07-11) @@ -1041,12 +1379,9 @@ - Fix crash when guessing Bootstrap \(expand\_dependencies\) [\#1914](https://github.com/kivy/python-for-android/pull/1914) ([opacam](https://github.com/opacam)) - Fix `run_pymodules_install` when `project_dir` isn't supplied [\#1898](https://github.com/kivy/python-for-android/pull/1898) ([opacam](https://github.com/opacam)) -- Fix Bootstrap.get\_bootstrap\_from\_recipes\(\) so it's smarter and deterministic, fixes \#1875 [\#1887](https://github.com/kivy/python-for-android/pull/1887) ([etc0de](https://github.com/etc0de)) - Typo [\#1880](https://github.com/kivy/python-for-android/pull/1880) ([JensGe](https://github.com/JensGe)) - Fix wrong env variable for `hostpython build path` in `archs.py` [\#1871](https://github.com/kivy/python-for-android/pull/1871) ([opacam](https://github.com/opacam)) -- Fix various setup.py processing bugs [\#1862](https://github.com/kivy/python-for-android/pull/1862) ([etc0de](https://github.com/etc0de)) - Add `--without-bzip2` to freetype's configure args [\#1857](https://github.com/kivy/python-for-android/pull/1857) ([opacam](https://github.com/opacam)) -- pythonpackage can't return build requirements for wheels, make it return an error if attempted [\#1852](https://github.com/kivy/python-for-android/pull/1852) ([etc0de](https://github.com/etc0de)) **Closed issues:** @@ -1079,8 +1414,6 @@ - Add unittest for module `pythonforandroid.bootstrap` [\#1872](https://github.com/kivy/python-for-android/pull/1872) ([opacam](https://github.com/opacam)) - Remove legacy version of openssl [\#1870](https://github.com/kivy/python-for-android/pull/1870) ([opacam](https://github.com/opacam)) - Make the tox jobs run in parallel &... [\#1864](https://github.com/kivy/python-for-android/pull/1864) ([opacam](https://github.com/opacam)) -- Try to be more clear in README about api levels & quickstart [\#1863](https://github.com/kivy/python-for-android/pull/1863) ([etc0de](https://github.com/etc0de)) -- Fix locating system python when it's not in $PATH \(weird but happens, apparently\) [\#1856](https://github.com/kivy/python-for-android/pull/1856) ([etc0de](https://github.com/etc0de)) - Add unittest for `pythonforandroid.util` and... [\#1855](https://github.com/kivy/python-for-android/pull/1855) ([opacam](https://github.com/opacam)) - Merge 2019.06.06.post0 hotfix: set long\_description\_content\_type in setup.py [\#1851](https://github.com/kivy/python-for-android/pull/1851) ([inclement](https://github.com/inclement)) - Improved release model documentation [\#1849](https://github.com/kivy/python-for-android/pull/1849) ([inclement](https://github.com/inclement)) @@ -1101,7 +1434,6 @@ - Cannot build APK - IndexError: List index out of range [\#1774](https://github.com/kivy/python-for-android/issues/1774) - ctypes.util.find\_library\(\) doesn't work on arch arm64-v8a [\#1770](https://github.com/kivy/python-for-android/issues/1770) - error building compiled components in netifaces [\#1539](https://github.com/kivy/python-for-android/issues/1539) -- \[WIP\] Fix crashes when using other commands than 'apk' [\#1809](https://github.com/kivy/python-for-android/pull/1809) ([etc0de](https://github.com/etc0de)) **Closed issues:** @@ -1115,11 +1447,10 @@ - Some links are broken in the docs [\#1780](https://github.com/kivy/python-for-android/issues/1780) - packaged python is built with IPv6 disabled [\#1771](https://github.com/kivy/python-for-android/issues/1771) - `p4a recipes` terminates with error [\#1769](https://github.com/kivy/python-for-android/issues/1769) -- the application does not work with scipy package [\#1767](https://github.com/kivy/python-for-android/issues/1767) - openssl not in the build order when compiling cryptography [\#1764](https://github.com/kivy/python-for-android/issues/1764) - "--orientation fullUser" is not working [\#1763](https://github.com/kivy/python-for-android/issues/1763) -- pydub problem [\#1759](https://github.com/kivy/python-for-android/issues/1759) - App crashes using python3 and android's run\_on\_ui\_thread [\#1755](https://github.com/kivy/python-for-android/issues/1755) +- pydub problem [\#1759](https://github.com/kivy/python-for-android/issues/1759) - str.decode\(\) issue again for Python 3 [\#1749](https://github.com/kivy/python-for-android/issues/1749) - Error while in gradlew [\#1740](https://github.com/kivy/python-for-android/issues/1740) - Buildozer [\#1736](https://github.com/kivy/python-for-android/issues/1736) @@ -1137,7 +1468,7 @@ - Webview build can't find `SDL_setenv`. [\#1702](https://github.com/kivy/python-for-android/issues/1702) - lxml and requests recipe: build interrupted, "\_ctype" error [\#1700](https://github.com/kivy/python-for-android/issues/1700) - weird orientation behavior [\#1698](https://github.com/kivy/python-for-android/issues/1698) -- SDLActivity.java\:1948\: error: cannot find symbol case MotionEvent.ACTION\_BUTTON\_PRESS: [\#1697](https://github.com/kivy/python-for-android/issues/1697) +- SDLActivity.java:1948: error: cannot find symbol case MotionEvent.ACTION\_BUTTON\_PRESS: [\#1697](https://github.com/kivy/python-for-android/issues/1697) - ImportError [\#1694](https://github.com/kivy/python-for-android/issues/1694) - unicode error during startup \(python3, numpy, opencv\) - patch included [\#1691](https://github.com/kivy/python-for-android/issues/1691) - "--orientation sensor" no longer works [\#1688](https://github.com/kivy/python-for-android/issues/1688) @@ -1176,7 +1507,6 @@ - enable IPv6 for packaged python3 [\#1815](https://github.com/kivy/python-for-android/pull/1815) ([SomberNight](https://github.com/SomberNight)) - Update pymunk to v5.5.0 [\#1814](https://github.com/kivy/python-for-android/pull/1814) ([viblo](https://github.com/viblo)) - Fixes ffpyplayer build [\#1813](https://github.com/kivy/python-for-android/pull/1813) ([misl6](https://github.com/misl6)) -- Fix corner case of pip hack workaround we should get rid of anyway [\#1807](https://github.com/kivy/python-for-android/pull/1807) ([etc0de](https://github.com/etc0de)) - Fixed doc links to plyer and pyjnius [\#1806](https://github.com/kivy/python-for-android/pull/1806) ([inclement](https://github.com/inclement)) - Fixed libzqm recipe linking issues [\#1803](https://github.com/kivy/python-for-android/pull/1803) ([hpsaturn](https://github.com/hpsaturn)) - Update recipes.rst [\#1799](https://github.com/kivy/python-for-android/pull/1799) ([FunmiKesa](https://github.com/FunmiKesa)) @@ -1186,8 +1516,6 @@ - Move ffmpeg download url to github repo [\#1791](https://github.com/kivy/python-for-android/pull/1791) ([misl6](https://github.com/misl6)) - Ignores Python 2 import\_recipe\(\) warnings [\#1789](https://github.com/kivy/python-for-android/pull/1789) ([AndreMiras](https://github.com/AndreMiras)) - \[kivy\] updated to 44a8a6f [\#1777](https://github.com/kivy/python-for-android/pull/1777) ([goffi-contrib](https://github.com/goffi-contrib)) -- Fix outdated PySDL2 version and non-PyPI install source [\#1775](https://github.com/kivy/python-for-android/pull/1775) ([etc0de](https://github.com/etc0de)) -- Properly search native lib dir in ctypes, fixes \#1770 [\#1772](https://github.com/kivy/python-for-android/pull/1772) ([etc0de](https://github.com/etc0de)) - \[kivy\] updated recipe to c4d6894 revision [\#1766](https://github.com/kivy/python-for-android/pull/1766) ([goffi-contrib](https://github.com/goffi-contrib)) - Fixes libglob recipe, closes \#1399 [\#1765](https://github.com/kivy/python-for-android/pull/1765) ([AndreMiras](https://github.com/AndreMiras)) - \[doubleratchet\] removed this recipe [\#1762](https://github.com/kivy/python-for-android/pull/1762) ([goffi-contrib](https://github.com/goffi-contrib)) @@ -1225,11 +1553,9 @@ - FIX: copy additional jar files into the correct libs directory [\#1693](https://github.com/kivy/python-for-android/pull/1693) ([OptimusGREEN](https://github.com/OptimusGREEN)) - SDL2\_image update to 2.0.4 and set kivy's version to master [\#1692](https://github.com/kivy/python-for-android/pull/1692) ([opacam](https://github.com/opacam)) - Use nativeSetenv\(\) provided by SDL2 and cleanups [\#1690](https://github.com/kivy/python-for-android/pull/1690) ([j-devel](https://github.com/j-devel)) -- Rename misguided shadowing --blacklist to --blacklist-requirements [\#1689](https://github.com/kivy/python-for-android/pull/1689) ([etc0de](https://github.com/etc0de)) - Deleted kivent recipes from constants.py [\#1686](https://github.com/kivy/python-for-android/pull/1686) ([inclement](https://github.com/inclement)) - Downgrade to pycryptodome==3.6.3 [\#1685](https://github.com/kivy/python-for-android/pull/1685) ([AndreMiras](https://github.com/AndreMiras)) - Added option to support custom shared libraries with \ tag [\#1684](https://github.com/kivy/python-for-android/pull/1684) ([pax0r](https://github.com/pax0r)) -- Implement --blacklist option and include more modules/recipes by default [\#1683](https://github.com/kivy/python-for-android/pull/1683) ([etc0de](https://github.com/etc0de)) - Origin [\#1681](https://github.com/kivy/python-for-android/pull/1681) ([strubbi77](https://github.com/strubbi77)) - Delete kivent recipes [\#1680](https://github.com/kivy/python-for-android/pull/1680) ([inclement](https://github.com/inclement)) - Fix zope\_interface and add python3 compatibility [\#1677](https://github.com/kivy/python-for-android/pull/1677) ([opacam](https://github.com/opacam)) @@ -1238,14 +1564,11 @@ - tox update and linter fixes [\#1674](https://github.com/kivy/python-for-android/pull/1674) ([AndreMiras](https://github.com/AndreMiras)) - tox update and linter fixes [\#1673](https://github.com/kivy/python-for-android/pull/1673) ([AndreMiras](https://github.com/AndreMiras)) - Delete the pygame bootstrap [\#1670](https://github.com/kivy/python-for-android/pull/1670) ([inclement](https://github.com/inclement)) -- Fix various issues with graphs and recipes [\#1669](https://github.com/kivy/python-for-android/pull/1669) ([etc0de](https://github.com/etc0de)) -- Fix setup.py install breaking due to unicode characters in README.md on Python 3 [\#1667](https://github.com/kivy/python-for-android/pull/1667) ([etc0de](https://github.com/etc0de)) - s/README.rst/README.md/ refs \#1664 [\#1666](https://github.com/kivy/python-for-android/pull/1666) ([AndreMiras](https://github.com/AndreMiras)) - Update and rename README.rst to README.md [\#1664](https://github.com/kivy/python-for-android/pull/1664) ([tito](https://github.com/tito)) - Defaults to post kivy==1.10.1 commit for SDL 2.0.9 fixes [\#1663](https://github.com/kivy/python-for-android/pull/1663) ([AndreMiras](https://github.com/AndreMiras)) - Rework opencv's recipe \(enable cv2.so and the extra opencv libraries\) [\#1661](https://github.com/kivy/python-for-android/pull/1661) ([opacam](https://github.com/opacam)) - Updated version to 0.7.1 [\#1660](https://github.com/kivy/python-for-android/pull/1660) ([inclement](https://github.com/inclement)) -- \[WIP\] Run project's setup.py if present, unless --ignore-setup-py was set [\#1625](https://github.com/kivy/python-for-android/pull/1625) ([etc0de](https://github.com/etc0de)) ## [0.7.0](https://github.com/kivy/python-for-android/tree/0.7.0) (2019-02-01) @@ -1255,7 +1578,7 @@ - python3 + openssl compilation fail [\#1590](https://github.com/kivy/python-for-android/issues/1590) - Update conditional build to python3 [\#1485](https://github.com/kivy/python-for-android/issues/1485) -- building apk fails \( python 3 \) [\#746](https://github.com/kivy/python-for-android/issues/746) +- building apk failes \( python 3 \) [\#746](https://github.com/kivy/python-for-android/issues/746) **Closed issues:** @@ -1303,7 +1626,7 @@ - p4a --requirements ignores absolute folder paths [\#1487](https://github.com/kivy/python-for-android/issues/1487) - Set the api level from 19 to 28 failed [\#1482](https://github.com/kivy/python-for-android/issues/1482) - libxml2 build broken on latest p4a master with python 3 [\#1479](https://github.com/kivy/python-for-android/issues/1479) -- working: make: \*\*\* \[Makefile\:426\: sharedmods\] Error 139 [\#1474](https://github.com/kivy/python-for-android/issues/1474) +- working: make: \*\*\* \[Makefile:426: sharedmods\] Error 139 [\#1474](https://github.com/kivy/python-for-android/issues/1474) - .pxd files of dependency targeted recipe'd library not found [\#1473](https://github.com/kivy/python-for-android/issues/1473) - Python 3 recipe follow up issues [\#1455](https://github.com/kivy/python-for-android/issues/1455) - Python-4-Android NumPy error: 'struct lconv' has no member named 'decimal\_point' [\#1450](https://github.com/kivy/python-for-android/issues/1450) @@ -1349,7 +1672,7 @@ - Auto-close awaiting-reply labeled issues [\#1331](https://github.com/kivy/python-for-android/issues/1331) - App crashes when sending POST request http [\#1329](https://github.com/kivy/python-for-android/issues/1329) - kivy build error with python3crystax [\#1328](https://github.com/kivy/python-for-android/issues/1328) -- No "pil" or "pillow" available for Python 3 [\#1326](https://github.com/kivy/python-for-android/issues/1326) +- No "pil" or "pillow" avaliable for Python 3 [\#1326](https://github.com/kivy/python-for-android/issues/1326) - pillow fails on import [\#1325](https://github.com/kivy/python-for-android/issues/1325) - Unavoidable PySDL2 crash on app resume [\#1323](https://github.com/kivy/python-for-android/issues/1323) - Tons of different PySDL2 crashes when tabbing in/out of application during loading or right after it finished [\#1321](https://github.com/kivy/python-for-android/issues/1321) @@ -1366,7 +1689,7 @@ - numpy Python3/Crystax broken toolchain can't link a simple C program [\#1303](https://github.com/kivy/python-for-android/issues/1303) - Screen Rotation and Re-layout [\#1302](https://github.com/kivy/python-for-android/issues/1302) - IOError: \[Errno socket error\] \[Errno 104\] Connection reset by peer [\#1301](https://github.com/kivy/python-for-android/issues/1301) -- Python2 Build fails with make: \*\*\* \[Makefile\:426\: sharedmods\] Error 139 [\#1297](https://github.com/kivy/python-for-android/issues/1297) +- Python2 Build fails with make: \*\*\* \[Makefile:426: sharedmods\] Error 139 [\#1297](https://github.com/kivy/python-for-android/issues/1297) - ffmpeg breaks buildozer android debug compilation process. [\#1294](https://github.com/kivy/python-for-android/issues/1294) - Android: python startup complaining about missing hashlib functions [\#1293](https://github.com/kivy/python-for-android/issues/1293) - sh.CommandNotFound: ndk\_build [\#1292](https://github.com/kivy/python-for-android/issues/1292) @@ -1414,20 +1737,20 @@ - The python3crystax recipe can only be built when using the CrystaX NDK. [\#1225](https://github.com/kivy/python-for-android/issues/1225) - Didn't find any valid dependency graphs. [\#1222](https://github.com/kivy/python-for-android/issues/1222) - Google requiring API Target 26 in Aug/Nov 2018 [\#1219](https://github.com/kivy/python-for-android/issues/1219) -- p4a can't find android sdk [\#1218](https://github.com/kivy/python-for-android/issues/1218) +- p4a cant find android sdk [\#1218](https://github.com/kivy/python-for-android/issues/1218) - IOError: \[Errno 2\] No such file or directory: u'/Users/gauravgupta/kivy/.buildozer/android/platform/build/dists/myellipse/build/outputs/apk/myellipse-debug.apk' [\#1216](https://github.com/kivy/python-for-android/issues/1216) -- Buildozer android application crashes on android [\#1215](https://github.com/kivy/python-for-android/issues/1215) +- Buildozer android application crashs on android [\#1215](https://github.com/kivy/python-for-android/issues/1215) - Multiple issues with latest Android SDK [\#1212](https://github.com/kivy/python-for-android/issues/1212) -- sdkmanager doesn't exist [\#1210](https://github.com/kivy/python-for-android/issues/1210) +- sdkmanager doesnt exist [\#1210](https://github.com/kivy/python-for-android/issues/1210) - add-jar doesn't work [\#1208](https://github.com/kivy/python-for-android/issues/1208) - Kivy not working on Sony devices [\#1206](https://github.com/kivy/python-for-android/issues/1206) - sqlite pre-populated database not being found [\#1203](https://github.com/kivy/python-for-android/issues/1203) - Try python3.7 with Google NDK [\#1202](https://github.com/kivy/python-for-android/issues/1202) - commit 3534a761 [\#1200](https://github.com/kivy/python-for-android/issues/1200) -- Kivy basic button program doesn't work [\#1199](https://github.com/kivy/python-for-android/issues/1199) +- Kivy basic button program doesnt work [\#1199](https://github.com/kivy/python-for-android/issues/1199) - Error Pythonforandroid.toolchain -m [\#1196](https://github.com/kivy/python-for-android/issues/1196) - assert keyword do not work [\#1193](https://github.com/kivy/python-for-android/issues/1193) -- macOS High Siera installation issue [\#1192](https://github.com/kivy/python-for-android/issues/1192) +- macOS Hight Siera installation issue [\#1192](https://github.com/kivy/python-for-android/issues/1192) - failed to setup p4a on ubuntu \(multiple issues\) [\#1191](https://github.com/kivy/python-for-android/issues/1191) - Cryptography woes: Can we freshen up our Python version... [\#1190](https://github.com/kivy/python-for-android/issues/1190) - Kivy crashes immediately on start, on Sony devices [\#1188](https://github.com/kivy/python-for-android/issues/1188) @@ -1468,7 +1791,7 @@ - ImportError: No module named audioop [\#1067](https://github.com/kivy/python-for-android/issues/1067) - sqlite3 not working with android\_new [\#1053](https://github.com/kivy/python-for-android/issues/1053) - dlopen failed: python2.7/site-packages/grpc/\_cython/cygrpc.so not 32-bit: 2 [\#1052](https://github.com/kivy/python-for-android/issues/1052) -- Can't start service app [\#1049](https://github.com/kivy/python-for-android/issues/1049) +- Cant start service app [\#1049](https://github.com/kivy/python-for-android/issues/1049) - Cannot build APK with python3crystax and flask - conflicting dependencies [\#1041](https://github.com/kivy/python-for-android/issues/1041) - Slow build process since sh 1.12.5 [\#1038](https://github.com/kivy/python-for-android/issues/1038) - Python3 + PyYaml conflict [\#1031](https://github.com/kivy/python-for-android/issues/1031) @@ -1496,7 +1819,7 @@ - ImportError android [\#943](https://github.com/kivy/python-for-android/issues/943) - Older android version can't load libraries properly [\#925](https://github.com/kivy/python-for-android/issues/925) - sed: 1: "Modules/Setup.local": invalid command code M [\#924](https://github.com/kivy/python-for-android/issues/924) -- Python3: armeabi used to copy, but armeabi-v7a chosen [\#913](https://github.com/kivy/python-for-android/issues/913) +- Python3: armeabi used to copy, but armeabi-v7a choosen [\#913](https://github.com/kivy/python-for-android/issues/913) - ImportError for sqlite3 [\#910](https://github.com/kivy/python-for-android/issues/910) - PyGame backend: error while using android.copy\_libs = 1 [\#888](https://github.com/kivy/python-for-android/issues/888) - pytz installation works, but requires user to make build folder manually [\#884](https://github.com/kivy/python-for-android/issues/884) @@ -1579,15 +1902,12 @@ - Remove old toolchain doc and add short note about overriding recipe sources [\#1641](https://github.com/kivy/python-for-android/pull/1641) ([inclement](https://github.com/inclement)) - Added separate module for checking user SDK, NDK, API etc. [\#1640](https://github.com/kivy/python-for-android/pull/1640) ([inclement](https://github.com/inclement)) - Added app for on-device unit tests [\#1636](https://github.com/kivy/python-for-android/pull/1636) ([inclement](https://github.com/inclement)) -- Revert use of shlex.quote to avoid problems with python 2 [\#1635](https://github.com/kivy/python-for-android/pull/1635) ([etc0de](https://github.com/etc0de)) - Default Travis builds to Python3 [\#1634](https://github.com/kivy/python-for-android/pull/1634) ([AndreMiras](https://github.com/AndreMiras)) - Fixes ifaddrs recipe, closes \#1398 [\#1633](https://github.com/kivy/python-for-android/pull/1633) ([AndreMiras](https://github.com/AndreMiras)) - Do not verbose the "tar tf" command [\#1631](https://github.com/kivy/python-for-android/pull/1631) ([AndreMiras](https://github.com/AndreMiras)) - psycopg2 recipe fixes and doc, fixes \#1405 [\#1629](https://github.com/kivy/python-for-android/pull/1629) ([AndreMiras](https://github.com/AndreMiras)) - Use enaml {version} rather than master, fixes \#1409 [\#1628](https://github.com/kivy/python-for-android/pull/1628) ([AndreMiras](https://github.com/AndreMiras)) - Clean-up LDSHARED, fixes \#1360 [\#1627](https://github.com/kivy/python-for-android/pull/1627) ([AndreMiras](https://github.com/AndreMiras)) -- Fix ctypes.util.find\_library\(\) not finding any libraries on Android [\#1624](https://github.com/kivy/python-for-android/pull/1624) ([etc0de](https://github.com/etc0de)) -- Fix librt recipe requires that NDK folder is writable [\#1623](https://github.com/kivy/python-for-android/pull/1623) ([etc0de](https://github.com/etc0de)) - Update of Recipes for python3 test [\#1622](https://github.com/kivy/python-for-android/pull/1622) ([strubbi77](https://github.com/strubbi77)) - - let cymunk also be built with python3 recipe [\#1620](https://github.com/kivy/python-for-android/pull/1620) ([maho](https://github.com/maho)) - Make python flags to be absolute paths for Android.mk files [\#1619](https://github.com/kivy/python-for-android/pull/1619) ([opacam](https://github.com/opacam)) @@ -1595,7 +1915,7 @@ - Made recipe graph resolution respect opt\_depends [\#1617](https://github.com/kivy/python-for-android/pull/1617) ([inclement](https://github.com/inclement)) - Fix C code being wrong for python2 in start.c \(char \* to wchar\_t \*\) [\#1616](https://github.com/kivy/python-for-android/pull/1616) ([opacam](https://github.com/opacam)) - Removed argument to cp that doesn't exist on macOS [\#1614](https://github.com/kivy/python-for-android/pull/1614) ([inclement](https://github.com/inclement)) -- Fix incorrect site-packages path breaking keyboard test app at runtime [\#1610](https://github.com/kivy/python-for-android/pull/1610) ([etc0de](https://github.com/etc0de)) +- Fix incorrect site-packages path breaking keyboard test app at runtime [\#1610](https://github.com/kivy/python-for-android/pull/1610) ([ghost](https://github.com/ghost)) - Fix libffi/ctypes - wrong libffi headers when building python [\#1609](https://github.com/kivy/python-for-android/pull/1609) ([opacam](https://github.com/opacam)) - Fix getting empty "modules" directory when arch is not armeabi-v7a [\#1608](https://github.com/kivy/python-for-android/pull/1608) ([j-devel](https://github.com/j-devel)) - Fix strip in bootstrap [\#1607](https://github.com/kivy/python-for-android/pull/1607) ([j-devel](https://github.com/j-devel)) @@ -1607,9 +1927,7 @@ - Fix hardcoded entries \(build platform\) for core modules: archs and python [\#1597](https://github.com/kivy/python-for-android/pull/1597) ([opacam](https://github.com/opacam)) - Fix zeroconf compilation and grants python3 compatibility [\#1596](https://github.com/kivy/python-for-android/pull/1596) ([opacam](https://github.com/opacam)) - Fix reportlab's recipe `crypt.h` error [\#1595](https://github.com/kivy/python-for-android/pull/1595) ([opacam](https://github.com/opacam)) -- Fix --force-build incorrectly listed as --force\_build, fixes \#1565 [\#1593](https://github.com/kivy/python-for-android/pull/1593) ([etc0de](https://github.com/etc0de)) - Allow patching from any folder + fix pygame components issues [\#1592](https://github.com/kivy/python-for-android/pull/1592) ([opacam](https://github.com/opacam)) -- Fix --private and others showing weird error when used without argument [\#1591](https://github.com/kivy/python-for-android/pull/1591) ([etc0de](https://github.com/etc0de)) - Minimal fixes to make pygame bootstrap work with python2legacy [\#1587](https://github.com/kivy/python-for-android/pull/1587) ([opacam](https://github.com/opacam)) - Corrections for `Fix bootstraps for webview and service_only` \(recently merged\) [\#1586](https://github.com/kivy/python-for-android/pull/1586) ([opacam](https://github.com/opacam)) - \[CORE FIX/ENHANCEMENT\] Speedup copy that can be very very long \(up to 2 minutes\) [\#1585](https://github.com/kivy/python-for-android/pull/1585) ([opacam](https://github.com/opacam)) @@ -1618,11 +1936,7 @@ - fix missing gethostbyname\_r on Android 5.1 [\#1581](https://github.com/kivy/python-for-android/pull/1581) ([opacam](https://github.com/opacam)) - \[WIP\] Rework libxml2, libxslt and lxml \(update versions\) [\#1580](https://github.com/kivy/python-for-android/pull/1580) ([opacam](https://github.com/opacam)) - Fixes ffmpeg compilation w/ openssl 1.1.1 [\#1579](https://github.com/kivy/python-for-android/pull/1579) ([misl6](https://github.com/misl6)) -- Fix incorrect call assuming that OS python minor version matches hostpython [\#1577](https://github.com/kivy/python-for-android/pull/1577) ([etc0de](https://github.com/etc0de)) -- Add download retries to deal better with connection hiccups during build [\#1574](https://github.com/kivy/python-for-android/pull/1574) ([etc0de](https://github.com/etc0de)) - Rework for Pillow/pil recipes & update jpeg and png [\#1573](https://github.com/kivy/python-for-android/pull/1573) ([opacam](https://github.com/opacam)) -- Fix APP\_PLATFORM not properly passed in NDKRecipe [\#1572](https://github.com/kivy/python-for-android/pull/1572) ([etc0de](https://github.com/etc0de)) -- Fix outdated hardcoded python recipe references in lxml, reportlab & Pillow recipe [\#1571](https://github.com/kivy/python-for-android/pull/1571) ([etc0de](https://github.com/etc0de)) - Fix linkage problems with python's versioned library \(reintroduce `INSTSONAME`\) [\#1568](https://github.com/kivy/python-for-android/pull/1568) ([opacam](https://github.com/opacam)) - \[OMEMO\] updated omemo recipe [\#1566](https://github.com/kivy/python-for-android/pull/1566) ([goffi-contrib](https://github.com/goffi-contrib)) - Render format string argument on BuildInterruptingException [\#1561](https://github.com/kivy/python-for-android/pull/1561) ([AndreMiras](https://github.com/AndreMiras)) @@ -1642,32 +1956,131 @@ - \[CORE UPDATE - PART II\] Fix bootstraps for webview and service\_only [\#1541](https://github.com/kivy/python-for-android/pull/1541) ([opacam](https://github.com/opacam)) - \[CORE UPDATE - PART I\] Refactor python recipes + openssl + sqlite3 [\#1537](https://github.com/kivy/python-for-android/pull/1537) ([opacam](https://github.com/opacam)) - Re-added argument that was lost during build.py merge [\#1533](https://github.com/kivy/python-for-android/pull/1533) ([inclement](https://github.com/inclement)) -- Use API 27 as new default for travis & docs [\#1532](https://github.com/kivy/python-for-android/pull/1532) ([etc0de](https://github.com/etc0de)) -- Bump SDL2 to 2.0.9 & Add API \>=23 runtime permissions API [\#1528](https://github.com/kivy/python-for-android/pull/1528) ([etc0de](https://github.com/etc0de)) -- Unify build.py contents [\#1524](https://github.com/kivy/python-for-android/pull/1524) ([etc0de](https://github.com/etc0de)) -- Unify configChanges manifest entry and add missing values [\#1522](https://github.com/kivy/python-for-android/pull/1522) ([etc0de](https://github.com/etc0de)) - Add google repository at allprojects [\#1521](https://github.com/kivy/python-for-android/pull/1521) ([wo01](https://github.com/wo01)) - Fix bytes/unicode issues in android recipe [\#1516](https://github.com/kivy/python-for-android/pull/1516) ([KeyWeeUsr](https://github.com/KeyWeeUsr)) -- Uses target python3 on conditional builds, fixes \#1485 [\#1515](https://github.com/kivy/python-for-android/pull/1515) ([AndreMiras](https://github.com/AndreMiras)) +- Uses target python3 on conditional buids, fixes \#1485 [\#1515](https://github.com/kivy/python-for-android/pull/1515) ([AndreMiras](https://github.com/AndreMiras)) - Updates websocket-client recipe, fixes \#1253 [\#1513](https://github.com/kivy/python-for-android/pull/1513) ([AndreMiras](https://github.com/AndreMiras)) - No need to decode into unicode when running in python 3 [\#1512](https://github.com/kivy/python-for-android/pull/1512) ([jtoledo1974](https://github.com/jtoledo1974)) - Update gradle version [\#1507](https://github.com/kivy/python-for-android/pull/1507) ([opacam](https://github.com/opacam)) - Fix libnacl recipe missing libsodium [\#1505](https://github.com/kivy/python-for-android/pull/1505) ([KeyWeeUsr](https://github.com/KeyWeeUsr)) -- Make SDL2 & services\_only bootstrap properly error with missing --private [\#1503](https://github.com/kivy/python-for-android/pull/1503) ([etc0de](https://github.com/etc0de)) -- Unify start.c of all bootstraps to one file [\#1500](https://github.com/kivy/python-for-android/pull/1500) ([etc0de](https://github.com/etc0de)) -- Minor fixes to basic common bootstrap handling code [\#1499](https://github.com/kivy/python-for-android/pull/1499) ([etc0de](https://github.com/etc0de)) -- Rework common bootstrap area based on kollivier's work [\#1496](https://github.com/kivy/python-for-android/pull/1496) ([etc0de](https://github.com/etc0de)) - Fixes audiostream recipe on Python3 [\#1495](https://github.com/kivy/python-for-android/pull/1495) ([misl6](https://github.com/misl6)) - when listing distributions, if one has no ndk\_api, consider it to be 0 [\#1494](https://github.com/kivy/python-for-android/pull/1494) ([tshirtman](https://github.com/tshirtman)) -- Make Cython work without recipe [\#1483](https://github.com/kivy/python-for-android/pull/1483) ([etc0de](https://github.com/etc0de)) +- decode gradle path to avoid python3 crash [\#1493](https://github.com/kivy/python-for-android/pull/1493) ([tshirtman](https://github.com/tshirtman)) +- add .tox to git ignore files [\#1486](https://github.com/kivy/python-for-android/pull/1486) ([tito](https://github.com/tito)) - Allow Python 3 To Be Built On Non-ARM Architectures [\#1481](https://github.com/kivy/python-for-android/pull/1481) ([TheBrokenRail](https://github.com/TheBrokenRail)) +- fixes invalid message showed when no ANDROIDNDKVER is set [\#1477](https://github.com/kivy/python-for-android/pull/1477) ([tito](https://github.com/tito)) +- Allow x86\_64 To Build [\#1476](https://github.com/kivy/python-for-android/pull/1476) ([TheBrokenRail](https://github.com/TheBrokenRail)) +- Fix android module JAVA\_NAMESPACE and JNI\_NAMESPACE with unicode [\#1475](https://github.com/kivy/python-for-android/pull/1475) ([KeyWeeUsr](https://github.com/KeyWeeUsr)) - Remove crystax docker and optimize Dockerfile [\#1471](https://github.com/kivy/python-for-android/pull/1471) ([KeyWeeUsr](https://github.com/KeyWeeUsr)) +- Add setup.py build for kivy-launcher reboot [\#1470](https://github.com/kivy/python-for-android/pull/1470) ([KeyWeeUsr](https://github.com/KeyWeeUsr)) +- Allow dist overwrite by default [\#1469](https://github.com/kivy/python-for-android/pull/1469) ([inclement](https://github.com/inclement)) - Replaced many `exit(1)`s with exception raising [\#1468](https://github.com/kivy/python-for-android/pull/1468) ([inclement](https://github.com/inclement)) +- Add instructions for using Docker image for building APKs [\#1467](https://github.com/kivy/python-for-android/pull/1467) ([KeyWeeUsr](https://github.com/KeyWeeUsr)) +- Added a minimum supported NDK api check to the python3 recipe [\#1466](https://github.com/kivy/python-for-android/pull/1466) ([inclement](https://github.com/inclement)) - Add ctypes support for python3's recipe [\#1465](https://github.com/kivy/python-for-android/pull/1465) ([opacam](https://github.com/opacam)) +- python3 is a core recipe built via .travis.yml [\#1464](https://github.com/kivy/python-for-android/pull/1464) ([AndreMiras](https://github.com/AndreMiras)) +- Fixes P4A\_FULL\_DEBUG that is broken [\#1462](https://github.com/kivy/python-for-android/pull/1462) ([tito](https://github.com/tito)) +- Cleans broken python3crystax recipe list [\#1459](https://github.com/kivy/python-for-android/pull/1459) ([AndreMiras](https://github.com/AndreMiras)) +- Show actual values in info messages [\#1458](https://github.com/kivy/python-for-android/pull/1458) ([dbrnz](https://github.com/dbrnz)) +- Various CI improvements [\#1457](https://github.com/kivy/python-for-android/pull/1457) ([AndreMiras](https://github.com/AndreMiras)) +- Added python3 testapp build to Travis matrix [\#1456](https://github.com/kivy/python-for-android/pull/1456) ([inclement](https://github.com/inclement)) +- C++ recipe didn't set all instances of `ctx.ndk_dir` in format string [\#1452](https://github.com/kivy/python-for-android/pull/1452) ([dbrnz](https://github.com/dbrnz)) +- Updates docstring to current state [\#1451](https://github.com/kivy/python-for-android/pull/1451) ([AndreMiras](https://github.com/AndreMiras)) +- \[omemo\] Added recipes needed to build omemo module [\#1444](https://github.com/kivy/python-for-android/pull/1444) ([goffi-contrib](https://github.com/goffi-contrib)) +- \[cryptography\] Updated to last available version \(2.3.1\) [\#1443](https://github.com/kivy/python-for-android/pull/1443) ([goffi-contrib](https://github.com/goffi-contrib)) +- \[libsodium\] Updated to last version \(1.0.16\) [\#1442](https://github.com/kivy/python-for-android/pull/1442) ([goffi-contrib](https://github.com/goffi-contrib)) +- \[cffi\] Updated recipe to last cffi version \(1.11.5\) [\#1441](https://github.com/kivy/python-for-android/pull/1441) ([goffi-contrib](https://github.com/goffi-contrib)) +- \[protobuf\_cpp\] Updated to Protobuf 3.5.1 + fixed protoc issue [\#1440](https://github.com/kivy/python-for-android/pull/1440) ([goffi-contrib](https://github.com/goffi-contrib)) +- allow setting the value for android:allowBackup [\#1438](https://github.com/kivy/python-for-android/pull/1438) ([tshirtman](https://github.com/tshirtman)) +- allow installing/using p4a in a virtualenv [\#1437](https://github.com/kivy/python-for-android/pull/1437) ([tshirtman](https://github.com/tshirtman)) +- Conditional builds falls back on Python2 if needed [\#1435](https://github.com/kivy/python-for-android/pull/1435) ([AndreMiras](https://github.com/AndreMiras)) +- \[pyOpenSSL\] version update [\#1431](https://github.com/kivy/python-for-android/pull/1431) ([goffi-contrib](https://github.com/goffi-contrib)) +- removed mmap from blacklist [\#1430](https://github.com/kivy/python-for-android/pull/1430) ([goffi-contrib](https://github.com/goffi-contrib)) +- Creates non root user in Dockerfile [\#1429](https://github.com/kivy/python-for-android/pull/1429) ([AndreMiras](https://github.com/AndreMiras)) +- lxml recipe [\#1428](https://github.com/kivy/python-for-android/pull/1428) ([goffi-contrib](https://github.com/goffi-contrib)) +- Pins pyjnius==1.1.3, fixes \#1416 [\#1427](https://github.com/kivy/python-for-android/pull/1427) ([AndreMiras](https://github.com/AndreMiras)) +- doc tweaks, grammar fixes and discord contact channel [\#1423](https://github.com/kivy/python-for-android/pull/1423) ([Zen-CODE](https://github.com/Zen-CODE)) +- doc: add instructions on accessing service argument [\#1419](https://github.com/kivy/python-for-android/pull/1419) ([Zen-CODE](https://github.com/Zen-CODE)) +- Installs requirements in a single statement [\#1418](https://github.com/kivy/python-for-android/pull/1418) ([AndreMiras](https://github.com/AndreMiras)) +- Fix pyjnius setup.py patches [\#1417](https://github.com/kivy/python-for-android/pull/1417) ([KeyWeeUsr](https://github.com/KeyWeeUsr)) +- Put install\_reqs on line so that buildozer's rubbish parsing will work [\#1413](https://github.com/kivy/python-for-android/pull/1413) ([inclement](https://github.com/inclement)) +- Python 3 recipe [\#1412](https://github.com/kivy/python-for-android/pull/1412) ([inclement](https://github.com/inclement)) +- List of broken recipes for python2, fixes \#1402 [\#1410](https://github.com/kivy/python-for-android/pull/1410) ([AndreMiras](https://github.com/AndreMiras)) +- List of broken recipes for python3crystax, refs \#1402 [\#1408](https://github.com/kivy/python-for-android/pull/1408) ([AndreMiras](https://github.com/AndreMiras)) +- Fixes Python3.6 and enum34 [\#1403](https://github.com/kivy/python-for-android/pull/1403) ([AndreMiras](https://github.com/AndreMiras)) +- Conditional recipe build fixes \#1382 [\#1401](https://github.com/kivy/python-for-android/pull/1401) ([AndreMiras](https://github.com/AndreMiras)) +- Linter fixes E111, E116, E122, E202, E225, E241... [\#1397](https://github.com/kivy/python-for-android/pull/1397) ([AndreMiras](https://github.com/AndreMiras)) +- Updates docs mentioning IRC to use Discord [\#1396](https://github.com/kivy/python-for-android/pull/1396) ([AndreMiras](https://github.com/AndreMiras)) +- Doc and cosmetics [\#1395](https://github.com/kivy/python-for-android/pull/1395) ([Zen-CODE](https://github.com/Zen-CODE)) +- cryptography: add missing include flag \[pyconfr18\] [\#1394](https://github.com/kivy/python-for-android/pull/1394) ([goffi-contrib](https://github.com/goffi-contrib)) +- twisted: added a patch to disable incremental during setup \[pyconfr18\] [\#1393](https://github.com/kivy/python-for-android/pull/1393) ([goffi-contrib](https://github.com/goffi-contrib)) +- jpeg: use https: URL instead of git: \[pyconfr18\] [\#1392](https://github.com/kivy/python-for-android/pull/1392) ([goffi-contrib](https://github.com/goffi-contrib)) +- Clarify how the package identifier is constructed [\#1389](https://github.com/kivy/python-for-android/pull/1389) ([Zen-CODE](https://github.com/Zen-CODE)) +- Linter fixes E114, E127, E128, E129 [\#1386](https://github.com/kivy/python-for-android/pull/1386) ([AndreMiras](https://github.com/AndreMiras)) +- ReportLabRecipe fixes and unit tests, fixes \#1380 [\#1383](https://github.com/kivy/python-for-android/pull/1383) ([AndreMiras](https://github.com/AndreMiras)) +- Enables unit tests in tox [\#1379](https://github.com/kivy/python-for-android/pull/1379) ([AndreMiras](https://github.com/AndreMiras)) +- Linter fixes E115, E201, E221, E251, E271, E703 [\#1378](https://github.com/kivy/python-for-android/pull/1378) ([AndreMiras](https://github.com/AndreMiras)) +- Adds Python3 support to reportlab, pyrxp and preppy [\#1377](https://github.com/kivy/python-for-android/pull/1377) ([AndreMiras](https://github.com/AndreMiras)) +- Adds Python3 Crystax support to Feedparser [\#1376](https://github.com/kivy/python-for-android/pull/1376) ([AndreMiras](https://github.com/AndreMiras)) +- Fixes and clarifies services auto-restart [\#1374](https://github.com/kivy/python-for-android/pull/1374) ([AndreMiras](https://github.com/AndreMiras)) +- Sets default service pythonName, fixes \#1049 [\#1371](https://github.com/kivy/python-for-android/pull/1371) ([AndreMiras](https://github.com/AndreMiras)) +- Adds issue template with basic required info [\#1370](https://github.com/kivy/python-for-android/pull/1370) ([AndreMiras](https://github.com/AndreMiras)) +- Fix cffi build failing on some hosts [\#1364](https://github.com/kivy/python-for-android/pull/1364) ([krinnewitz](https://github.com/krinnewitz)) - Fix jpeg build for newer NDKs [\#1363](https://github.com/kivy/python-for-android/pull/1363) ([mkg20001](https://github.com/mkg20001)) +- Fixes example service name example consistency [\#1358](https://github.com/kivy/python-for-android/pull/1358) ([AndreMiras](https://github.com/AndreMiras)) +- Update Docker base image Ubuntu Bionic 18.04 [\#1356](https://github.com/kivy/python-for-android/pull/1356) ([AndreMiras](https://github.com/AndreMiras)) +- Fix apk argument parsing oversight [\#1355](https://github.com/kivy/python-for-android/pull/1355) ([wolfgangp](https://github.com/wolfgangp)) +- Fix segfault on hostpython2 when compiling for x86\_64 [\#1351](https://github.com/kivy/python-for-android/pull/1351) ([tito](https://github.com/tito)) +- Add recipes for OpenAL support [\#1348](https://github.com/kivy/python-for-android/pull/1348) ([krinnewitz](https://github.com/krinnewitz)) +- Extend numpy recipe to support python3 [\#1343](https://github.com/kivy/python-for-android/pull/1343) ([krinnewitz](https://github.com/krinnewitz)) +- Added code style exception for android module \* import [\#1340](https://github.com/kivy/python-for-android/pull/1340) ([inclement](https://github.com/inclement)) +- Add Pillow Recipe [\#1339](https://github.com/kivy/python-for-android/pull/1339) ([krinnewitz](https://github.com/krinnewitz)) +- Use zip instead of tar.gz to obtain setuptools [\#1334](https://github.com/kivy/python-for-android/pull/1334) ([krinnewitz](https://github.com/krinnewitz)) +- fix android import [\#1332](https://github.com/kivy/python-for-android/pull/1332) ([akshayaurora](https://github.com/akshayaurora)) +- Defaults to latest kivy==1.10.1 release, fixes \#1328 [\#1330](https://github.com/kivy/python-for-android/pull/1330) ([AndreMiras](https://github.com/AndreMiras)) +- Fix for Mac OS version bug [\#1316](https://github.com/kivy/python-for-android/pull/1316) ([OptimusGREEN](https://github.com/OptimusGREEN)) +- Reduce docker image size [\#1308](https://github.com/kivy/python-for-android/pull/1308) ([opacam](https://github.com/opacam)) +- Troubleshooting NoClassDefFoundError BASE64Encoder [\#1305](https://github.com/kivy/python-for-android/pull/1305) ([AndreMiras](https://github.com/AndreMiras)) +- Adds numpy/python2 to continuous integration, refs \#1263 [\#1304](https://github.com/kivy/python-for-android/pull/1304) ([AndreMiras](https://github.com/AndreMiras)) +- Fix twisted and cryptography build for python 3 [\#1296](https://github.com/kivy/python-for-android/pull/1296) ([om26er](https://github.com/om26er)) +- Recipes updates with CrystaX/Python3 support [\#1295](https://github.com/kivy/python-for-android/pull/1295) ([AndreMiras](https://github.com/AndreMiras)) +- fixes find\_library when deployed external storage [\#1291](https://github.com/kivy/python-for-android/pull/1291) ([AndreMiras](https://github.com/AndreMiras)) +- Made hostpython3crystax check if system python is available [\#1289](https://github.com/kivy/python-for-android/pull/1289) ([inclement](https://github.com/inclement)) +- Groestlcoin hash [\#1288](https://github.com/kivy/python-for-android/pull/1288) ([tshirtman](https://github.com/tshirtman)) +- Fixes linter E203 E231 E261 E302 E303 E305 W291 W293 W391 [\#1286](https://github.com/kivy/python-for-android/pull/1286) ([AndreMiras](https://github.com/AndreMiras)) +- Fixes linter F821 \(undefined name\) [\#1285](https://github.com/kivy/python-for-android/pull/1285) ([AndreMiras](https://github.com/AndreMiras)) +- Fixes linter F401 \(unused imports\) [\#1284](https://github.com/kivy/python-for-android/pull/1284) ([AndreMiras](https://github.com/AndreMiras)) +- Introduces linting \(tox/flake8\) [\#1283](https://github.com/kivy/python-for-android/pull/1283) ([AndreMiras](https://github.com/AndreMiras)) +- Builds setuptools with both python2 & hostpython3crystax [\#1282](https://github.com/kivy/python-for-android/pull/1282) ([AndreMiras](https://github.com/AndreMiras)) +- Feature/ticket1263 setup testapp python3 [\#1281](https://github.com/kivy/python-for-android/pull/1281) ([AndreMiras](https://github.com/AndreMiras)) +- Build `testapp_sqlite_openssl` using `setup_testapp_python2.py` [\#1278](https://github.com/kivy/python-for-android/pull/1278) ([AndreMiras](https://github.com/AndreMiras)) +- Build `testapp_python2` using `setup_testapp_python2.py` [\#1277](https://github.com/kivy/python-for-android/pull/1277) ([AndreMiras](https://github.com/AndreMiras)) +- get\_recipe\_dir\(\) also handle local recipes, fixes \#1185 [\#1276](https://github.com/kivy/python-for-android/pull/1276) ([AndreMiras](https://github.com/AndreMiras)) +- Revert "Merge pull request \#1252 from Iqoqo/master" [\#1273](https://github.com/kivy/python-for-android/pull/1273) ([inclement](https://github.com/inclement)) +- Added 2 tests to ensure directories exist. [\#1262](https://github.com/kivy/python-for-android/pull/1262) ([lufebe16](https://github.com/lufebe16)) +- allow setting launchMode for the main activity in the manifest [\#1256](https://github.com/kivy/python-for-android/pull/1256) ([SomberNight](https://github.com/SomberNight)) +- Continuous integration with Travis and Docker, fixes \#625 [\#1255](https://github.com/kivy/python-for-android/pull/1255) ([AndreMiras](https://github.com/AndreMiras)) +- compile numpy for x86 [\#1252](https://github.com/kivy/python-for-android/pull/1252) ([ilyaiqoqo](https://github.com/ilyaiqoqo)) +- Gevent Crystax/Python3 support [\#1251](https://github.com/kivy/python-for-android/pull/1251) ([AndreMiras](https://github.com/AndreMiras)) +- symlink system Python to hostpython3crystax build dir [\#1249](https://github.com/kivy/python-for-android/pull/1249) ([AndreMiras](https://github.com/AndreMiras)) +- Setuptools for Python3 \(Crystax\) [\#1248](https://github.com/kivy/python-for-android/pull/1248) ([AndreMiras](https://github.com/AndreMiras)) - Added sympy recipe [\#1236](https://github.com/kivy/python-for-android/pull/1236) ([inclement](https://github.com/inclement)) - Added --no-optimize-python option to remove -OO in sdl2 bootstrap [\#1221](https://github.com/kivy/python-for-android/pull/1221) ([inclement](https://github.com/inclement)) +- Made sdl2 build.gradle work with Java 7 [\#1220](https://github.com/kivy/python-for-android/pull/1220) ([inclement](https://github.com/inclement)) +- Adds new recipe: libexpat [\#1214](https://github.com/kivy/python-for-android/pull/1214) ([opacam](https://github.com/opacam)) +- Allow adding activities to the manifest [\#1213](https://github.com/kivy/python-for-android/pull/1213) ([bauerj](https://github.com/bauerj)) +- Include jar files in build.gradle [\#1211](https://github.com/kivy/python-for-android/pull/1211) ([bauerj](https://github.com/bauerj)) +- fix for \#1141 - added ldflags to numpy [\#1209](https://github.com/kivy/python-for-android/pull/1209) ([maho](https://github.com/maho)) +- sdl2: build.tmpl.gradle: sourceCompatibility 1.7 [\#1205](https://github.com/kivy/python-for-android/pull/1205) ([QuadTriangle](https://github.com/QuadTriangle)) +- setup.py: fix installation [\#1204](https://github.com/kivy/python-for-android/pull/1204) ([QuadTriangle](https://github.com/QuadTriangle)) +- FFpyplayer fix for NDK 15+ [\#1201](https://github.com/kivy/python-for-android/pull/1201) ([germn](https://github.com/germn)) +- Fix what looks like a typo [\#1198](https://github.com/kivy/python-for-android/pull/1198) ([rogererens](https://github.com/rogererens)) +- Added missing exit\(1\) call when SDK is not found [\#1194](https://github.com/kivy/python-for-android/pull/1194) ([inclement](https://github.com/inclement)) +- vlc recipe improvements [\#1189](https://github.com/kivy/python-for-android/pull/1189) ([ibobalo](https://github.com/ibobalo)) +- Update \_\_init\_\_.py to support SDL2 [\#1178](https://github.com/kivy/python-for-android/pull/1178) ([snuq](https://github.com/snuq)) +- Support ruamel.yaml, improved yaml lib. [\#1037](https://github.com/kivy/python-for-android/pull/1037) ([mixmastamyk](https://github.com/mixmastamyk)) - android\_new: fix force\_build option [\#1006](https://github.com/kivy/python-for-android/pull/1006) ([ZingBallyhoo](https://github.com/ZingBallyhoo)) +- Fixes the include and link paths for python2 [\#793](https://github.com/kivy/python-for-android/pull/793) ([opacam](https://github.com/opacam)) ## [0.6.0](https://github.com/kivy/python-for-android/tree/0.6.0) (2017-11-25) @@ -1729,7 +2142,6 @@ - Cleaned up some old comments [\#1160](https://github.com/kivy/python-for-android/pull/1160) ([inclement](https://github.com/inclement)) - The pypi python return http 403 error on http [\#1157](https://github.com/kivy/python-for-android/pull/1157) ([brvier](https://github.com/brvier)) - Accept pypi fragmented URLs \(\#md5...\) [\#1155](https://github.com/kivy/python-for-android/pull/1155) ([wexi](https://github.com/wexi)) -- Add note about NDK version on 32-bit OS [\#1150](https://github.com/kivy/python-for-android/pull/1150) ([ghost](https://github.com/ghost)) - Adds zbar \(and dependencies\) support, refs \#854 [\#1145](https://github.com/kivy/python-for-android/pull/1145) ([AndreMiras](https://github.com/AndreMiras)) - Remove unused `extract_source()` method [\#1143](https://github.com/kivy/python-for-android/pull/1143) ([AndreMiras](https://github.com/AndreMiras)) - This current Twisted version actually runs! [\#1140](https://github.com/kivy/python-for-android/pull/1140) ([wexi](https://github.com/wexi)) @@ -1785,14 +2197,14 @@ - --presplash and --icon aren't mentioned in revamp docs [\#975](https://github.com/kivy/python-for-android/issues/975) - NDK automatic lookup tries to pick a tarball [\#972](https://github.com/kivy/python-for-android/issues/972) - Kivy is broken on recent master [\#970](https://github.com/kivy/python-for-android/issues/970) -- device doesn't go on sleep mode [\#969](https://github.com/kivy/python-for-android/issues/969) +- device doesnt go on sleep mode [\#969](https://github.com/kivy/python-for-android/issues/969) - The python2 build imports cython from the system python in /usr/lib/... [\#964](https://github.com/kivy/python-for-android/issues/964) - "Could not remove android presplash" if 'android' is not in requirements [\#963](https://github.com/kivy/python-for-android/issues/963) - "AndroidJoystick is not supported by your version of linux" confusing message in log [\#962](https://github.com/kivy/python-for-android/issues/962) - Could not ping localhost:5000 [\#960](https://github.com/kivy/python-for-android/issues/960) - Using pyjnius leads to crash \(sometimes?\) if app built by new toolchain [\#959](https://github.com/kivy/python-for-android/issues/959) - Android screen rotation is probably broken [\#955](https://github.com/kivy/python-for-android/issues/955) -- Compiling pyo with sdl is breaking ply / enaml [\#947](https://github.com/kivy/python-for-android/issues/947) +- Compling pyo with sdl is breaking ply / enaml [\#947](https://github.com/kivy/python-for-android/issues/947) - Access WiFi information? [\#940](https://github.com/kivy/python-for-android/issues/940) - p4a erroring on SSL connection [\#939](https://github.com/kivy/python-for-android/issues/939) - Compiling PIL seems to use pyconfig.h from the wrong directory [\#937](https://github.com/kivy/python-for-android/issues/937) @@ -1830,11 +2242,11 @@ - non debug apk? [\#844](https://github.com/kivy/python-for-android/issues/844) - Rotation Lock Ignored [\#842](https://github.com/kivy/python-for-android/issues/842) - Plyer GPS example works on android but not android\_new toolchain [\#833](https://github.com/kivy/python-for-android/issues/833) -- p4a create Error with openssl: start.c\:2\:20\: Python.h: No such file or directory [\#830](https://github.com/kivy/python-for-android/issues/830) +- p4a create Error with openssl: start.c:2:20: Python.h: No such file or directory [\#830](https://github.com/kivy/python-for-android/issues/830) - MD5sum - UnboundLocalError: current\_md5 referenced before assignment [\#828](https://github.com/kivy/python-for-android/issues/828) - Recipes are still not resolved properly sometimes [\#826](https://github.com/kivy/python-for-android/issues/826) - Failed to build Pillow-3.3.0 gcc: error: \_imaging.o: No such file or directory [\#823](https://github.com/kivy/python-for-android/issues/823) -- p4a create error: kivy/\_clock.pxd\:6\:4\: Executable statement not allowed here [\#822](https://github.com/kivy/python-for-android/issues/822) +- p4a create error: kivy/\_clock.pxd:6:4: Executable statement not allowed here [\#822](https://github.com/kivy/python-for-android/issues/822) - No such file or directory: ".../whitelist.txt" [\#821](https://github.com/kivy/python-for-android/issues/821) - Docs - connected toctrees, too deep? [\#820](https://github.com/kivy/python-for-android/issues/820) - Showcase with launcher [\#814](https://github.com/kivy/python-for-android/issues/814) @@ -1866,7 +2278,7 @@ - raise exc\_info\[0\], exc\_info\[1\], exc\_info\[2\] - Syntax Error [\#721](https://github.com/kivy/python-for-android/issues/721) - Some input files use or override a deprecated API. [\#719](https://github.com/kivy/python-for-android/issues/719) - Unexpected "malformed start tag" error with HTMLParser [\#715](https://github.com/kivy/python-for-android/issues/715) -- open\(\) built-in function don't work as expected [\#706](https://github.com/kivy/python-for-android/issues/706) +- open\(\) build-in function don't work as expected [\#706](https://github.com/kivy/python-for-android/issues/706) - Webview bootstrap. Where to start? \[$100\] [\#700](https://github.com/kivy/python-for-android/issues/700) - Back button doesn't work [\#699](https://github.com/kivy/python-for-android/issues/699) - FileNotFoundError '/bin/sh' with subprocess.py python3crystax [\#691](https://github.com/kivy/python-for-android/issues/691) @@ -1936,9 +2348,9 @@ - \[revamp\] Recipes can only depend on other recipes [\#449](https://github.com/kivy/python-for-android/issues/449) - \[revamp\] p4a silently fails if --private is not absolute [\#448](https://github.com/kivy/python-for-android/issues/448) - \[revamp\] Invalid syntax for python3 [\#444](https://github.com/kivy/python-for-android/issues/444) -- \[revamp\] toolchain.py ignores recipes with errors [\#440](https://github.com/kivy/python-for-android/issues/440) +- \[revamp\] toolchain.py ignores recipes with errrors [\#440](https://github.com/kivy/python-for-android/issues/440) - Error when trying to create an apk package with buildozer or with distribute.sh [\#435](https://github.com/kivy/python-for-android/issues/435) -- pylibpd fails to compile [\#434](https://github.com/kivy/python-for-android/issues/434) +- pylibpd failes to compile [\#434](https://github.com/kivy/python-for-android/issues/434) - \[revamp\] --android\_api is ignored on SDL2 bootstrap [\#425](https://github.com/kivy/python-for-android/issues/425) - OSError: \[Errno 2\] No such file or directory: '/home/username/code/kivy/examples/demo/touchtracer' [\#424](https://github.com/kivy/python-for-android/issues/424) - \[revamp\] - Darwin patches applied on Linux [\#423](https://github.com/kivy/python-for-android/issues/423) @@ -1975,7 +2387,7 @@ - pygame.display.set\_mode runs out of memory [\#331](https://github.com/kivy/python-for-android/issues/331) - Python Service multiple instances [\#329](https://github.com/kivy/python-for-android/issues/329) - Kivy Launcher should include Plyer [\#328](https://github.com/kivy/python-for-android/issues/328) -- Issue in Cython file compilation and building kivy.graphics.vertex\_instruction extensions [\#326](https://github.com/kivy/python-for-android/issues/326) +- Issue in Cython file compilation and building kivy.graphics.vertex\_instruction extentions [\#326](https://github.com/kivy/python-for-android/issues/326) - Failed Cython Compilation [\#325](https://github.com/kivy/python-for-android/issues/325) - Python3 Branch: jinja2 traceback on buildozer --verbose android debug [\#322](https://github.com/kivy/python-for-android/issues/322) - About ctypes [\#319](https://github.com/kivy/python-for-android/issues/319) @@ -1989,7 +2401,7 @@ - My `./distribute.sh` suddenly stop building today. [\#294](https://github.com/kivy/python-for-android/issues/294) - Create recipes for storm and psycopg2 [\#293](https://github.com/kivy/python-for-android/issues/293) - error in your VM Image after ./distribute.sh -m kivy [\#291](https://github.com/kivy/python-for-android/issues/291) -- Error in Apk process building [\#290](https://github.com/kivy/python-for-android/issues/290) +- Eror in Apk process building [\#290](https://github.com/kivy/python-for-android/issues/290) - IOError: \[Errno 2\] No usable temporary directory [\#289](https://github.com/kivy/python-for-android/issues/289) - Path commands on readme and official-website-toolchain don't seem to work [\#281](https://github.com/kivy/python-for-android/issues/281) - Twisted/recipe.sh can't find zope.interface [\#280](https://github.com/kivy/python-for-android/issues/280) @@ -2041,11 +2453,11 @@ - Kivy TextInput doesn't work with SwiftKey keyboard [\#184](https://github.com/kivy/python-for-android/issues/184) - Error in using debug flag, calling ANT debugger? [\#179](https://github.com/kivy/python-for-android/issues/179) - Update setuptools version [\#176](https://github.com/kivy/python-for-android/issues/176) -- Problems with distribute.sh [\#175](https://github.com/kivy/python-for-android/issues/175) +- Problems with distibute.sh [\#175](https://github.com/kivy/python-for-android/issues/175) - Rst editor crashing on android [\#174](https://github.com/kivy/python-for-android/issues/174) - Doubt about distribute.sh [\#173](https://github.com/kivy/python-for-android/issues/173) - Own Activities in AndroidManifest.xml [\#172](https://github.com/kivy/python-for-android/issues/172) -- Error to execute command ./distribute.sh -m "openssl pil kivy" [\#167](https://github.com/kivy/python-for-android/issues/167) +- Error to execute comand ./distribute.sh -m "openssl pil kivy" [\#167](https://github.com/kivy/python-for-android/issues/167) - keyboard stays on screen in android, after app exit [\#166](https://github.com/kivy/python-for-android/issues/166) - ffmpeg ndk r9 incompatibility [\#165](https://github.com/kivy/python-for-android/issues/165) - kivy touchtracer apk not running on emmulator [\#162](https://github.com/kivy/python-for-android/issues/162) @@ -2059,7 +2471,7 @@ - configure: error: C compiler cannot create executables [\#145](https://github.com/kivy/python-for-android/issues/145) - GCC 4.4.3 depreciated in android NDK [\#143](https://github.com/kivy/python-for-android/issues/143) - dlopen fail on android 4.3 [\#141](https://github.com/kivy/python-for-android/issues/141) -- new dependency ordering broke some usecases with buildozer [\#140](https://github.com/kivy/python-for-android/issues/140) +- new depencency ordering broke some usecases with buildozer [\#140](https://github.com/kivy/python-for-android/issues/140) - Android Keyboard information [\#139](https://github.com/kivy/python-for-android/issues/139) - Android keyboards do not recognize Password fields as secure passwords [\#138](https://github.com/kivy/python-for-android/issues/138) - kivy.network.urlrequest: No callback parameter: on\_failure [\#137](https://github.com/kivy/python-for-android/issues/137) @@ -2131,7 +2543,7 @@ - Error: Target id 'android-8' is not valid. [\#25](https://github.com/kivy/python-for-android/issues/25) - Build Error: "/usr/lib/libpython2.7.so: file not recognized: File format not recognized" [\#16](https://github.com/kivy/python-for-android/issues/16) - FFMpeg doesn't build [\#13](https://github.com/kivy/python-for-android/issues/13) -- Problem init environment [\#12](https://github.com/kivy/python-for-android/issues/12) +- Problem init enviroment [\#12](https://github.com/kivy/python-for-android/issues/12) - error when build the APK [\#10](https://github.com/kivy/python-for-android/issues/10) - arm-linux-androideabi-gcc: Internal error: Killed \(program cc1\) [\#9](https://github.com/kivy/python-for-android/issues/9) - Build: Pyrex error [\#7](https://github.com/kivy/python-for-android/issues/7) @@ -2160,7 +2572,7 @@ - Call avdmanager instead of android in the SDK [\#1057](https://github.com/kivy/python-for-android/pull/1057) ([inclement](https://github.com/inclement)) - Updated Kivy recipe to pull 1.10.0 [\#1048](https://github.com/kivy/python-for-android/pull/1048) ([inclement](https://github.com/inclement)) - \[Core\] Get the latest version of requests. [\#1045](https://github.com/kivy/python-for-android/pull/1045) ([hobbestigrou](https://github.com/hobbestigrou)) -- Recipe for websocket-client [\#1039](https://github.com/kivy/python-for-android/pull/1039) ([debauchery1st](https://github.com/debauchery1st)) +- Recipe for websocket-client [\#1039](https://github.com/kivy/python-for-android/pull/1039) ([trevorjamesmartin](https://github.com/trevorjamesmartin)) - Recipe updates and small fixes to build process [\#1034](https://github.com/kivy/python-for-android/pull/1034) ([bobatsar](https://github.com/bobatsar)) - Added warning about different path behavior in new toolchain service [\#1028](https://github.com/kivy/python-for-android/pull/1028) ([Bakterija](https://github.com/Bakterija)) - Recipe for Pymunk [\#1026](https://github.com/kivy/python-for-android/pull/1026) ([viblo](https://github.com/viblo)) @@ -2186,7 +2598,7 @@ - Update apis.rst [\#941](https://github.com/kivy/python-for-android/pull/941) ([codytrey](https://github.com/codytrey)) - Update recipes sqlite3 to 3.15.1 and apsw to 3.15.0-r1 both with FTS4 enabled [\#936](https://github.com/kivy/python-for-android/pull/936) ([brussee](https://github.com/brussee)) - Add remove\_presplash [\#930](https://github.com/kivy/python-for-android/pull/930) ([KeyWeeUsr](https://github.com/KeyWeeUsr)) -- Complete closure of the application with SDL2. [\#923](https://github.com/kivy/python-for-android/pull/923) ([dkrukouski](https://github.com/dkrukouski)) +- Complete closure of the application with SDL2. [\#923](https://github.com/kivy/python-for-android/pull/923) ([dkruk](https://github.com/dkruk)) - Testapp improvements [\#919](https://github.com/kivy/python-for-android/pull/919) ([inclement](https://github.com/inclement)) - Make boost recipe compatible with Google NDK 13.0 [\#916](https://github.com/kivy/python-for-android/pull/916) ([brussee](https://github.com/brussee)) - Completing md5sum comparison and download [\#915](https://github.com/kivy/python-for-android/pull/915) ([thopiekar](https://github.com/thopiekar)) @@ -2197,15 +2609,356 @@ - Added "presplash"\_color argument [\#906](https://github.com/kivy/python-for-android/pull/906) ([mrhdias](https://github.com/mrhdias)) - Added argument to set the loading screen background color [\#905](https://github.com/kivy/python-for-android/pull/905) ([mrhdias](https://github.com/mrhdias)) - Easy way to set the presplash background color [\#904](https://github.com/kivy/python-for-android/pull/904) ([mrhdias](https://github.com/mrhdias)) -- Allow installation on Windows [\#902](https://github.com/kivy/python-for-android/pull/902) ([ethanhs](https://github.com/ethanhs)) +- Allow installation on Windows [\#902](https://github.com/kivy/python-for-android/pull/902) ([emmatyping](https://github.com/emmatyping)) - Made clean-recipe-build delete dists [\#901](https://github.com/kivy/python-for-android/pull/901) ([inclement](https://github.com/inclement)) - Improved log for missing python modules [\#900](https://github.com/kivy/python-for-android/pull/900) ([inclement](https://github.com/inclement)) -- Added textinput scatter testapp [\#899](https://github.com/kivy/python-for-android/pull/899) ([inclement](https://github.com/inclement)) +- Addded textinput scatter testapp [\#899](https://github.com/kivy/python-for-android/pull/899) ([inclement](https://github.com/inclement)) - Allow list of permissions for bdist [\#898](https://github.com/kivy/python-for-android/pull/898) ([KeyWeeUsr](https://github.com/KeyWeeUsr)) - Fix bdistapk for launcher [\#896](https://github.com/kivy/python-for-android/pull/896) ([KeyWeeUsr](https://github.com/KeyWeeUsr)) - Added symlink\_java\_src dev option [\#894](https://github.com/kivy/python-for-android/pull/894) ([inclement](https://github.com/inclement)) +- New tests [\#893](https://github.com/kivy/python-for-android/pull/893) ([inclement](https://github.com/inclement)) - Port launcher to SDL2 bootstrap [\#891](https://github.com/kivy/python-for-android/pull/891) ([KeyWeeUsr](https://github.com/KeyWeeUsr)) - - - -\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* \ No newline at end of file +- Fix clean\_download\_cache, add deleting of separate packages [\#886](https://github.com/kivy/python-for-android/pull/886) ([KeyWeeUsr](https://github.com/KeyWeeUsr)) +- restore call to \_read\_configuration in Toolchain [\#875](https://github.com/kivy/python-for-android/pull/875) ([loulouxiv](https://github.com/loulouxiv)) +- fix issue with loading\_screen [\#869](https://github.com/kivy/python-for-android/pull/869) ([akshayaurora](https://github.com/akshayaurora)) +- libzmq recipe: do not hardcode g++ version [\#863](https://github.com/kivy/python-for-android/pull/863) ([chaubold](https://github.com/chaubold)) +- enable recipe package top-level directory names to be the same as the… [\#862](https://github.com/kivy/python-for-android/pull/862) ([cidermole](https://github.com/cidermole)) +- Check if bdist\_dir exists before removing [\#857](https://github.com/kivy/python-for-android/pull/857) ([nocarryr](https://github.com/nocarryr)) +- move app dir to `/app` allowing for re-installation/upda… [\#852](https://github.com/kivy/python-for-android/pull/852) ([akshayaurora](https://github.com/akshayaurora)) +- Boost recipe NDK12b compatibility [\#851](https://github.com/kivy/python-for-android/pull/851) ([brussee](https://github.com/brussee)) +- Improve service\_only bootstrap [\#845](https://github.com/kivy/python-for-android/pull/845) ([brussee](https://github.com/brussee)) +- rewrite netifaces recipe [\#841](https://github.com/kivy/python-for-android/pull/841) ([brussee](https://github.com/brussee)) +- introduce versioning for openssl [\#838](https://github.com/kivy/python-for-android/pull/838) ([brussee](https://github.com/brussee)) +- update openssl recipe to 1.0.2h [\#837](https://github.com/kivy/python-for-android/pull/837) ([brussee](https://github.com/brussee)) +- update cryptography to 1.4 [\#836](https://github.com/kivy/python-for-android/pull/836) ([brussee](https://github.com/brussee)) +- Workaround recursive link libtorrent.so [\#835](https://github.com/kivy/python-for-android/pull/835) ([brussee](https://github.com/brussee)) +- Coverage recipe [\#834](https://github.com/kivy/python-for-android/pull/834) ([brussee](https://github.com/brussee)) +- Add recipes for libgeos, pyproj, and shapely [\#831](https://github.com/kivy/python-for-android/pull/831) ([frmdstryr](https://github.com/frmdstryr)) +- Fix toctree [\#829](https://github.com/kivy/python-for-android/pull/829) ([KeyWeeUsr](https://github.com/KeyWeeUsr)) +- Add setuptools for kiwisolver [\#827](https://github.com/kivy/python-for-android/pull/827) ([frmdstryr](https://github.com/frmdstryr)) +- Added temporary fix for buildozer 0.32 [\#824](https://github.com/kivy/python-for-android/pull/824) ([inclement](https://github.com/inclement)) +- Fix build errors in docs [\#818](https://github.com/kivy/python-for-android/pull/818) ([KeyWeeUsr](https://github.com/KeyWeeUsr)) +- Add docs for launcher [\#817](https://github.com/kivy/python-for-android/pull/817) ([KeyWeeUsr](https://github.com/KeyWeeUsr)) +- Enable launcher for pygame [\#815](https://github.com/kivy/python-for-android/pull/815) ([KeyWeeUsr](https://github.com/KeyWeeUsr)) +- Fixed python2 with pygame bootstrap [\#811](https://github.com/kivy/python-for-android/pull/811) ([inclement](https://github.com/inclement)) +- Reworked argument handling [\#808](https://github.com/kivy/python-for-android/pull/808) ([inclement](https://github.com/inclement)) +- Add generic recipe for C++ extensions using STL and recipes for Enaml, Atom, Kiwisolver [\#805](https://github.com/kivy/python-for-android/pull/805) ([frmdstryr](https://github.com/frmdstryr)) +- fix autoconf libffi [\#800](https://github.com/kivy/python-for-android/pull/800) ([brussee](https://github.com/brussee)) +- Copylibs fix [\#799](https://github.com/kivy/python-for-android/pull/799) ([kollivier](https://github.com/kollivier)) +- Android Activities can resume with some or all of the UI object state… [\#798](https://github.com/kivy/python-for-android/pull/798) ([kollivier](https://github.com/kollivier)) +- Added python modules check [\#794](https://github.com/kivy/python-for-android/pull/794) ([inclement](https://github.com/inclement)) +- recipe libtribler split and add python dependencies [\#790](https://github.com/kivy/python-for-android/pull/790) ([brussee](https://github.com/brussee)) +- update recipe zope\_interface to 4.1.3 and remove tests [\#789](https://github.com/kivy/python-for-android/pull/789) ([brussee](https://github.com/brussee)) +- Netifaces's recipe \(mandatory for Python 2.7.11\) [\#783](https://github.com/kivy/python-for-android/pull/783) ([opacam](https://github.com/opacam)) +- Changed 'webviewjni' to 'genericndkbuild' [\#770](https://github.com/kivy/python-for-android/pull/770) ([inclement](https://github.com/inclement)) +- Use the org.kivy.android bootstrap for the webview backend as well. [\#769](https://github.com/kivy/python-for-android/pull/769) ([kollivier](https://github.com/kollivier)) +- fix jpeg build by merging libjpeg.a and libsimd.a [\#767](https://github.com/kivy/python-for-android/pull/767) ([kived](https://github.com/kived)) +- Add opencv recipe [\#765](https://github.com/kivy/python-for-android/pull/765) ([frmdstryr](https://github.com/frmdstryr)) +- Add distutils command for 'python setup.py apk' [\#764](https://github.com/kivy/python-for-android/pull/764) ([inclement](https://github.com/inclement)) +- Fixed error messages when build vars aren't set [\#762](https://github.com/kivy/python-for-android/pull/762) ([inclement](https://github.com/inclement)) +- Doc improvements [\#761](https://github.com/kivy/python-for-android/pull/761) ([inclement](https://github.com/inclement)) +- Added toolchain\_version initialisation [\#760](https://github.com/kivy/python-for-android/pull/760) ([inclement](https://github.com/inclement)) +- doc: add a getting started with the initial commands [\#757](https://github.com/kivy/python-for-android/pull/757) ([tito](https://github.com/tito)) +- Port storm and psycopg2 recipes from the old toolchain to the revamp. [\#754](https://github.com/kivy/python-for-android/pull/754) ([felipenehmi](https://github.com/felipenehmi)) +- Webview improvements [\#750](https://github.com/kivy/python-for-android/pull/750) ([bobatsar](https://github.com/bobatsar)) +- Various new recipes [\#749](https://github.com/kivy/python-for-android/pull/749) ([bobatsar](https://github.com/bobatsar)) +- add kivent recipes [\#743](https://github.com/kivy/python-for-android/pull/743) ([kived](https://github.com/kived)) +- throw error early if running in venv [\#742](https://github.com/kivy/python-for-android/pull/742) ([kived](https://github.com/kived)) +- gevent and greenlet recipes [\#737](https://github.com/kivy/python-for-android/pull/737) ([bobatsar](https://github.com/bobatsar)) +- add --color argument [\#736](https://github.com/kivy/python-for-android/pull/736) ([kived](https://github.com/kived)) +- call autoreconf before building libffi [\#735](https://github.com/kivy/python-for-android/pull/735) ([kived](https://github.com/kived)) +- minimal bootstrap for PythonService [\#729](https://github.com/kivy/python-for-android/pull/729) ([brussee](https://github.com/brussee)) +- Add webview bootstrap [\#728](https://github.com/kivy/python-for-android/pull/728) ([inclement](https://github.com/inclement)) +- boost recipe handle arch armeabi-v7a [\#727](https://github.com/kivy/python-for-android/pull/727) ([brussee](https://github.com/brussee)) +- add libtribler recipe [\#726](https://github.com/kivy/python-for-android/pull/726) ([brussee](https://github.com/brussee)) +- added ffmpeg recipe [\#725](https://github.com/kivy/python-for-android/pull/725) ([brussee](https://github.com/brussee)) +- add --storage-dir option [\#720](https://github.com/kivy/python-for-android/pull/720) ([kived](https://github.com/kived)) +- rewrite recipe and update cryptography to 1.3.1 [\#718](https://github.com/kivy/python-for-android/pull/718) ([brussee](https://github.com/brussee)) +- update m2crypto to 0.24.0 [\#717](https://github.com/kivy/python-for-android/pull/717) ([brussee](https://github.com/brussee)) +- update libtorrent to 1.0.9 [\#716](https://github.com/kivy/python-for-android/pull/716) ([brussee](https://github.com/brussee)) +- Enable snappy recipe for py-leveldb [\#714](https://github.com/kivy/python-for-android/pull/714) ([brussee](https://github.com/brussee)) +- update sdl2 to 2.0.4 [\#713](https://github.com/kivy/python-for-android/pull/713) ([brussee](https://github.com/brussee)) +- update ipaddress to 1.0.16 [\#712](https://github.com/kivy/python-for-android/pull/712) ([brussee](https://github.com/brussee)) +- update enum34 to 1.1.3 [\#711](https://github.com/kivy/python-for-android/pull/711) ([brussee](https://github.com/brussee)) +- update sdl2\_ttf to 2.0.14 [\#710](https://github.com/kivy/python-for-android/pull/710) ([brussee](https://github.com/brussee)) +- update sdl2\_mixer 2.0.1 [\#709](https://github.com/kivy/python-for-android/pull/709) ([brussee](https://github.com/brussee)) +- update sdl2\_image to 2.0.1 [\#708](https://github.com/kivy/python-for-android/pull/708) ([brussee](https://github.com/brussee)) +- Fix python\_recipe.from\_crystax [\#704](https://github.com/kivy/python-for-android/pull/704) ([brussee](https://github.com/brussee)) +- Bump colorama requirement to 0.3.3 [\#702](https://github.com/kivy/python-for-android/pull/702) ([kahowell](https://github.com/kahowell)) +- Add spine-cython recipe. [\#701](https://github.com/kivy/python-for-android/pull/701) ([pythonic64](https://github.com/pythonic64)) +- Added main.py existence check in both bootstraps [\#698](https://github.com/kivy/python-for-android/pull/698) ([inclement](https://github.com/inclement)) +- Fixed pygame bootstrap local.properties creation [\#697](https://github.com/kivy/python-for-android/pull/697) ([inclement](https://github.com/inclement)) +- Added Service doc page [\#695](https://github.com/kivy/python-for-android/pull/695) ([inclement](https://github.com/inclement)) +- Let tar automatically recognize compression format [\#685](https://github.com/kivy/python-for-android/pull/685) ([brussee](https://github.com/brussee)) +- Fixed : alignment in instructions [\#683](https://github.com/kivy/python-for-android/pull/683) ([miohtama](https://github.com/miohtama)) +- Window option for SDL2 bootstrap [\#682](https://github.com/kivy/python-for-android/pull/682) ([pythonic64](https://github.com/pythonic64)) +- add release builds and apk signing [\#680](https://github.com/kivy/python-for-android/pull/680) ([kived](https://github.com/kived)) +- update cryptography to 1.2.3 [\#679](https://github.com/kivy/python-for-android/pull/679) ([kived](https://github.com/kived)) +- Python recipes CherryPy LibNaCl Requests FeedParser Decorator [\#676](https://github.com/kivy/python-for-android/pull/676) ([brussee](https://github.com/brussee)) +- Update openssl to 1.0.2g [\#675](https://github.com/kivy/python-for-android/pull/675) ([brussee](https://github.com/brussee)) +- sqlite3 for python2 [\#672](https://github.com/kivy/python-for-android/pull/672) ([brussee](https://github.com/brussee)) +- Minor refactor PyLevelDB recipe [\#671](https://github.com/kivy/python-for-android/pull/671) ([brussee](https://github.com/brussee)) +- Apsw recipe [\#665](https://github.com/kivy/python-for-android/pull/665) ([brussee](https://github.com/brussee)) +- OpenSSL for LibTorrent optional dependency [\#663](https://github.com/kivy/python-for-android/pull/663) ([brussee](https://github.com/brussee)) +- install .jam config files for recipes; [\#662](https://github.com/kivy/python-for-android/pull/662) ([brussee](https://github.com/brussee)) +- Added LevelDB recipe including snappy [\#660](https://github.com/kivy/python-for-android/pull/660) ([brussee](https://github.com/brussee)) +- fix android webbrowser module to work with both sdl2 and pygame [\#655](https://github.com/kivy/python-for-android/pull/655) ([akshayaurora](https://github.com/akshayaurora)) +- Added M2Crypto recipe [\#652](https://github.com/kivy/python-for-android/pull/652) ([brussee](https://github.com/brussee)) +- load python lib before main [\#649](https://github.com/kivy/python-for-android/pull/649) ([kived](https://github.com/kived)) +- Make unistr available in logger [\#647](https://github.com/kivy/python-for-android/pull/647) ([Konubinix](https://github.com/Konubinix)) +- Add ndg.httpsclient recipe [\#644](https://github.com/kivy/python-for-android/pull/644) ([kmonson](https://github.com/kmonson)) +- add sticky services, auto-restart services, fix foreground option [\#643](https://github.com/kivy/python-for-android/pull/643) ([kived](https://github.com/kived)) +- remove getenv.patch from pyjnius recipe [\#642](https://github.com/kivy/python-for-android/pull/642) ([kived](https://github.com/kived)) +- Fixed some bugs with recipe graph calculations [\#641](https://github.com/kivy/python-for-android/pull/641) ([inclement](https://github.com/inclement)) +- Added error when api and arch conflict [\#640](https://github.com/kivy/python-for-android/pull/640) ([inclement](https://github.com/inclement)) +- Made build fail if no cython found [\#639](https://github.com/kivy/python-for-android/pull/639) ([inclement](https://github.com/inclement)) +- stop service on interpreter exit [\#638](https://github.com/kivy/python-for-android/pull/638) ([kived](https://github.com/kived)) +- add libtorrent recipe [\#637](https://github.com/kivy/python-for-android/pull/637) ([brussee](https://github.com/brussee)) +- Fixed missing else statement in for loop, allowing systems where cyth… [\#634](https://github.com/kivy/python-for-android/pull/634) ([mixedCase](https://github.com/mixedCase)) +- Remove print from cryptography recipe. [\#630](https://github.com/kivy/python-for-android/pull/630) ([Doberman4ik](https://github.com/Doberman4ik)) +- add foreground option to segregated services [\#628](https://github.com/kivy/python-for-android/pull/628) ([kived](https://github.com/kived)) +- Use darwin patches [\#626](https://github.com/kivy/python-for-android/pull/626) ([cbenhagen](https://github.com/cbenhagen)) +- Do not recommend kivysdl2 recipe [\#621](https://github.com/kivy/python-for-android/pull/621) ([cbenhagen](https://github.com/cbenhagen)) +- fix missing mk files in installed p4a [\#618](https://github.com/kivy/python-for-android/pull/618) ([kived](https://github.com/kived)) +- Update OpenSSL recipe & patch [\#615](https://github.com/kivy/python-for-android/pull/615) ([brussee](https://github.com/brussee)) +- fix more path arguments [\#612](https://github.com/kivy/python-for-android/pull/612) ([kived](https://github.com/kived)) +- sdl2 bootstrap: implement --add-source argument [\#611](https://github.com/kivy/python-for-android/pull/611) ([kived](https://github.com/kived)) +- use service name as log tag [\#609](https://github.com/kivy/python-for-android/pull/609) ([kived](https://github.com/kived)) +- sdl2: add support to start multiple services [\#608](https://github.com/kivy/python-for-android/pull/608) ([tito](https://github.com/tito)) +- SDL2: implement support for loadingscreen [\#605](https://github.com/kivy/python-for-android/pull/605) ([tito](https://github.com/tito)) +- logger: fix encoding issue for python 2 only [\#604](https://github.com/kivy/python-for-android/pull/604) ([tito](https://github.com/tito)) +- Fixes empty argument to mv -t [\#603](https://github.com/kivy/python-for-android/pull/603) ([tito](https://github.com/tito)) +- Add zeroconf and netifaces recipes [\#602](https://github.com/kivy/python-for-android/pull/602) ([tito](https://github.com/tito)) +- Parse and export in environ requirements version [\#601](https://github.com/kivy/python-for-android/pull/601) ([tito](https://github.com/tito)) +- add missing arm64 include stub [\#600](https://github.com/kivy/python-for-android/pull/600) ([kived](https://github.com/kived)) +- add aarch64/arm64-v8a arch [\#599](https://github.com/kivy/python-for-android/pull/599) ([kived](https://github.com/kived)) +- fix mysqldb patching [\#597](https://github.com/kivy/python-for-android/pull/597) ([kived](https://github.com/kived)) +- fix library include path [\#596](https://github.com/kivy/python-for-android/pull/596) ([kived](https://github.com/kived)) +- fix site packages [\#595](https://github.com/kivy/python-for-android/pull/595) ([kived](https://github.com/kived)) +- add missing files to setup.py [\#592](https://github.com/kivy/python-for-android/pull/592) ([kived](https://github.com/kived)) +- add babel and pytz recipes [\#588](https://github.com/kivy/python-for-android/pull/588) ([kived](https://github.com/kived)) +- add mysqldb/libmysqlclient recipes [\#587](https://github.com/kivy/python-for-android/pull/587) ([kived](https://github.com/kived)) +- add pil/png/jpeg recipes [\#586](https://github.com/kivy/python-for-android/pull/586) ([kived](https://github.com/kived)) +- add openssl support [\#585](https://github.com/kivy/python-for-android/pull/585) ([kived](https://github.com/kived)) +- only try to load libpymodules.so once [\#584](https://github.com/kivy/python-for-android/pull/584) ([kived](https://github.com/kived)) +- recipe and build improvements [\#583](https://github.com/kivy/python-for-android/pull/583) ([kived](https://github.com/kived)) +- ignore idea files [\#582](https://github.com/kivy/python-for-android/pull/582) ([kived](https://github.com/kived)) +- misc recipe fixes [\#581](https://github.com/kivy/python-for-android/pull/581) ([kived](https://github.com/kived)) +- fix root extraction from zip [\#580](https://github.com/kivy/python-for-android/pull/580) ([kived](https://github.com/kived)) +- add basic env-based overrides for recipe version and url [\#579](https://github.com/kivy/python-for-android/pull/579) ([kived](https://github.com/kived)) +- Enable services with SDL2 bootstrap [\#578](https://github.com/kivy/python-for-android/pull/578) ([kived](https://github.com/kived)) +- add option to not include cflags in cc [\#577](https://github.com/kivy/python-for-android/pull/577) ([kived](https://github.com/kived)) +- alternative version string to download from sourceforge; [\#575](https://github.com/kivy/python-for-android/pull/575) ([brussee](https://github.com/brussee)) +- sdl2/bootstrap: add --add-jar and --intent-filters support [\#571](https://github.com/kivy/python-for-android/pull/571) ([tito](https://github.com/tito)) +- Fix logger stdout/stderr encoding [\#570](https://github.com/kivy/python-for-android/pull/570) ([tito](https://github.com/tito)) +- sdl2/bootstrap: Restore GenericBroadcastReceiver/GenericBroadcastRece… [\#569](https://github.com/kivy/python-for-android/pull/569) ([tito](https://github.com/tito)) +- sdl2/bootstrap: add support for onActivityResult and onNewIntent [\#568](https://github.com/kivy/python-for-android/pull/568) ([tito](https://github.com/tito)) +- Fix -m compileall [\#566](https://github.com/kivy/python-for-android/pull/566) ([tito](https://github.com/tito)) +- rename sdl2 templates [\#564](https://github.com/kivy/python-for-android/pull/564) ([kived](https://github.com/kived)) +- make org.renpy.android.PythonActivity a proxy for org.kivy.android.Py… [\#563](https://github.com/kivy/python-for-android/pull/563) ([kived](https://github.com/kived)) +- update android package for sdl2 bootstrap [\#562](https://github.com/kivy/python-for-android/pull/562) ([kived](https://github.com/kived)) +- remove build dir before copying for IncludedFilesBehaviour [\#561](https://github.com/kivy/python-for-android/pull/561) ([kived](https://github.com/kived)) +- fix prebuild for armeabi-v7a, make missing recipe error more informative [\#560](https://github.com/kivy/python-for-android/pull/560) ([kived](https://github.com/kived)) +- add python\_depends to recipe [\#559](https://github.com/kivy/python-for-android/pull/559) ([kived](https://github.com/kived)) +- fix logger unicode errors on py2 [\#558](https://github.com/kivy/python-for-android/pull/558) ([kived](https://github.com/kived)) +- ignore deps when installing via pip [\#557](https://github.com/kivy/python-for-android/pull/557) ([kived](https://github.com/kived)) +- look for eggs when checking for packages [\#556](https://github.com/kivy/python-for-android/pull/556) ([kived](https://github.com/kived)) +- add copy libs option [\#555](https://github.com/kivy/python-for-android/pull/555) ([kived](https://github.com/kived)) +- always parse dist args [\#554](https://github.com/kivy/python-for-android/pull/554) ([kived](https://github.com/kived)) +- support crystax ndk [\#553](https://github.com/kivy/python-for-android/pull/553) ([kived](https://github.com/kived)) +- add custom blacklist/whitelist support to sdl2 bootstrap [\#552](https://github.com/kivy/python-for-android/pull/552) ([kived](https://github.com/kived)) +- added recipe libsodium [\#549](https://github.com/kivy/python-for-android/pull/549) ([brussee](https://github.com/brussee)) +- Add python3 support [\#546](https://github.com/kivy/python-for-android/pull/546) ([inclement](https://github.com/inclement)) +- use ccache for cross compilation [\#543](https://github.com/kivy/python-for-android/pull/543) ([kived](https://github.com/kived)) +- Various fixes [\#539](https://github.com/kivy/python-for-android/pull/539) ([kived](https://github.com/kived)) +- allow git clone over SSH and HTTP\(S\) [\#538](https://github.com/kivy/python-for-android/pull/538) ([kived](https://github.com/kived)) +- add custom recipe support \[needs py3 testing\] [\#537](https://github.com/kivy/python-for-android/pull/537) ([kived](https://github.com/kived)) +- add sqlalchemy recipe [\#536](https://github.com/kivy/python-for-android/pull/536) ([kived](https://github.com/kived)) +- add pyusb recipe [\#535](https://github.com/kivy/python-for-android/pull/535) ([kived](https://github.com/kived)) +- add evdev recipe [\#534](https://github.com/kivy/python-for-android/pull/534) ([kived](https://github.com/kived)) +- add cdecimal recipe [\#533](https://github.com/kivy/python-for-android/pull/533) ([kived](https://github.com/kived)) +- allow using a command other than "build\_ext", fix some env usage [\#532](https://github.com/kivy/python-for-android/pull/532) ([kived](https://github.com/kived)) +- add NDKRecipe, rename old to BootstrapNDKRecipe [\#531](https://github.com/kivy/python-for-android/pull/531) ([kived](https://github.com/kived)) +- use version for git urls [\#530](https://github.com/kivy/python-for-android/pull/530) ([kived](https://github.com/kived)) +- fix pymodules install [\#529](https://github.com/kivy/python-for-android/pull/529) ([kived](https://github.com/kived)) +- add missing code from previous pr [\#527](https://github.com/kivy/python-for-android/pull/527) ([kived](https://github.com/kived)) +- Split toolchain.py into separate modules [\#526](https://github.com/kivy/python-for-android/pull/526) ([inclement](https://github.com/inclement)) +- pythonpath and setup.py build fixes [\#525](https://github.com/kivy/python-for-android/pull/525) ([kived](https://github.com/kived)) +- Improved recipe output [\#524](https://github.com/kivy/python-for-android/pull/524) ([inclement](https://github.com/inclement)) +- fix typo in pyjnius recipe [\#523](https://github.com/kivy/python-for-android/pull/523) ([kived](https://github.com/kived)) +- easier patching for recipes [\#522](https://github.com/kivy/python-for-android/pull/522) ([kived](https://github.com/kived)) +- Fix for \#515 - dependency graph issue [\#521](https://github.com/kivy/python-for-android/pull/521) ([JonAnCla](https://github.com/JonAnCla)) +- fix root directory for tgz extraction [\#519](https://github.com/kivy/python-for-android/pull/519) ([kived](https://github.com/kived)) +- show full output from failed commands [\#518](https://github.com/kivy/python-for-android/pull/518) ([kived](https://github.com/kived)) +- fix hard coded python2 path in sdl2 Android.mk [\#517](https://github.com/kivy/python-for-android/pull/517) ([kived](https://github.com/kived)) +- fix pycrypto apply\_patch error [\#514](https://github.com/kivy/python-for-android/pull/514) ([kived](https://github.com/kived)) +- add new error message and improve existing [\#513](https://github.com/kivy/python-for-android/pull/513) ([kived](https://github.com/kived)) +- Arch support [\#510](https://github.com/kivy/python-for-android/pull/510) ([inclement](https://github.com/inclement)) +- Added audiostream recipe [\#508](https://github.com/kivy/python-for-android/pull/508) ([JonAnCla](https://github.com/JonAnCla)) +- Fixed use of non-existent variable "Fore" [\#507](https://github.com/kivy/python-for-android/pull/507) ([JonAnCla](https://github.com/JonAnCla)) +- Update OpenSSL to 1.0.2e [\#506](https://github.com/kivy/python-for-android/pull/506) ([cbenhagen](https://github.com/cbenhagen)) +- cosmetic: toolchain logs improved [\#505](https://github.com/kivy/python-for-android/pull/505) ([ibobalo](https://github.com/ibobalo)) +- Fixing missing Colo [\#502](https://github.com/kivy/python-for-android/pull/502) ([dl1ksv](https://github.com/dl1ksv)) +- Fixing unicode error [\#501](https://github.com/kivy/python-for-android/pull/501) ([dl1ksv](https://github.com/dl1ksv)) +- Fix boolean options [\#500](https://github.com/kivy/python-for-android/pull/500) ([denys-duchier](https://github.com/denys-duchier)) +- Update bootstraps.rst [\#498](https://github.com/kivy/python-for-android/pull/498) ([go-bears](https://github.com/go-bears)) +- Update index.rst [\#497](https://github.com/kivy/python-for-android/pull/497) ([go-bears](https://github.com/go-bears)) +- send notifications to stderr. use colorization on stdout or stderr only if a tty. [\#495](https://github.com/kivy/python-for-android/pull/495) ([denys-duchier](https://github.com/denys-duchier)) +- suppress colorization if stdout is not a tty [\#494](https://github.com/kivy/python-for-android/pull/494) ([denys-duchier](https://github.com/denys-duchier)) +- Fixing compiler problem \( parse tuples \) [\#493](https://github.com/kivy/python-for-android/pull/493) ([dl1ksv](https://github.com/dl1ksv)) +- Fix keyboard height issue [\#483](https://github.com/kivy/python-for-android/pull/483) ([dylanjeffers](https://github.com/dylanjeffers)) +- VLC recepie, sdl2 bootstaps improvements [\#480](https://github.com/kivy/python-for-android/pull/480) ([ibobalo](https://github.com/ibobalo)) +- Update toolchain.py [\#471](https://github.com/kivy/python-for-android/pull/471) ([ibobalo](https://github.com/ibobalo)) +- Update toolchain.py [\#470](https://github.com/kivy/python-for-android/pull/470) ([ibobalo](https://github.com/ibobalo)) +- Replace the p4a master with the revamp [\#463](https://github.com/kivy/python-for-android/pull/463) ([inclement](https://github.com/inclement)) +- Update NDK download link as NumPy can't be built using NDK r8c [\#429](https://github.com/kivy/python-for-android/pull/429) ([asmfreak](https://github.com/asmfreak)) +- Converted --minsdk option input to int [\#428](https://github.com/kivy/python-for-android/pull/428) ([inclement](https://github.com/inclement)) +- README: reStructuredText highlighting / indentation touchups [\#426](https://github.com/kivy/python-for-android/pull/426) ([tony](https://github.com/tony)) +- Replace hardcoded "-jX" for make [\#420](https://github.com/kivy/python-for-android/pull/420) ([thopiekar](https://github.com/thopiekar)) +- Fixed version number logic for non-int versions [\#416](https://github.com/kivy/python-for-android/pull/416) ([Cheaterman](https://github.com/Cheaterman)) +- Fix crash on presplash screen if back button pressed [\#412](https://github.com/kivy/python-for-android/pull/412) ([Mystic-Mirage](https://github.com/Mystic-Mirage)) +- Enabling android-21 builds [\#410](https://github.com/kivy/python-for-android/pull/410) ([dl1ksv](https://github.com/dl1ksv)) +- Update paramiko recipe [\#404](https://github.com/kivy/python-for-android/pull/404) ([extra84](https://github.com/extra84)) +- add evdev recipe [\#402](https://github.com/kivy/python-for-android/pull/402) ([kived](https://github.com/kived)) +- Updated Twisted and Zope recipes [\#398](https://github.com/kivy/python-for-android/pull/398) ([torfinnberset](https://github.com/torfinnberset)) +- update openssl version to 1.0.2c [\#396](https://github.com/kivy/python-for-android/pull/396) ([cbenhagen](https://github.com/cbenhagen)) +- use $VERSION\_apsw instead of hardcoding version number [\#395](https://github.com/kivy/python-for-android/pull/395) ([mathewvermeer](https://github.com/mathewvermeer)) +- update to openssl version 1.0.2b [\#394](https://github.com/kivy/python-for-android/pull/394) ([mathewvermeer](https://github.com/mathewvermeer)) +- update to zope.interface version 4.1.2 [\#393](https://github.com/kivy/python-for-android/pull/393) ([mathewvermeer](https://github.com/mathewvermeer)) +- update netifaces to version 0.10.4 [\#392](https://github.com/kivy/python-for-android/pull/392) ([mathewvermeer](https://github.com/mathewvermeer)) +- add cherrypy recipe [\#391](https://github.com/kivy/python-for-android/pull/391) ([mathewvermeer](https://github.com/mathewvermeer)) +- add leveldb and plyvel recipes [\#390](https://github.com/kivy/python-for-android/pull/390) ([mathewvermeer](https://github.com/mathewvermeer)) +- add boost & libtorrent recipes [\#389](https://github.com/kivy/python-for-android/pull/389) ([mathewvermeer](https://github.com/mathewvermeer)) +- Fixed small documentation typo [\#386](https://github.com/kivy/python-for-android/pull/386) ([rdoursenaud](https://github.com/rdoursenaud)) +- add libsodium recipe [\#385](https://github.com/kivy/python-for-android/pull/385) ([mathewvermeer](https://github.com/mathewvermeer)) +- Make sure `keyboard_height` is triggered while being dismissed. [\#383](https://github.com/kivy/python-for-android/pull/383) ([akshayaurora](https://github.com/akshayaurora)) +- fix rotation bug with AndroidManifest.xml generation [\#382](https://github.com/kivy/python-for-android/pull/382) ([kived](https://github.com/kived)) +- fix ctypes build errors [\#375](https://github.com/kivy/python-for-android/pull/375) ([kived](https://github.com/kived)) +- switch to faster jpeg-turbo [\#373](https://github.com/kivy/python-for-android/pull/373) ([akshayaurora](https://github.com/akshayaurora)) +- Recipe for MIDI streaming [\#370](https://github.com/kivy/python-for-android/pull/370) ([b3b](https://github.com/b3b)) +- Recipes for zeroconf and six [\#368](https://github.com/kivy/python-for-android/pull/368) ([artfwo](https://github.com/artfwo)) +- added recipe for bidi \(bi-directional layout implementation\) [\#365](https://github.com/kivy/python-for-android/pull/365) ([Gillu13](https://github.com/Gillu13)) +- for some python3 compatibility [\#361](https://github.com/kivy/python-for-android/pull/361) ([a358003542](https://github.com/a358003542)) +- use listener to respond to keyboard height changes [\#360](https://github.com/kivy/python-for-android/pull/360) ([kived](https://github.com/kived)) +- bump numpy to 1.9.2 [\#356](https://github.com/kivy/python-for-android/pull/356) ([cbenhagen](https://github.com/cbenhagen)) +- fix manifest\_extra [\#354](https://github.com/kivy/python-for-android/pull/354) ([cbenhagen](https://github.com/cbenhagen)) +- reciepes for freetype and harfbuzz [\#351](https://github.com/kivy/python-for-android/pull/351) ([olymk2](https://github.com/olymk2)) +- Revert "fix mktemp usage for OS X" [\#349](https://github.com/kivy/python-for-android/pull/349) ([kived](https://github.com/kived)) +- make get\_keyboard\_height more dynamic [\#347](https://github.com/kivy/python-for-android/pull/347) ([denys-duchier](https://github.com/denys-duchier)) +- check the calculated NDK platform path for validity [\#345](https://github.com/kivy/python-for-android/pull/345) ([r1chardj0n3s](https://github.com/r1chardj0n3s)) +- fix mktemp usage for OS X [\#344](https://github.com/kivy/python-for-android/pull/344) ([r1chardj0n3s](https://github.com/r1chardj0n3s)) +- Feature/enable ctypes [\#343](https://github.com/kivy/python-for-android/pull/343) ([olymk2](https://github.com/olymk2)) +- Fix issue \#337 [\#338](https://github.com/kivy/python-for-android/pull/338) ([jxai](https://github.com/jxai)) +- Apply ignore\_path filter to private data [\#336](https://github.com/kivy/python-for-android/pull/336) ([emanuele-f](https://github.com/emanuele-f)) +- Add warning and description for P4A in a venv... [\#334](https://github.com/kivy/python-for-android/pull/334) ([FeralBytes](https://github.com/FeralBytes)) +- Recipe for OpenCV [\#327](https://github.com/kivy/python-for-android/pull/327) ([jxai](https://github.com/jxai)) +- Corrected spelling of "environment" [\#324](https://github.com/kivy/python-for-android/pull/324) ([intchanter](https://github.com/intchanter)) +- save and restore environment when running recipe functions [\#320](https://github.com/kivy/python-for-android/pull/320) ([kived](https://github.com/kived)) +- fix android package for services [\#317](https://github.com/kivy/python-for-android/pull/317) ([kived](https://github.com/kived)) +- Don't search for the pip command [\#316](https://github.com/kivy/python-for-android/pull/316) ([mmariani](https://github.com/mmariani)) +- removed reference to ARM from audiostream and pyparsing recipes [\#315](https://github.com/kivy/python-for-android/pull/315) ([mmariani](https://github.com/mmariani)) +- actually raise an error if virtualenv or pip are missing [\#314](https://github.com/kivy/python-for-android/pull/314) ([mmariani](https://github.com/mmariani)) +- libyaml + pyyaml [\#313](https://github.com/kivy/python-for-android/pull/313) ([mmariani](https://github.com/mmariani)) +- provide api versions in android package [\#304](https://github.com/kivy/python-for-android/pull/304) ([kived](https://github.com/kived)) +- Documentation grammar and spelling fixes [\#303](https://github.com/kivy/python-for-android/pull/303) ([mivade](https://github.com/mivade)) +- Fixes for \#297 [\#298](https://github.com/kivy/python-for-android/pull/298) ([tito](https://github.com/tito)) +- Autodetect cython2 version [\#296](https://github.com/kivy/python-for-android/pull/296) ([rdoursenaud](https://github.com/rdoursenaud)) +- add recipe for cprotobuf [\#295](https://github.com/kivy/python-for-android/pull/295) ([yihuang](https://github.com/yihuang)) +- Add a storm/psycopg2 recipe [\#292](https://github.com/kivy/python-for-android/pull/292) ([romaia](https://github.com/romaia)) +- Added protobuf recipe [\#287](https://github.com/kivy/python-for-android/pull/287) ([minou](https://github.com/minou)) +- Update usage.rst [\#285](https://github.com/kivy/python-for-android/pull/285) ([jdruiter](https://github.com/jdruiter)) +- Update prerequisites.rst [\#284](https://github.com/kivy/python-for-android/pull/284) ([jdruiter](https://github.com/jdruiter)) +- Update toolchain.rst [\#283](https://github.com/kivy/python-for-android/pull/283) ([jdruiter](https://github.com/jdruiter)) +- fix twisted recipe [\#282](https://github.com/kivy/python-for-android/pull/282) ([kived](https://github.com/kived)) +- Add support for NDK r10 version [\#274](https://github.com/kivy/python-for-android/pull/274) ([rakesh-sankar](https://github.com/rakesh-sankar)) +- make private service work \(but only if there is no public folder\) [\#273](https://github.com/kivy/python-for-android/pull/273) ([kived](https://github.com/kived)) +- move parts of get\_keyboard\_height to global [\#272](https://github.com/kivy/python-for-android/pull/272) ([chozabu](https://github.com/chozabu)) +- Added support for setting string resources in generated strings.xml [\#266](https://github.com/kivy/python-for-android/pull/266) ([excessivedemon](https://github.com/excessivedemon)) +- Add LinuxMint [\#259](https://github.com/kivy/python-for-android/pull/259) ([mariogrip](https://github.com/mariogrip)) +- skip biglink for jb 4.3 [\#258](https://github.com/kivy/python-for-android/pull/258) ([kived](https://github.com/kived)) +- Added 4 recipes and updated Twisted [\#254](https://github.com/kivy/python-for-android/pull/254) ([lfdversluis](https://github.com/lfdversluis)) +- Fix spelling [\#253](https://github.com/kivy/python-for-android/pull/253) ([trivedigaurav](https://github.com/trivedigaurav)) +- Recipe for Polygon [\#252](https://github.com/kivy/python-for-android/pull/252) ([chozabu](https://github.com/chozabu)) +- Fixed kivy recipe to work on repeated runs with P4A\_kivy\_DIR [\#251](https://github.com/kivy/python-for-android/pull/251) ([inclement](https://github.com/inclement)) +- Fix ANDROIDAPI [\#250](https://github.com/kivy/python-for-android/pull/250) ([knappador](https://github.com/knappador)) +- fix pycrypto recipe; add recipe for apsw [\#248](https://github.com/kivy/python-for-android/pull/248) ([wjanssen](https://github.com/wjanssen)) +- Fixed a tiny misspelling. [\#246](https://github.com/kivy/python-for-android/pull/246) ([erikdsjostrom](https://github.com/erikdsjostrom)) +- Fixed a tiny grammatical error [\#245](https://github.com/kivy/python-for-android/pull/245) ([erikdsjostrom](https://github.com/erikdsjostrom)) +- Added psutil recipe [\#243](https://github.com/kivy/python-for-android/pull/243) ([devpack](https://github.com/devpack)) +- Update examples.rst [\#240](https://github.com/kivy/python-for-android/pull/240) ([trivedigaurav](https://github.com/trivedigaurav)) +- heartbleed fix [\#230](https://github.com/kivy/python-for-android/pull/230) ([cbenhagen](https://github.com/cbenhagen)) +- Pep8 fixes for build.py [\#224](https://github.com/kivy/python-for-android/pull/224) ([inclement](https://github.com/inclement)) +- fix blacklist comment bug and add whitelist [\#219](https://github.com/kivy/python-for-android/pull/219) ([kived](https://github.com/kived)) +- fix service handling [\#218](https://github.com/kivy/python-for-android/pull/218) ([kived](https://github.com/kived)) +- comment out the functions/declarations that are greater than API9 [\#214](https://github.com/kivy/python-for-android/pull/214) ([akshayaurora](https://github.com/akshayaurora)) +- Repeatable and prebuild-worthy igraph recipe [\#206](https://github.com/kivy/python-for-android/pull/206) ([clayote](https://github.com/clayote)) +- Introduce method `get_keyboard_height` that returns current softkeyboard [\#205](https://github.com/kivy/python-for-android/pull/205) ([akshayaurora](https://github.com/akshayaurora)) +- fixes to support swiftkey [\#204](https://github.com/kivy/python-for-android/pull/204) ([akshayaurora](https://github.com/akshayaurora)) +- Django recipe [\#203](https://github.com/kivy/python-for-android/pull/203) ([blagarde](https://github.com/blagarde)) +- Added more robust check for pip and virtualenv [\#201](https://github.com/kivy/python-for-android/pull/201) ([inclement](https://github.com/inclement)) +- improve voiceinput handeling [\#194](https://github.com/kivy/python-for-android/pull/194) ([akshayaurora](https://github.com/akshayaurora)) +- remove "and" from dependencies for 64bit [\#193](https://github.com/kivy/python-for-android/pull/193) ([zeimusu](https://github.com/zeimusu)) +- \[FIX\] Launcher APK does not enable PythonService [\#192](https://github.com/kivy/python-for-android/pull/192) ([alanjds](https://github.com/alanjds)) +- Custom actions and categories for BroadcastReceiver [\#189](https://github.com/kivy/python-for-android/pull/189) ([alanjds](https://github.com/alanjds)) +- FIX: Typos and style details [\#183](https://github.com/kivy/python-for-android/pull/183) ([blagarde](https://github.com/blagarde)) +- Fix UnicodeDecodeError on build.py [\#180](https://github.com/kivy/python-for-android/pull/180) ([satels](https://github.com/satels)) +- fix keyboard issues with kitkat and stock keyboard [\#178](https://github.com/kivy/python-for-android/pull/178) ([akshayaurora](https://github.com/akshayaurora)) +- Fix bug in igraph recipe [\#177](https://github.com/kivy/python-for-android/pull/177) ([clayote](https://github.com/clayote)) +- recipes for igraph, a hi-performance library of graph algorithms [\#171](https://github.com/kivy/python-for-android/pull/171) ([clayote](https://github.com/clayote)) +- r9 fix [\#161](https://github.com/kivy/python-for-android/pull/161) ([akshayaurora](https://github.com/akshayaurora)) +- - added pyparsing recipe [\#160](https://github.com/kivy/python-for-android/pull/160) ([aliceinwire](https://github.com/aliceinwire)) +- Honor `input_type` Textinput property to choose the type of keyboard [\#158](https://github.com/kivy/python-for-android/pull/158) ([akshayaurora](https://github.com/akshayaurora)) +- Revert "fix touch offset in window mode" \(needs testing\) [\#154](https://github.com/kivy/python-for-android/pull/154) ([inclement](https://github.com/inclement)) +- Replaced 'python' with '$PYTHON' for compatibility [\#152](https://github.com/kivy/python-for-android/pull/152) ([inclement](https://github.com/inclement)) +- created sqlalchemy recipe for compiling its C extension in ARM [\#151](https://github.com/kivy/python-for-android/pull/151) ([eulerreich](https://github.com/eulerreich)) +- added msgpack recipe [\#147](https://github.com/kivy/python-for-android/pull/147) ([Roger](https://github.com/Roger)) +- Add gevent recipe [\#146](https://github.com/kivy/python-for-android/pull/146) ([Roger](https://github.com/Roger)) +- build.py: Fail when ant process fails [\#135](https://github.com/kivy/python-for-android/pull/135) ([encukou](https://github.com/encukou)) +- WIP: Add depsolving utility [\#134](https://github.com/kivy/python-for-android/pull/134) ([encukou](https://github.com/encukou)) +- Fixed recipe for pylibpd [\#128](https://github.com/kivy/python-for-android/pull/128) ([brousch](https://github.com/brousch)) +- Added recipe for paramiko [\#125](https://github.com/kivy/python-for-android/pull/125) ([vimalkvn](https://github.com/vimalkvn)) +- Add apt-get install libsqlite3-dev to FAQ on sqlite3 [\#124](https://github.com/kivy/python-for-android/pull/124) ([SonOfLilit](https://github.com/SonOfLilit)) +- --add-jar command line option for including .jar files [\#120](https://github.com/kivy/python-for-android/pull/120) ([bob-the-hamster](https://github.com/bob-the-hamster)) +- Ouya support [\#119](https://github.com/kivy/python-for-android/pull/119) ([bob-the-hamster](https://github.com/bob-the-hamster)) +- Clarify the documentation about how to use --intent-filters argument [\#118](https://github.com/kivy/python-for-android/pull/118) ([bob-the-hamster](https://github.com/bob-the-hamster)) +- Added 64bit Android NDK to export line [\#117](https://github.com/kivy/python-for-android/pull/117) ([brousch](https://github.com/brousch)) +- Fix Keyboard auto-suggestion bug when dealing with multiple textinputs. [\#115](https://github.com/kivy/python-for-android/pull/115) ([akshayaurora](https://github.com/akshayaurora)) +- Numpy recipe [\#112](https://github.com/kivy/python-for-android/pull/112) ([tito](https://github.com/tito)) +- Issue \#107 solution candidate \(Android service\) [\#108](https://github.com/kivy/python-for-android/pull/108) ([b3b](https://github.com/b3b)) +- seek, get\_pos and get\_length support for mediaplayer [\#106](https://github.com/kivy/python-for-android/pull/106) ([akshayaurora](https://github.com/akshayaurora)) +- allow overloading of recipe origin using env vars [\#105](https://github.com/kivy/python-for-android/pull/105) ([tshirtman](https://github.com/tshirtman)) +- Swype Input Support [\#104](https://github.com/kivy/python-for-android/pull/104) ([akshayaurora](https://github.com/akshayaurora)) +- Deleted recursive SDL dir [\#101](https://github.com/kivy/python-for-android/pull/101) ([brousch](https://github.com/brousch)) +- Issue \#97 solution candidate [\#99](https://github.com/kivy/python-for-android/pull/99) ([nskrypnik](https://github.com/nskrypnik)) +- Force wget or curl to save files using the expected filename [\#96](https://github.com/kivy/python-for-android/pull/96) ([d3vgru](https://github.com/d3vgru)) +- .gitignore: add a couple of rules [\#93](https://github.com/kivy/python-for-android/pull/93) ([artagnon](https://github.com/artagnon)) +- Clarify recipes [\#92](https://github.com/kivy/python-for-android/pull/92) ([artagnon](https://github.com/artagnon)) +- Change hash-bang for maximum compatability [\#89](https://github.com/kivy/python-for-android/pull/89) ([brousch](https://github.com/brousch)) +- Fix for build fails when no java files to copy. [\#84](https://github.com/kivy/python-for-android/pull/84) ([brousch](https://github.com/brousch)) +- MySQL/Connector update - 1.0.8 [\#80](https://github.com/kivy/python-for-android/pull/80) ([thopiekar](https://github.com/thopiekar)) +- New recipe for mysql-connector-python! [\#71](https://github.com/kivy/python-for-android/pull/71) ([thopiekar](https://github.com/thopiekar)) +- Get Android network state by direct query or with BroadcastReciever [\#65](https://github.com/kivy/python-for-android/pull/65) ([legikaloz](https://github.com/legikaloz)) +- Freetype includes is in includes/freetype [\#59](https://github.com/kivy/python-for-android/pull/59) ([rcludwick](https://github.com/rcludwick)) +- recipe for docutils [\#58](https://github.com/kivy/python-for-android/pull/58) ([akshayaurora](https://github.com/akshayaurora)) +- Distribute.sh doesnt work properly with python3 [\#56](https://github.com/kivy/python-for-android/pull/56) ([bgola](https://github.com/bgola)) +- tidy new Hardware.java including backwards compatibility and changed and upated doc-files [\#51](https://github.com/kivy/python-for-android/pull/51) ([nklever](https://github.com/nklever)) +- hide "set -x" into an option [\#49](https://github.com/kivy/python-for-android/pull/49) ([nklever](https://github.com/nklever)) +- some "public" declarations are necessary to get access by pyjnius [\#48](https://github.com/kivy/python-for-android/pull/48) ([nklever](https://github.com/nklever)) +- Change documentation to use previously set environment variables. [\#40](https://github.com/kivy/python-for-android/pull/40) ([hartym](https://github.com/hartym)) +- No big change to work with NDK r8 [\#35](https://github.com/kivy/python-for-android/pull/35) ([bertonha](https://github.com/bertonha)) +- Working with NDK 7\* [\#32](https://github.com/kivy/python-for-android/pull/32) ([bertonha](https://github.com/bertonha)) +- A fix for the bug where subprocess.call\(\) hangs forever. [\#30](https://github.com/kivy/python-for-android/pull/30) ([bbigras](https://github.com/bbigras)) +- Update for pylibpd [\#28](https://github.com/kivy/python-for-android/pull/28) ([dustinlacewell](https://github.com/dustinlacewell)) +- Lxml \(again\) [\#24](https://github.com/kivy/python-for-android/pull/24) ([phlax](https://github.com/phlax)) +- Added pyopenssl recipe [\#22](https://github.com/kivy/python-for-android/pull/22) ([phlax](https://github.com/phlax)) +- Integrating setuptools [\#21](https://github.com/kivy/python-for-android/pull/21) ([phlax](https://github.com/phlax)) +- Expat [\#20](https://github.com/kivy/python-for-android/pull/20) ([phlax](https://github.com/phlax)) +- This is needed to get the ndk-build command. [\#15](https://github.com/kivy/python-for-android/pull/15) ([mike-perdide](https://github.com/mike-perdide)) +- Fixing small typo: ANDROIDNDK instead of ANDROIDSDK. [\#14](https://github.com/kivy/python-for-android/pull/14) ([mike-perdide](https://github.com/mike-perdide)) +- use ANDROIDSDK path in build.py [\#11](https://github.com/kivy/python-for-android/pull/11) ([hansent](https://github.com/hansent)) +- wifi scanning api documentation [\#8](https://github.com/kivy/python-for-android/pull/8) ([cwiz](https://github.com/cwiz)) +- Native API wrappers - scan visible WiFi spots [\#6](https://github.com/kivy/python-for-android/pull/6) ([cwiz](https://github.com/cwiz)) + + + +\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1987de13b1..d0d7c98775 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -140,7 +140,7 @@ arises. To complete the release: - Tag the release commit in `master`, with tag `vYYYY.MM.DD`. Include a short summary of the changes. - Release distributions and PyPI upload should be - [handled by the CI](https://github.com/kivy/python-for-android/blob/v2020.04.29/.travis.yml#L60-L70). + [handled by the CI](.github/workflows/pypi-release.yml). - Add to the GitHub release page (see e.g. [this example](https://github.com/kivy/python-for-android/releases/tag/v2019.06.06): - The python-for-android README summary - A short list of major changes in this release, if any diff --git a/pythonforandroid/__init__.py b/pythonforandroid/__init__.py index ecdf256efa..07b71d4baa 100644 --- a/pythonforandroid/__init__.py +++ b/pythonforandroid/__init__.py @@ -1 +1 @@ -__version__ = '2024.01.21' +__version__ = '2026.05.09' diff --git a/setup.py b/setup.py index 0bf5b124a5..b150b6075a 100644 --- a/setup.py +++ b/setup.py @@ -128,6 +128,9 @@ def recursively_include(results, directory, patterns): 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', + 'Programming Language :: Python :: 3.13', + 'Programming Language :: Python :: 3.14', 'Topic :: Software Development', 'Topic :: Utilities', ], From b54bba6f63f2c2faa642d9fa486c291dd0630b22 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Sun, 10 May 2026 19:22:11 +0000 Subject: [PATCH 35/82] :fire: Drop EOL Python 3.7/3.8/3.9 support Bump python_requires to >=3.10.0, drop the matching classifiers and CI matrix entries. Align MIN_PYTHON_MINOR_VERSION to 10 and drop the now-unreachable Python 2 branch in check_python_version(). Remove the Python 2 compatibility shims anchored to the pre-3.10 floor (urlparse import, load_source Py3.3/3.4 fallback, FileNotFoundError shims, virtualenv branch, to_unicode wrapper, time.monotonic wrapper, path_type TypeError fallback, add_parser argparse aliases wrapper) and the permanently-inert Python 2 test markers. Drop the `from __future__ import annotations` workaround in the msgspec recipe (PEP 585 generics are native since 3.9) and the PEP 508 `python_version<"3.3"` / `<"3.5"` markers in the ifaddr and zeroconf recipes (never satisfied under the new floor). Modernize the remaining `typing.List` annotation to PEP 585 builtin generics in scipy/wrapper.py. The aiohttp recipe is left untouched on purpose: editing it would trigger the rebuild_updated_recipes CI, which fails because aiohttp 3.8.3's pregenerated Cython C is incompatible with Python 3.14 hostpython -- fixing that needs a recipe bump and is out of scope here. --- .github/workflows/push.yml | 2 +- pythonforandroid/pythonpackage.py | 53 +++--------- pythonforandroid/recipe.py | 5 +- pythonforandroid/recipes/ifaddr/__init__.py | 2 +- pythonforandroid/recipes/msgspec/__init__.py | 2 - pythonforandroid/recipes/scipy/wrapper.py | 3 +- pythonforandroid/recipes/zeroconf/__init__.py | 2 +- pythonforandroid/recommendations.py | 11 +-- pythonforandroid/toolchain.py | 81 +++++++------------ pythonforandroid/util.py | 14 +--- setup.py | 6 +- tests/test_recommendations.py | 20 +---- tests/test_toolchain.py | 3 - 13 files changed, 50 insertions(+), 154 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index c0bb2db3d2..bdfd7a9231 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -54,7 +54,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13', '3.14', '3.14t'] + python-version: ['3.10', '3.11', '3.12', '3.13', '3.14', '3.14t'] os: [ubuntu-latest, macos-latest] steps: - name: Checkout python-for-android diff --git a/pythonforandroid/pythonpackage.py b/pythonforandroid/pythonpackage.py index 0649d8848a..f5de4dc49a 100644 --- a/pythonforandroid/pythonpackage.py +++ b/pythonforandroid/pythonpackage.py @@ -34,7 +34,6 @@ import functools -from io import open # needed for python 2 import os import shutil import subprocess @@ -153,17 +152,13 @@ def binary_is_usable(python_bin): return # We should check file not found anyway trying to run it, # since it might be a dead symlink: - try: - filenotfounderror = FileNotFoundError - except NameError: # Python 2 - filenotfounderror = OSError try: # Run it and see if version output works with no error: subprocess.check_output([ os.path.join(path, python_bin), "--version" ], stderr=subprocess.STDOUT) return True - except (subprocess.CalledProcessError, filenotfounderror): + except (subprocess.CalledProcessError, FileNotFoundError): return False python_name = "python" + sys.version @@ -271,21 +266,10 @@ def get_package_as_folder(dependency): try: # Create a venv to install into: try: - if int(sys.version.partition(".")[0]) < 3: - # Python 2.x has no venv. - subprocess.check_output([ - sys.executable, # no venv conflict possible, - # -> no need to use system python - "-m", "virtualenv", - "--python=" + _get_system_python_executable(), - os.path.join(venv_parent, 'venv') - ], cwd=venv_parent) - else: - # On modern Python 3, use venv. - subprocess.check_output([ - _get_system_python_executable(), "-m", "venv", - os.path.join(venv_parent, 'venv') - ], cwd=venv_parent) + subprocess.check_output([ + _get_system_python_executable(), "-m", "venv", + os.path.join(venv_parent, 'venv') + ], cwd=venv_parent) except subprocess.CalledProcessError as e: output = e.output.decode('utf-8', 'replace') raise ValueError( @@ -295,16 +279,12 @@ def get_package_as_folder(dependency): venv_path = os.path.join(venv_parent, "venv") # Update pip and wheel in venv for latest feature support: - try: - filenotfounderror = FileNotFoundError - except NameError: # Python 2. - filenotfounderror = OSError try: subprocess.check_output([ os.path.join(venv_path, "bin", "pip"), "install", "-U", "pip", "wheel", ]) - except filenotfounderror: + except FileNotFoundError: raise RuntimeError( "venv appears to be missing pip. " "did we fail to use a proper system python??\n" @@ -322,12 +302,7 @@ def get_package_as_folder(dependency): with open(os.path.join(venv_path, "requirements.txt"), "w", encoding="utf-8" ) as f: - def to_unicode(s): # Needed for Python 2. - try: - return s.decode("utf-8") - except AttributeError: - return s - f.write(to_unicode(transform_dep_for_pip(dependency))) + f.write(transform_dep_for_pip(dependency)) try: subprocess.check_output( [ @@ -451,10 +426,7 @@ def _extract_metainfo_files_from_package_unsafe( # distribution, and others get_package_as_folder() may support # in the future. with open(os.path.join(output_path, "metadata_source"), "w") as f: - try: - f.write(path_type) - except TypeError: # in python 2 path_type may be str/bytes: - f.write(path_type.decode("utf-8", "replace")) + f.write(path_type) # Copy the metadata file: shutil.copyfile(metadata_path, os.path.join(output_path, "METADATA")) @@ -585,19 +557,14 @@ def _extract_info_from_package(dependency, def get_package_name(dependency, use_cache=True): - def timestamp(): - try: - return time.monotonic() - except AttributeError: - return time.time() # Python 2. try: value = package_name_cache[dependency] - if value[0] + 600.0 > timestamp() and use_cache: + if value[0] + 600.0 > time.monotonic() and use_cache: return value[1] except KeyError: pass result = _extract_info_from_package(dependency, extract_type="name") - package_name_cache[dependency] = (timestamp(), result) + package_name_cache[dependency] = (time.monotonic(), result) return result diff --git a/pythonforandroid/recipe.py b/pythonforandroid/recipe.py index 55db2bc194..05c1df97b4 100644 --- a/pythonforandroid/recipe.py +++ b/pythonforandroid/recipe.py @@ -16,10 +16,7 @@ from packaging.version import Version from multiprocessing import cpu_count import time -try: - from urlparse import urlparse -except ImportError: - from urllib.parse import urlparse +from urllib.parse import urlparse import packaging.version diff --git a/pythonforandroid/recipes/ifaddr/__init__.py b/pythonforandroid/recipes/ifaddr/__init__.py index 9409e76d17..36c02e4b86 100644 --- a/pythonforandroid/recipes/ifaddr/__init__.py +++ b/pythonforandroid/recipes/ifaddr/__init__.py @@ -5,7 +5,7 @@ class IfaddrRecipe(PythonRecipe): name = 'ifaddr' version = '0.1.7' url = 'https://pypi.python.org/packages/source/i/ifaddr/ifaddr-{version}.tar.gz' - depends = ['setuptools', 'ifaddrs', 'ipaddress;python_version<"3.3"'] + depends = ['setuptools', 'ifaddrs'] call_hostpython_via_targetpython = False patches = ["getifaddrs.patch"] diff --git a/pythonforandroid/recipes/msgspec/__init__.py b/pythonforandroid/recipes/msgspec/__init__.py index 87b24cd5f1..7ec2b8442a 100644 --- a/pythonforandroid/recipes/msgspec/__init__.py +++ b/pythonforandroid/recipes/msgspec/__init__.py @@ -1,5 +1,3 @@ -from __future__ import annotations - from typing import Any from pythonforandroid.archs import Arch diff --git a/pythonforandroid/recipes/scipy/wrapper.py b/pythonforandroid/recipes/scipy/wrapper.py index ca0e60d22e..d3573c8e6f 100644 --- a/pythonforandroid/recipes/scipy/wrapper.py +++ b/pythonforandroid/recipes/scipy/wrapper.py @@ -5,7 +5,6 @@ import os import subprocess import sys -import typing """ This wrapper is used to ignore or replace some unsupported flags for flang-new. @@ -30,7 +29,7 @@ COMPLIER_PATH = "@COMPILER@" -def main(argv: typing.List[str]): +def main(argv: list[str]): cwd = os.getcwd() argv_new = [] i = 0 diff --git a/pythonforandroid/recipes/zeroconf/__init__.py b/pythonforandroid/recipes/zeroconf/__init__.py index a23bd6e25c..471029e13e 100644 --- a/pythonforandroid/recipes/zeroconf/__init__.py +++ b/pythonforandroid/recipes/zeroconf/__init__.py @@ -5,7 +5,7 @@ class ZeroconfRecipe(PythonRecipe): name = 'zeroconf' version = '0.24.5' url = 'https://pypi.python.org/packages/source/z/zeroconf/zeroconf-{version}.tar.gz' - depends = ['setuptools', 'ifaddr', 'typing;python_version<"3.5"'] + depends = ['setuptools', 'ifaddr'] call_hostpython_via_targetpython = False diff --git a/pythonforandroid/recommendations.py b/pythonforandroid/recommendations.py index 397dcd9ca4..aa8ea31be5 100644 --- a/pythonforandroid/recommendations.py +++ b/pythonforandroid/recommendations.py @@ -186,14 +186,10 @@ def check_ndk_api(ndk_api, android_api): MIN_PYTHON_MAJOR_VERSION = 3 -MIN_PYTHON_MINOR_VERSION = 6 +MIN_PYTHON_MINOR_VERSION = 10 MIN_PYTHON_VERSION = packaging.version.Version( f"{MIN_PYTHON_MAJOR_VERSION}.{MIN_PYTHON_MINOR_VERSION}" ) -PY2_ERROR_TEXT = ( - 'python-for-android no longer supports running under Python 2. Either upgrade to ' - 'Python {min_version} or higher (recommended), or revert to python-for-android 2019.07.08.' -).format(min_version=MIN_PYTHON_VERSION) PY_VERSION_ERROR_TEXT = ( 'Your Python version {user_major}.{user_minor} is not supported by python-for-android, ' @@ -205,11 +201,6 @@ def check_ndk_api(ndk_api, android_api): def check_python_version(): - # Python 2 special cased because it's a major transition. In the - # future the major or minor versions can increment more quietly. - if sys.version_info.major == 2: - raise BuildInterruptingException(PY2_ERROR_TEXT) - if ( sys.version_info.major < MIN_PYTHON_MAJOR_VERSION or sys.version_info.minor < MIN_PYTHON_MINOR_VERSION diff --git a/pythonforandroid/toolchain.py b/pythonforandroid/toolchain.py index 2fec092640..eaaeb8f2e0 100644 --- a/pythonforandroid/toolchain.py +++ b/pythonforandroid/toolchain.py @@ -393,22 +393,11 @@ def __init__(self): subparsers = parser.add_subparsers(dest='subparser_name', help='The command to run') - def add_parser(subparsers, *args, **kwargs): - """ - argparse in python2 doesn't support the aliases option, - so we just don't provide the aliases there. - """ - if 'aliases' in kwargs and sys.version_info.major < 3: - kwargs.pop('aliases') - return subparsers.add_parser(*args, **kwargs) - - add_parser( - subparsers, + subparsers.add_parser( 'recommendations', parents=[generic_parser], help='List recommended p4a dependencies') - parser_recipes = add_parser( - subparsers, + parser_recipes = subparsers.add_parser( 'recipes', parents=[generic_parser], help='List the available recipes') @@ -416,33 +405,33 @@ def add_parser(subparsers, *args, **kwargs): "--compact", action="store_true", default=False, help="Produce a compact list suitable for scripting") - add_parser( - subparsers, 'bootstraps', + subparsers.add_parser( + 'bootstraps', help='List the available bootstraps', parents=[generic_parser]) - add_parser( - subparsers, 'clean_all', + subparsers.add_parser( + 'clean_all', aliases=['clean-all'], help='Delete all builds, dists and caches', parents=[generic_parser]) - add_parser( - subparsers, 'clean_dists', + subparsers.add_parser( + 'clean_dists', aliases=['clean-dists'], help='Delete all dists', parents=[generic_parser]) - add_parser( - subparsers, 'clean_bootstrap_builds', + subparsers.add_parser( + 'clean_bootstrap_builds', aliases=['clean-bootstrap-builds'], help='Delete all bootstrap builds', parents=[generic_parser]) - add_parser( - subparsers, 'clean_builds', + subparsers.add_parser( + 'clean_builds', aliases=['clean-builds'], help='Delete all builds', parents=[generic_parser]) - parser_clean = add_parser( - subparsers, 'clean', + parser_clean = subparsers.add_parser( + 'clean', help='Delete build components.', parents=[generic_parser]) parser_clean.add_argument( @@ -451,8 +440,7 @@ def add_parser(subparsers, *args, **kwargs): 'number of arguments from "all", "builds", "dists", ' '"distributions", "bootstrap_builds", "downloads".')) - parser_clean_recipe_build = add_parser( - subparsers, + parser_clean_recipe_build = subparsers.add_parser( 'clean_recipe_build', aliases=['clean-recipe-build'], help=('Delete the build components of the given recipe. ' 'By default this will also delete built dists'), @@ -465,8 +453,7 @@ def add_parser(subparsers, *args, **kwargs): action='store_true', help='If passed, do not delete existing dists') - parser_clean_download_cache = add_parser( - subparsers, + parser_clean_download_cache = subparsers.add_parser( 'clean_download_cache', aliases=['clean-download-cache'], help='Delete cached downloads for requirement builds', parents=[generic_parser]) @@ -476,8 +463,7 @@ def add_parser(subparsers, *args, **kwargs): help='The recipes to clean (space-separated). If no recipe name is' ' provided, the entire cache is cleared.') - parser_export_dist = add_parser( - subparsers, + parser_export_dist = subparsers.add_parser( 'export_dist', aliases=['export-dist'], help='Copy the named dist to the given path', parents=[generic_parser]) @@ -547,57 +533,46 @@ def add_parser(subparsers, *args, **kwargs): '--signkeypw', dest='signkeypw', action='store', default=None, help='Password for key alias') - add_parser( - subparsers, + subparsers.add_parser( 'aar', help='Build an AAR', parents=[parser_packaging]) - add_parser( - subparsers, + subparsers.add_parser( 'apk', help='Build an APK', parents=[parser_packaging]) - add_parser( - subparsers, + subparsers.add_parser( 'aab', help='Build an AAB', parents=[parser_packaging]) - add_parser( - subparsers, + subparsers.add_parser( 'create', help='Compile a set of requirements into a dist', parents=[generic_parser]) - add_parser( - subparsers, + subparsers.add_parser( 'archs', help='List the available target architectures', parents=[generic_parser]) - add_parser( - subparsers, + subparsers.add_parser( 'distributions', aliases=['dists'], help='List the currently available (compiled) dists', parents=[generic_parser]) - add_parser( - subparsers, + subparsers.add_parser( 'delete_dist', aliases=['delete-dist'], help='Delete a compiled dist', parents=[generic_parser]) - parser_sdk_tools = add_parser( - subparsers, + parser_sdk_tools = subparsers.add_parser( 'sdk_tools', aliases=['sdk-tools'], help='Run the given binary from the SDK tools dis', parents=[generic_parser]) parser_sdk_tools.add_argument( 'tool', help='The binary tool name to run') - add_parser( - subparsers, + subparsers.add_parser( 'adb', help='Run adb from the given SDK', parents=[generic_parser]) - add_parser( - subparsers, + subparsers.add_parser( 'logcat', help='Run logcat from the given SDK', parents=[generic_parser]) - add_parser( - subparsers, + subparsers.add_parser( 'build_status', aliases=['build-status'], help='Print some debug information about current built components', parents=[generic_parser]) diff --git a/pythonforandroid/util.py b/pythonforandroid/util.py index 3cdcaaae76..9b1752beea 100644 --- a/pythonforandroid/util.py +++ b/pythonforandroid/util.py @@ -86,17 +86,11 @@ def walk_valid_filens(base_dir, invalid_dir_names, invalid_file_patterns, exclud def load_source(module, filename): - # Python 3.5+ import importlib.util - if hasattr(importlib.util, 'module_from_spec'): - spec = importlib.util.spec_from_file_location(module, filename) - mod = importlib.util.module_from_spec(spec) - spec.loader.exec_module(mod) - return mod - else: - # Python 3.3 and 3.4: - from importlib.machinery import SourceFileLoader - return SourceFileLoader(module, filename).load_module() + spec = importlib.util.spec_from_file_location(module, filename) + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + return mod class BuildInterruptingException(Exception): diff --git a/setup.py b/setup.py index b150b6075a..5c2b90eb21 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,5 @@ import glob -from io import open # for open(..,encoding=...) parameter in python 2 from os import walk from os.path import join, dirname, sep import re @@ -95,7 +94,7 @@ def recursively_include(results, directory, patterns): ), long_description=long_description, long_description_content_type='text/markdown', - python_requires=">=3.7.0", + python_requires=">=3.10.0", author='Kivy Team and other contributors', author_email='kivy-dev@googlegroups.com', url='https://github.com/kivy/python-for-android', @@ -123,9 +122,6 @@ def recursively_include(results, directory, patterns): 'Operating System :: Android', 'Programming Language :: C', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', diff --git a/tests/test_recommendations.py b/tests/test_recommendations.py index 443ec52b39..ce21b71886 100644 --- a/tests/test_recommendations.py +++ b/tests/test_recommendations.py @@ -1,6 +1,5 @@ import unittest from os.path import join -from sys import version as py_version import packaging.version from unittest import mock @@ -33,14 +32,11 @@ OLD_API_MESSAGE, MIN_PYTHON_MAJOR_VERSION, MIN_PYTHON_MINOR_VERSION, - PY2_ERROR_TEXT, PY_VERSION_ERROR_TEXT, ) from pythonforandroid.util import BuildInterruptingException -running_in_py2 = int(py_version[0]) < 3 - class TestRecommendations(unittest.TestCase): """ @@ -51,7 +47,6 @@ class TestRecommendations(unittest.TestCase): def setUp(self): self.ndk_dir = "/opt/android/android-ndk" - @unittest.skipIf(running_in_py2, "`assertLogs` requires Python 3.4+") @mock.patch("pythonforandroid.recommendations.read_ndk_version") def test_check_ndk_version_greater_than_recommended(self, mock_read_ndk): _version_string = f"{MIN_NDK_VERSION + 1}.0.5232133" @@ -90,7 +85,6 @@ def test_check_ndk_version_lower_than_recommended(self, mock_read_ndk): ) mock_read_ndk.assert_called_once_with(self.ndk_dir) - @unittest.skipIf(running_in_py2, "`assertLogs` requires Python 3.4+") def test_check_ndk_version_error(self): """ Test that a fake ndk dir give us two messages: @@ -131,7 +125,6 @@ def test_read_ndk_version(self, mock_open_src_prop): assert version.minor == 2 assert version.micro == 4988734 - @unittest.skipIf(running_in_py2, "`assertLogs` requires Python 3.4+") @mock.patch("pythonforandroid.recommendations.open") def test_read_ndk_version_error(self, mock_open_src_prop): mock_open_src_prop.side_effect = [ @@ -160,7 +153,6 @@ def test_check_target_api_error_arch_armeabi(self): ), ) - @unittest.skipIf(running_in_py2, "`assertLogs` requires Python 3.4+") def test_check_target_api_warning_target_api(self): with self.assertLogs(level="INFO") as cm: @@ -191,7 +183,6 @@ def test_check_ndk_api_error_android_api(self): ), ) - @unittest.skipIf(running_in_py2, "`assertLogs` requires Python 3.4+") def test_check_ndk_api_warning_old_ndk(self): """ Given an `android api` lower than the supported by p4a, we should @@ -216,17 +207,8 @@ def test_check_python_version(self): """ with mock.patch('sys.version_info') as fake_version_info: - # Major version is Python 2 => exception - fake_version_info.major = MIN_PYTHON_MAJOR_VERSION - 1 - fake_version_info.minor = MIN_PYTHON_MINOR_VERSION - with self.assertRaises(BuildInterruptingException) as context: - check_python_version() - assert context.exception.message == PY2_ERROR_TEXT - # Major version too low => exception - # Using a float valued major version just to test the logic and avoid - # clashing with the Python 2 check - fake_version_info.major = MIN_PYTHON_MAJOR_VERSION - 0.1 + fake_version_info.major = MIN_PYTHON_MAJOR_VERSION - 1 fake_version_info.minor = MIN_PYTHON_MINOR_VERSION with self.assertRaises(BuildInterruptingException) as context: check_python_version() diff --git a/tests/test_toolchain.py b/tests/test_toolchain.py index 03b008fd35..0580763a64 100644 --- a/tests/test_toolchain.py +++ b/tests/test_toolchain.py @@ -1,6 +1,5 @@ import io import os -import sys import pytest from unittest import mock from pythonforandroid.recipe import Recipe @@ -37,7 +36,6 @@ def test_help(self): assert ex_info.value.code == 0 assert m_print_help.call_args_list == [mock.call()] - @pytest.mark.skipif(sys.version_info < (3, 0), reason="requires python3") def test_unknown(self): """ Calling with unknown args should print help and exit 1. @@ -116,7 +114,6 @@ def test_create_no_sdk_dir(self): assert ex_info.value.message == ( 'Android SDK dir was not specified, exiting.') - @pytest.mark.skipif(sys.version_info < (3, 0), reason="requires python3") def test_recipes(self): """ Checks the `recipes` command prints out recipes information without crashing. From 055e7696e7256471bc25ba18f48e1d904d8655cb Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Sun, 10 May 2026 20:46:47 +0000 Subject: [PATCH 36/82] :memo: Document release process and fix README badges Extract the "Creating a new release" and "Release checklist" sections from CONTRIBUTING.md into a dedicated RELEASING.md, expanded to cover version bump, changelog regeneration, tagging, and PyPI auto-publish on tag push. CONTRIBUTING.md keeps a pointer to the new file. Also fix three README badges: - Wrap PyPI version and Python-version badges in links to the PyPI project page; previously image-only. - Replace the deprecated /workflows//badge.svg URL for the "Unit tests & build apps" badge with the current /actions/workflows/push.yml/badge.svg form. The legacy URL was returning "no status". --- CONTRIBUTING.md | 42 +++-------------------- README.md | 6 ++-- RELEASING.md | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 41 deletions(-) create mode 100644 RELEASING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d0d7c98775..0a9310ad97 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -120,44 +120,10 @@ and runs the linting inside the container. - Trailing whitespace trimming - Files end with newline -## Creating a new release - -(These instructions are for core developers, not casual contributors.) - -New releases follow these steps: - -- Create a new branch `release-YYYY.MM.DD` based on the `develop` branch. - - `git checkout -b release-YYYY.MM.DD develop` -- Create a Github pull request to merge `release-YYYY.MM.DD` into `master`. -- Complete all steps in the [release checklist](#Release_checklist), - and document this in the pull request (copy the checklist into the PR text) - -At this point, wait for reviewer approval and conclude any discussion that -arises. To complete the release: - -- Merge the release branch to the `master` branch. -- Also merge the release branch to the `develop` branch. -- Tag the release commit in `master`, with tag `vYYYY.MM.DD`. Include a short - summary of the changes. -- Release distributions and PyPI upload should be - [handled by the CI](.github/workflows/pypi-release.yml). -- Add to the GitHub release page (see e.g. [this example](https://github.com/kivy/python-for-android/releases/tag/v2019.06.06): - - The python-for-android README summary - - A short list of major changes in this release, if any - - A changelog summarising merge commits since the last release - - The release sdist and wheel(s) - -## Release checklist - - - [ ] Check that the builds are passing - - [ ] [GitHub Action](https://github.com/kivy/python-for-android/actions) - - [ ] Run the tests locally via `tox`: this performs some long-running tests that are skipped on github-actions. - - [ ] Build and run the [on_device_unit_tests](https://github.com/kivy/python-for-android/tree/master/testapps/on_device_unit_tests) app using buildozer. Check that they all pass. - - [ ] Build (or download from github actions) and run the following [testapps](https://github.com/kivy/python-for-android/tree/master/testapps/on_device_unit_tests) for arch `armeabi-v7a` and `arm64-v8a`: - - [ ] on_device_unit_tests - - [ ] `armeabi-v7a` (`cd testapps/on_device_unit_tests && PYTHONPATH=.:../../ python3 setup.py apk --ndk-dir= --sdk-dir= --arch=armeabi-v7a --debug`) - - [ ] `arm64-v8a` (`cd testapps/on_device_unit_tests && PYTHONPATH=.:../../ python3 setup.py apk --ndk-dir= --sdk-dir= --arch=arm64-v8a --debug`) - - [ ] Check that the version number is correct +## Releasing + +The release process for core developers is documented separately in +[RELEASING.md](RELEASING.md). ## How python-for-android uses `pip` diff --git a/README.md b/README.md index e4d3062b37..3717cac145 100644 --- a/README.md +++ b/README.md @@ -42,10 +42,10 @@ python-for-android is not limited to being used with Buildozer. [![GitHub contributors](https://img.shields.io/github/contributors-anon/kivy/python-for-android)](https://github.com/kivy/python-for-android/graphs/contributors) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE_OF_CONDUCT.md) -![PyPI - Version](https://img.shields.io/pypi/v/python-for-android) -![PyPI - Python Version](https://img.shields.io/pypi/pyversions/python-for-android) +[![PyPI - Version](https://img.shields.io/pypi/v/python-for-android)](https://pypi.org/project/python-for-android/) +[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/python-for-android)](https://pypi.org/project/python-for-android/) -[![Unit tests & build apps](https://github.com/kivy/python-for-android/workflows/Unit%20tests%20&%20build%20apps/badge.svg?branch=develop)](https://github.com/kivy/python-for-android/actions?query=workflow%3A%22Unit+tests+%26+build+apps%22) +[![Unit tests & build apps](https://github.com/kivy/python-for-android/actions/workflows/push.yml/badge.svg?branch=develop)](https://github.com/kivy/python-for-android/actions/workflows/push.yml) [![Coverage Status](https://coveralls.io/repos/github/kivy/python-for-android/badge.svg?branch=develop&kill_cache=1)](https://coveralls.io/github/kivy/python-for-android?branch=develop) [![Docker](https://github.com/kivy/python-for-android/actions/workflows/docker.yml/badge.svg)](https://github.com/kivy/python-for-android/actions/workflows/docker.yml) diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 0000000000..50ebc2fb5c --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,89 @@ +# Releasing python-for-android + +This document describes the release process for python-for-android. It is +intended for core developers who cut new releases. Casual contributors do +not need to read it. + +## Versioning + +python-for-android uses [calendar versioning](https://calver.org/) of the +form `YYYY.MM.DD` (e.g. `2026.05.09`). Calendar versioning is used because +changes are often driven by Android build-tool updates, so users generally +want the latest release. Backward compatibility is preserved across +releases where possible. + +The single source of truth for the version is +[`pythonforandroid/__init__.py`](pythonforandroid/__init__.py). `setup.py` +parses `__version__` from that file and exposes it as the package version. + +## Branching model + +- `master` always represents the latest stable release. +- `develop` is the active development branch and the target for all PRs. +- Release branches `release-YYYY.MM.DD` are cut from `develop` for each + release, then merged into both `master` and back into `develop`. + +## Release steps + +1. **Cut a release branch** from an up-to-date `develop`: + + ```bash + git checkout develop && git pull + git checkout -b release-YYYY.MM.DD + ``` + +2. **Bump the version** in + [`pythonforandroid/__init__.py`](pythonforandroid/__init__.py). + +3. **Regenerate `CHANGELOG.md`** using + [`github-changelog-generator`](https://github.com/github-changelog-generator/github-changelog-generator). + +4. **Open a pull request** from `release-YYYY.MM.DD` targeting `master`. + Copy the [release checklist](#release-checklist) into the PR + description and tick items off as they are validated. + +5. **Wait for review and complete the checklist** before merging. + +6. **Merge the release branch into `master`**, then merge it back into + `develop` so the version bump and changelog land on both branches. + +7. **Tag the release commit on `master`** with an annotated tag: + + ```bash + git checkout master && git pull + git tag -a vYYYY.MM.DD -m "Release YYYY.MM.DD" + git push origin vYYYY.MM.DD + ``` + + Tags follow the format `vYYYY.MM.DD`. + +8. **PyPI upload happens automatically** when the tag is pushed. The + [`pypi-release.yml`](.github/workflows/pypi-release.yml) workflow + builds `sdist` and `bdist_wheel`, runs `twine check`, and uploads via + the `pypi_password` token. Non-tag pushes still build and check the + artifacts but do not publish. + +9. **Create the GitHub Release** at + from the new + tag. Use GitHub's "Generate release notes" feature to auto-fill the + title and description from merged PRs since the previous tag, then + tweak as needed. + +10. **Announce the release on Discord** in the + [#announcements](https://discord.com/channels/423249981340778496/490505571271704577) + channel. Include the version number and a link to the GitHub + release page. + +## Release checklist + +Use this as the PR description for the release branch. + +- [ ] Check that the builds are passing + - [ ] [GitHub Action](https://github.com/kivy/python-for-android/actions) +- [ ] Run the tests locally via `tox`: this performs some long-running tests that are skipped on github-actions. +- [ ] Build and run the [on_device_unit_tests](https://github.com/kivy/python-for-android/tree/master/testapps/on_device_unit_tests) app using buildozer. Check that they all pass. +- [ ] Build (or download from github actions) and run the following [testapps](https://github.com/kivy/python-for-android/tree/master/testapps/on_device_unit_tests) for arch `armeabi-v7a` and `arm64-v8a`: + - [ ] on_device_unit_tests + - [ ] `armeabi-v7a` (`cd testapps/on_device_unit_tests && PYTHONPATH=.:../../ python3 setup.py apk --ndk-dir= --sdk-dir= --arch=armeabi-v7a --debug`) + - [ ] `arm64-v8a` (`cd testapps/on_device_unit_tests && PYTHONPATH=.:../../ python3 setup.py apk --ndk-dir= --sdk-dir= --arch=arm64-v8a --debug`) +- [ ] Check that the version number is correct From bf10a90d16eeae9c76d1cd588cc8e20e05ed1023 Mon Sep 17 00:00:00 2001 From: Ansh Dadwal Date: Thu, 16 Apr 2026 17:11:36 +0530 Subject: [PATCH 37/82] `pyav`: update to `17.0.0` --- pythonforandroid/recipes/av/__init__.py | 21 ++++++--------- .../patches/compilation_syntax_errors.patch | 27 ------------------- 2 files changed, 8 insertions(+), 40 deletions(-) delete mode 100644 pythonforandroid/recipes/av/patches/compilation_syntax_errors.patch diff --git a/pythonforandroid/recipes/av/__init__.py b/pythonforandroid/recipes/av/__init__.py index f189467add..c765eafe98 100644 --- a/pythonforandroid/recipes/av/__init__.py +++ b/pythonforandroid/recipes/av/__init__.py @@ -1,25 +1,20 @@ from pythonforandroid.toolchain import Recipe -from pythonforandroid.recipe import CythonRecipe +from pythonforandroid.recipe import PyProjectRecipe -class PyAVRecipe(CythonRecipe): +class PyAVRecipe(PyProjectRecipe): name = "av" - version = "13.1.0" + version = "17.0.0" url = "https://github.com/PyAV-Org/PyAV/archive/v{version}.zip" - - depends = ["python3", "cython", "ffmpeg", "av_codecs"] - opt_depends = ["openssl"] - patches = ['patches/compilation_syntax_errors.patch'] + depends = ["python3", "ffmpeg", "av_codecs", "openssl"] + hostpython_prerequisites = ["cython>=3.1.0"] def get_recipe_env(self, arch, with_flags_in_cc=True): env = super().get_recipe_env(arch) - - build_dir = Recipe.get_recipe("ffmpeg", self.ctx).get_build_dir( - arch.arch - ) - self.setup_extra_args = ["--ffmpeg-dir={}".format(build_dir)] - + build_dir = Recipe.get_recipe("ffmpeg", self.ctx).get_build_dir(arch.arch) + env["CFLAGS"] += f" -I{build_dir}" + self.extra_build_args += ["--config-setting=--ffmpeg-dir={}".format(build_dir)] return env diff --git a/pythonforandroid/recipes/av/patches/compilation_syntax_errors.patch b/pythonforandroid/recipes/av/patches/compilation_syntax_errors.patch deleted file mode 100644 index c9a7e9adb3..0000000000 --- a/pythonforandroid/recipes/av/patches/compilation_syntax_errors.patch +++ /dev/null @@ -1,27 +0,0 @@ -diff --git a/av/container/streams.pyx b/av/container/streams.pyx -index 17e4992..502ac5a 100644 ---- a/av/container/streams.pyx -+++ b/av/container/streams.pyx -@@ -144,7 +144,7 @@ cdef class StreamContainer: - - return stream_index - -- def best(self, str type, /, Stream related = None): -+ def best(self, str type, Stream related=None): - """best(type: Literal["video", "audio", "subtitle", "attachment", "data"], /, related: Stream | None) - Finds the "best" stream in the file. Wraps :ffmpeg:`av_find_best_stream`. Example:: - -diff --git a/av/filter/context.pyx b/av/filter/context.pyx -index b820d3d..8908b56 100644 ---- a/av/filter/context.pyx -+++ b/av/filter/context.pyx -@@ -77,7 +77,8 @@ cdef class FilterContext: - - @property - def graph(self): -- if (graph := self._graph()): -+ graph = self._graph() -+ if graph: - return graph - else: - raise RuntimeError("graph is unallocated") From 213d4bad31384ba5d9315edf8f55e9977029c70d Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Sun, 17 May 2026 17:42:57 +0000 Subject: [PATCH 38/82] :recycle: Deduplicate Java service intent setup Add a shared PythonServiceIntent helper for building Python service intents and stopping services. Migrate activity service-start methods and generated service templates to delegate intent construction while preserving public APIs, service-only Binder behavior, and service-library foreground startup behavior. --- .../org/kivy/android/PythonServiceIntent.java | 173 ++++++++++++++++++ .../common/build/templates/Service.tmpl.java | 30 ++- .../java/org/kivy/android/PythonActivity.java | 25 +-- .../java/org/kivy/android/PythonActivity.java | 25 +-- .../java/org/kivy/android/PythonActivity.java | 25 +-- .../build/templates/Service.tmpl.java | 34 ++-- .../java/org/kivy/android/PythonActivity.java | 25 +-- .../build/templates/Service.tmpl.java | 60 +++--- .../java/org/kivy/android/PythonActivity.java | 25 +-- 9 files changed, 281 insertions(+), 141 deletions(-) create mode 100644 pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonServiceIntent.java diff --git a/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonServiceIntent.java b/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonServiceIntent.java new file mode 100644 index 0000000000..4f68d6343b --- /dev/null +++ b/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonServiceIntent.java @@ -0,0 +1,173 @@ +package org.kivy.android; + +import android.content.Context; +import android.content.Intent; + +public class PythonServiceIntent { + + private PythonServiceIntent() {} + + public static Intent build( + Context ctx, + Class serviceClass, + String serviceEntrypoint, + String serviceTitle, + String pythonName, + String serviceStartAsForeground, + String pythonServiceArgument, + String smallIconName, + String contentTitle, + String contentText) { + String appRoot = PythonUtil.getAppRoot(ctx); + return buildWithPaths( + ctx, + serviceClass, + ctx.getFilesDir().getAbsolutePath(), + appRoot, + null, + serviceEntrypoint, + serviceTitle, + null, + pythonName, + serviceStartAsForeground, + pythonServiceArgument, + smallIconName, + contentTitle, + contentText); + } + + public static Intent build( + Context ctx, + Class serviceClass, + String serviceEntrypoint, + String serviceTitle, + String pythonName, + boolean serviceStartAsForeground, + String pythonServiceArgument, + String smallIconName, + String contentTitle, + String contentText) { + return build( + ctx, + serviceClass, + serviceEntrypoint, + serviceTitle, + pythonName, + booleanToString(serviceStartAsForeground), + pythonServiceArgument, + smallIconName, + contentTitle, + contentText); + } + + public static Intent buildActivityService( + Context ctx, + Class serviceClass, + String serviceEntrypoint, + String serviceTitle, + String serviceDescription, + boolean serviceStartAsForeground, + String pythonServiceArgument) { + String appRoot = PythonUtil.getAppRoot(ctx); + return buildWithPaths( + ctx, + serviceClass, + ctx.getFilesDir().getAbsolutePath(), + appRoot, + null, + serviceEntrypoint, + serviceTitle, + serviceDescription, + "python", + booleanToString(serviceStartAsForeground), + pythonServiceArgument, + null, + null, + null); + } + + public static Intent buildWithPaths( + Context ctx, + Class serviceClass, + String androidPrivate, + String androidArgument, + String androidUnpack, + String serviceEntrypoint, + String serviceTitle, + String serviceDescription, + String pythonName, + String serviceStartAsForeground, + String pythonServiceArgument, + String smallIconName, + String contentTitle, + String contentText) { + Intent intent = new Intent(ctx, serviceClass); + intent.putExtra("androidPrivate", androidPrivate); + intent.putExtra("androidArgument", androidArgument); + intent.putExtra("serviceEntrypoint", serviceEntrypoint); + intent.putExtra("pythonName", pythonName); + intent.putExtra("serviceStartAsForeground", serviceStartAsForeground); + intent.putExtra("pythonHome", androidArgument); + intent.putExtra("pythonPath", androidArgument + ":" + androidArgument + "/lib"); + intent.putExtra("pythonServiceArgument", pythonServiceArgument); + intent.putExtra("serviceTitle", serviceTitle); + + if (androidUnpack != null) { + intent.putExtra("androidUnpack", androidUnpack); + } + if (serviceDescription != null) { + intent.putExtra("serviceDescription", serviceDescription); + } + if (smallIconName != null) { + intent.putExtra("smallIconName", smallIconName); + } + if (contentTitle != null) { + intent.putExtra("contentTitle", contentTitle); + } + if (contentText != null) { + intent.putExtra("contentText", contentText); + } + + return intent; + } + + public static Intent buildWithPaths( + Context ctx, + Class serviceClass, + String androidPrivate, + String androidArgument, + String androidUnpack, + String serviceEntrypoint, + String serviceTitle, + String serviceDescription, + String pythonName, + boolean serviceStartAsForeground, + String pythonServiceArgument, + String smallIconName, + String contentTitle, + String contentText) { + return buildWithPaths( + ctx, + serviceClass, + androidPrivate, + androidArgument, + androidUnpack, + serviceEntrypoint, + serviceTitle, + serviceDescription, + pythonName, + booleanToString(serviceStartAsForeground), + pythonServiceArgument, + smallIconName, + contentTitle, + contentText); + } + + public static void stop(Context ctx, Class serviceClass) { + ctx.stopService(new Intent(ctx, serviceClass)); + } + + private static String booleanToString(boolean value) { + return value ? "true" : "false"; + } +} diff --git a/pythonforandroid/bootstraps/common/build/templates/Service.tmpl.java b/pythonforandroid/bootstraps/common/build/templates/Service.tmpl.java index bbce7bed4f..fdab9d963f 100644 --- a/pythonforandroid/bootstraps/common/build/templates/Service.tmpl.java +++ b/pythonforandroid/bootstraps/common/build/templates/Service.tmpl.java @@ -3,6 +3,7 @@ import android.content.Intent; import android.content.Context; import {{ args.service_class_name }}; +import org.kivy.android.PythonServiceIntent; public class Service{{ name|capitalize }} extends {{ base_service_class }} { @@ -39,21 +40,17 @@ static public void start(Context ctx, String smallIconName, static public Intent getDefaultIntent(Context ctx, String smallIconName, String contentTitle, String contentText, String pythonServiceArgument) { - Intent intent = new Intent(ctx, Service{{ name|capitalize }}.class); - String argument = ctx.getFilesDir().getAbsolutePath() + "/app"; - intent.putExtra("androidPrivate", ctx.getFilesDir().getAbsolutePath()); - intent.putExtra("androidArgument", argument); - intent.putExtra("serviceTitle", "{{ args.name }}"); - intent.putExtra("serviceEntrypoint", "{{ entrypoint }}"); - intent.putExtra("pythonName", "{{ name }}"); - intent.putExtra("serviceStartAsForeground", "{{ foreground|lower }}"); - intent.putExtra("pythonHome", argument); - intent.putExtra("pythonPath", argument + ":" + argument + "/lib"); - intent.putExtra("pythonServiceArgument", pythonServiceArgument); - intent.putExtra("smallIconName", smallIconName); - intent.putExtra("contentTitle", contentTitle); - intent.putExtra("contentText", contentText); - return intent; + return PythonServiceIntent.build( + ctx, + Service{{ name|capitalize }}.class, + "{{ entrypoint }}", + "{{ args.name }}", + "{{ name }}", + "{{ foreground|lower }}", + pythonServiceArgument, + smallIconName, + contentTitle, + contentText); } @Override @@ -63,7 +60,6 @@ protected Intent getThisDefaultIntent(Context ctx, String pythonServiceArgument) } static public void stop(Context ctx) { - Intent intent = new Intent(ctx, Service{{ name|capitalize }}.class); - ctx.stopService(intent); + PythonServiceIntent.stop(ctx, Service{{ name|capitalize }}.class); } } 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 index 01bdd96805..9c1415db0c 100644 --- 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 @@ -216,26 +216,21 @@ public static void _do_start_service( 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); + Intent serviceIntent = + PythonServiceIntent.buildActivityService( + PythonActivity.mActivity, + PythonService.class, + "service/" + entry_point, + serviceTitle, + serviceDescription, + showForegroundNotification, + pythonServiceArgument); PythonActivity.mActivity.startService(serviceIntent); } public static void stop_service() { - Intent serviceIntent = new Intent(PythonActivity.mActivity, PythonService.class); - PythonActivity.mActivity.stopService(serviceIntent); + PythonServiceIntent.stop(PythonActivity.mActivity, PythonService.class); } } diff --git a/pythonforandroid/bootstraps/sdl2/build/src/main/java/org/kivy/android/PythonActivity.java b/pythonforandroid/bootstraps/sdl2/build/src/main/java/org/kivy/android/PythonActivity.java index 04d3eee30a..a5d494213e 100644 --- a/pythonforandroid/bootstraps/sdl2/build/src/main/java/org/kivy/android/PythonActivity.java +++ b/pythonforandroid/bootstraps/sdl2/build/src/main/java/org/kivy/android/PythonActivity.java @@ -302,27 +302,22 @@ public static void _do_start_service( 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); + Intent serviceIntent = + PythonServiceIntent.buildActivityService( + PythonActivity.mActivity, + PythonService.class, + "service/" + entry_point, + serviceTitle, + serviceDescription, + showForegroundNotification, + pythonServiceArgument); PythonActivity.mActivity.startService(serviceIntent); } public static void stop_service() { - Intent serviceIntent = new Intent(PythonActivity.mActivity, PythonService.class); - PythonActivity.mActivity.stopService(serviceIntent); + PythonServiceIntent.stop(PythonActivity.mActivity, PythonService.class); } /** Loading screen view * */ diff --git a/pythonforandroid/bootstraps/sdl3/build/src/main/java/org/kivy/android/PythonActivity.java b/pythonforandroid/bootstraps/sdl3/build/src/main/java/org/kivy/android/PythonActivity.java index 8feed58ee4..abc4afbf15 100644 --- a/pythonforandroid/bootstraps/sdl3/build/src/main/java/org/kivy/android/PythonActivity.java +++ b/pythonforandroid/bootstraps/sdl3/build/src/main/java/org/kivy/android/PythonActivity.java @@ -301,27 +301,22 @@ public static void _do_start_service( 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); + Intent serviceIntent = + PythonServiceIntent.buildActivityService( + PythonActivity.mActivity, + PythonService.class, + "service/" + entry_point, + serviceTitle, + serviceDescription, + showForegroundNotification, + pythonServiceArgument); PythonActivity.mActivity.startService(serviceIntent); } public static void stop_service() { - Intent serviceIntent = new Intent(PythonActivity.mActivity, PythonService.class); - PythonActivity.mActivity.stopService(serviceIntent); + PythonServiceIntent.stop(PythonActivity.mActivity, PythonService.class); } /** Loading screen view * */ diff --git a/pythonforandroid/bootstraps/service_library/build/templates/Service.tmpl.java b/pythonforandroid/bootstraps/service_library/build/templates/Service.tmpl.java index ff889b462c..ea00bc8d7e 100644 --- a/pythonforandroid/bootstraps/service_library/build/templates/Service.tmpl.java +++ b/pythonforandroid/bootstraps/service_library/build/templates/Service.tmpl.java @@ -9,6 +9,7 @@ import android.util.Log; import org.kivy.android.PythonService; +import org.kivy.android.PythonServiceIntent; import org.kivy.android.PythonUtil; public class Service{{ name|capitalize }} extends PythonService { @@ -69,21 +70,21 @@ static public Intent getDefaultIntent(Context ctx, String smallIconName, String contentText, String pythonServiceArgument) { String appRoot = PythonUtil.getAppRoot(ctx); - Intent intent = new Intent(ctx, Service{{ name|capitalize }}.class); - intent.putExtra("androidPrivate", appRoot); - intent.putExtra("androidArgument", appRoot); - intent.putExtra("serviceEntrypoint", "{{ entrypoint }}"); - intent.putExtra("serviceTitle", "{{ name|capitalize }}"); - intent.putExtra("pythonName", "{{ name }}"); - intent.putExtra("serviceStartAsForeground", "{{ foreground|lower }}"); - intent.putExtra("pythonHome", appRoot); - intent.putExtra("androidUnpack", appRoot); - intent.putExtra("pythonPath", appRoot + ":" + appRoot + "/lib"); - intent.putExtra("pythonServiceArgument", pythonServiceArgument); - intent.putExtra("smallIconName", smallIconName); - intent.putExtra("contentTitle", contentTitle); - intent.putExtra("contentText", contentText); - return intent; + return PythonServiceIntent.buildWithPaths( + ctx, + Service{{ name|capitalize }}.class, + appRoot, + appRoot, + appRoot, + "{{ entrypoint }}", + "{{ name|capitalize }}", + null, + "{{ name }}", + "{{ foreground|lower }}", + pythonServiceArgument, + smallIconName, + contentTitle, + contentText); } @Override @@ -95,8 +96,7 @@ protected Intent getThisDefaultIntent(Context ctx, String pythonServiceArgument) static public void stop(Context ctx) { - Intent intent = new Intent(ctx, Service{{ name|capitalize }}.class); - ctx.stopService(intent); + PythonServiceIntent.stop(ctx, Service{{ name|capitalize }}.class); } } diff --git a/pythonforandroid/bootstraps/service_only/build/src/main/java/org/kivy/android/PythonActivity.java b/pythonforandroid/bootstraps/service_only/build/src/main/java/org/kivy/android/PythonActivity.java index 5d532de29a..9bffcc9b28 100644 --- a/pythonforandroid/bootstraps/service_only/build/src/main/java/org/kivy/android/PythonActivity.java +++ b/pythonforandroid/bootstraps/service_only/build/src/main/java/org/kivy/android/PythonActivity.java @@ -286,27 +286,22 @@ public static void _do_start_service( 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); + Intent serviceIntent = + PythonServiceIntent.buildActivityService( + PythonActivity.mActivity, + PythonService.class, + "service/" + entry_point, + serviceTitle, + serviceDescription, + showForegroundNotification, + pythonServiceArgument); PythonActivity.mActivity.startService(serviceIntent); } public static void stop_service() { - Intent serviceIntent = new Intent(PythonActivity.mActivity, PythonService.class); - PythonActivity.mActivity.stopService(serviceIntent); + PythonServiceIntent.stop(PythonActivity.mActivity, PythonService.class); } public static native void nativeSetenv(String name, String value); diff --git a/pythonforandroid/bootstraps/service_only/build/templates/Service.tmpl.java b/pythonforandroid/bootstraps/service_only/build/templates/Service.tmpl.java index eeda810bef..853262a1c6 100644 --- a/pythonforandroid/bootstraps/service_only/build/templates/Service.tmpl.java +++ b/pythonforandroid/bootstraps/service_only/build/templates/Service.tmpl.java @@ -5,6 +5,8 @@ import android.content.Intent; import android.content.Context; import org.kivy.android.PythonService; +import org.kivy.android.PythonServiceIntent; +import org.kivy.android.PythonUtil; public class Service{{ name|capitalize }} extends PythonService { /** @@ -28,21 +30,8 @@ protected int getServiceId() { } public static void start(Context ctx, String pythonServiceArgument) { - String argument = ctx.getFilesDir().getAbsolutePath() + "/app"; - Intent intent = new Intent(ctx, Service{{ name|capitalize }}.class); - intent.putExtra("androidPrivate", argument); - intent.putExtra("androidArgument", argument); - intent.putExtra("serviceEntrypoint", "{{ entrypoint }}"); - intent.putExtra("serviceTitle", "{{ name|capitalize }}"); - intent.putExtra("pythonName", "{{ name }}"); - intent.putExtra("serviceStartAsForeground", "{{ foreground|lower }}"); - intent.putExtra("pythonHome", argument); - intent.putExtra("androidUnpack", argument); - intent.putExtra("pythonPath", argument + ":" + argument + "/lib"); - intent.putExtra("pythonServiceArgument", pythonServiceArgument); - intent.putExtra("smallIconName", ""); - intent.putExtra("contentTitle", "{{ name|capitalize }}"); - intent.putExtra("contentText", ""); + Intent intent = getDefaultIntent(ctx, "", "{{ name|capitalize }}", "", + pythonServiceArgument); ctx.startService(intent); } @@ -50,27 +39,34 @@ public static void start(Context ctx, String smallIconName, String contentTitle, String contentText, String pythonServiceArgument) { - String argument = ctx.getFilesDir().getAbsolutePath() + "/app"; - Intent intent = new Intent(ctx, Service{{ name|capitalize }}.class); - intent.putExtra("androidPrivate", argument); - intent.putExtra("androidArgument", argument); - intent.putExtra("serviceEntrypoint", "{{ entrypoint }}"); - intent.putExtra("serviceTitle", "{{ name|capitalize }}"); - intent.putExtra("pythonName", "{{ name }}"); - intent.putExtra("serviceStartAsForeground", "{{ foreground|lower }}"); - intent.putExtra("pythonHome", argument); - intent.putExtra("androidUnpack", argument); - intent.putExtra("pythonPath", argument + ":" + argument + "/lib"); - intent.putExtra("pythonServiceArgument", pythonServiceArgument); - intent.putExtra("smallIconName", smallIconName); - intent.putExtra("contentTitle", contentTitle); - intent.putExtra("contentText", contentText); + Intent intent = getDefaultIntent(ctx, smallIconName, contentTitle, + contentText, pythonServiceArgument); ctx.startService(intent); } + + public static Intent getDefaultIntent(Context ctx, String smallIconName, + String contentTitle, String contentText, + String pythonServiceArgument) { + String appRoot = PythonUtil.getAppRoot(ctx); + return PythonServiceIntent.buildWithPaths( + ctx, + Service{{ name|capitalize }}.class, + appRoot, + appRoot, + appRoot, + "{{ entrypoint }}", + "{{ name|capitalize }}", + null, + "{{ name }}", + "{{ foreground|lower }}", + pythonServiceArgument, + smallIconName, + contentTitle, + contentText); + } public static void stop(Context ctx) { - Intent intent = new Intent(ctx, Service{{ name|capitalize }}.class); - ctx.stopService(intent); + PythonServiceIntent.stop(ctx, Service{{ name|capitalize }}.class); } /** diff --git a/pythonforandroid/bootstraps/webview/build/src/main/java/org/kivy/android/PythonActivity.java b/pythonforandroid/bootstraps/webview/build/src/main/java/org/kivy/android/PythonActivity.java index 9ad9503a6f..f0e384adaa 100644 --- a/pythonforandroid/bootstraps/webview/build/src/main/java/org/kivy/android/PythonActivity.java +++ b/pythonforandroid/bootstraps/webview/build/src/main/java/org/kivy/android/PythonActivity.java @@ -463,27 +463,22 @@ public static void _do_start_service( 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); + Intent serviceIntent = + PythonServiceIntent.buildActivityService( + PythonActivity.mActivity, + PythonService.class, + "service/" + entry_point, + serviceTitle, + serviceDescription, + showForegroundNotification, + pythonServiceArgument); PythonActivity.mActivity.startService(serviceIntent); } public static void stop_service() { - Intent serviceIntent = new Intent(PythonActivity.mActivity, PythonService.class); - PythonActivity.mActivity.stopService(serviceIntent); + PythonServiceIntent.stop(PythonActivity.mActivity, PythonService.class); } public static native void nativeSetenv(String name, String value); From f72e940307e0c746d61e29ca9d61891d08048335 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Sun, 17 May 2026 19:52:07 +0000 Subject: [PATCH 39/82] :safety_vest: Guard Android versionCode values Validate generated and explicit Android versionCode values before rendering Gradle or manifest templates. This keeps valid legacy generated values unchanged while failing early when versionCode is non-integer, non-positive, or above Google Play's documented 2100000000 maximum. Document the versionName/versionCode split with a reference to the Android versioning docs, and cover the helper behavior with focused bootstrap build tests. Upstream reference: https://developer.android.com/tools/publishing/versioning --- doc/source/buildoptions.rst | 18 ++- .../bootstraps/common/build/build.py | 106 ++++++++++++++---- tests/test_bootstrap_build.py | 69 ++++++++++-- 3 files changed, 162 insertions(+), 31 deletions(-) diff --git a/doc/source/buildoptions.rst b/doc/source/buildoptions.rst index 167f4fd718..ac1f3040bf 100644 --- a/doc/source/buildoptions.rst +++ b/doc/source/buildoptions.rst @@ -56,7 +56,14 @@ options (this list may not be exhaustive): - ``--private``: The directory containing your project files. - ``--package``: The Java package name for your project. e.g. ``org.example.yourapp``. - ``--name``: The app name. -- ``--version``: The version number. +- ``--version``: The display version shown to users. On Android this is + rendered as ``versionName``. +- ``--numeric-version``: The Android ``versionCode`` used for update ordering. + This must be a positive integer no greater than ``2100000000``. If omitted, + python-for-android computes it from ``--version``. If the computed value is + too large, keep the display version in ``--version`` and set a valid + ``--numeric-version``. See Android's + `versionCode documentation `__. - ``--orientation``: The orientations that the app will display in. (Available options are ``portrait``, ``landscape``, ``portrait-reverse``, ``landscape-reverse``). Since Android ignores ``android:screenOrientation`` when in multi-window mode @@ -145,7 +152,14 @@ ready. - ``--private``: The directory containing your project files. - ``--package``: The Java package name for your project. e.g. ``org.example.yourapp``. - ``--name``: The app name. -- ``--version``: The version number. +- ``--version``: The display version shown to users. On Android this is + rendered as ``versionName``. +- ``--numeric-version``: The Android ``versionCode`` used for update ordering. + This must be a positive integer no greater than ``2100000000``. If omitted, + python-for-android computes it from ``--version``. If the computed value is + too large, keep the display version in ``--version`` and set a valid + ``--numeric-version``. See Android's + `versionCode documentation `__. - ``--orientation``: The orientations that the app will display in. (Available options are ``portrait``, ``landscape``, ``portrait-reverse``, ``landscape-reverse``). Since Android ignores ``android:screenOrientation`` when in multi-window mode diff --git a/pythonforandroid/bootstraps/common/build/build.py b/pythonforandroid/bootstraps/common/build/build.py index e2aacc7ac8..2eb2d555fc 100644 --- a/pythonforandroid/bootstraps/common/build/build.py +++ b/pythonforandroid/bootstraps/common/build/build.py @@ -93,6 +93,73 @@ def get_bootstrap_name(): DEFAULT_PYTHON_ACTIVITY_JAVA_CLASS = 'org.kivy.android.PythonActivity' DEFAULT_PYTHON_SERVICE_JAVA_CLASS = 'org.kivy.android.PythonService' +# Google Play's documented maximum Android versionCode. +# https://developer.android.com/tools/publishing/versioning +MAX_ANDROID_VERSION_CODE = 2100000000 + + +def get_android_numeric_version(version, min_sdk_version): + """ + Generate the default Android versionCode value from --version. + + The format is (10 + minsdk + app_version). Older versioning was + (arch + minsdk + app_version), with arch expressed with a single digit + from 6 to 9. Since multi-arch support, this uses 10. + """ + version_code = 0 + try: + for part in version.split('.'): + version_code *= 100 + version_code += int(part) + except ValueError as exc: + raise ValueError( + "Could not generate Android versionCode from --version " + "{!r}. --version is Android versionName; when it is not numeric " + "dot-separated text, set --numeric-version to a positive Android " + "versionCode integer no greater than {}.".format( + version, MAX_ANDROID_VERSION_CODE + ) + ) from exc + return "{}{}{}".format("10", min_sdk_version, version_code) + + +def validate_android_numeric_version(numeric_version, *, generated_from_version=None): + try: + normalized_version = int(numeric_version) + except (TypeError, ValueError) as exc: + raise ValueError( + "--numeric-version must be a decimal integer Android versionCode " + "greater than 0 and no greater than {}; got {!r}.".format( + MAX_ANDROID_VERSION_CODE, numeric_version + ) + ) from exc + + if normalized_version <= 0: + raise ValueError( + "--numeric-version must be a positive Android versionCode " + "greater than 0; got {!r}.".format(numeric_version) + ) + + if normalized_version > MAX_ANDROID_VERSION_CODE: + if generated_from_version is not None: + raise ValueError( + "Generated Android versionCode {} from --version {!r}, " + "which exceeds the maximum {}. --version is Android " + "versionName; keep this display version by setting " + "--numeric-version to a positive Android versionCode no " + "greater than {}.".format( + normalized_version, + generated_from_version, + MAX_ANDROID_VERSION_CODE, + MAX_ANDROID_VERSION_CODE, + ) + ) + raise ValueError( + "--numeric-version is Android versionCode and must not exceed " + "{}; got {!r}.".format(MAX_ANDROID_VERSION_CODE, numeric_version) + ) + + return str(normalized_version) def render(template, dest, **kwargs): @@ -420,19 +487,17 @@ def make_package(args): versioned_name = (args.name.replace(' ', '').replace('\'', '') + '-' + args.version) - version_code = 0 - if not args.numeric_version: - """ - Set version code in format (10 + minsdk + app_version) - Historically versioning was (arch + minsdk + app_version), - with arch expressed with a single digit from 6 to 9. - Since the multi-arch support, has been changed to 10. - """ - 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) + generated_from_version = None + if args.numeric_version is None: + generated_from_version = args.version + args.numeric_version = get_android_numeric_version( + args.version, + args.min_sdk_version, + ) + args.numeric_version = validate_android_numeric_version( + args.numeric_version, + generated_from_version=generated_from_version, + ) if args.intent_filters: with open(args.intent_filters) as fd: @@ -793,14 +858,15 @@ def create_argument_parser(): help=('The human-readable name of the project.'), required=True) ap.add_argument('--numeric-version', dest='numeric_version', - help=('The numeric version number of the project. If not ' - 'given, this is automatically computed from the ' - 'version.')) + help=('The Android versionCode of the project. This must ' + 'be a positive decimal integer no greater than ' + '{}. If not given, it is automatically computed ' + 'from --version.').format(MAX_ANDROID_VERSION_CODE)) ap.add_argument('--version', dest='version', - help=('The version number of the project. This should ' - 'consist of numbers and dots, and should have the ' - 'same number of groups of numbers as previous ' - 'versions.'), + help=('The Android versionName of the project, shown to ' + 'users as the display version. Use ' + '--numeric-version to control Android versionCode ' + 'and update ordering.'), required=True) if is_sdl_bootstrap(): ap.add_argument('--launcher', dest='launcher', action='store_true', diff --git a/tests/test_bootstrap_build.py b/tests/test_bootstrap_build.py index ff5f7dcacc..e78c2e5778 100644 --- a/tests/test_bootstrap_build.py +++ b/tests/test_bootstrap_build.py @@ -6,18 +6,22 @@ from pythonforandroid.util import load_source -class TestBootstrapBuild(unittest.TestCase): - def setUp(self): - os.environ["P4A_BUILD_IS_RUNNING_UNITTESTS"] = "1" +def load_bootstrap_build_module(): + os.environ["P4A_BUILD_IS_RUNNING_UNITTESTS"] = "1" - build_src = os.path.join( - os.path.dirname(os.path.abspath(__file__)), - "../pythonforandroid/bootstraps/common/build/build.py", - ) + build_src = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "../pythonforandroid/bootstraps/common/build/build.py", + ) - self.buildpy = load_source("buildpy", build_src) - self.buildpy.get_bootstrap_name = mock.Mock(return_value="sdl2") + buildpy = load_source("buildpy", build_src) + buildpy.get_bootstrap_name = mock.Mock(return_value="sdl2") + return buildpy + +class TestBootstrapBuild(unittest.TestCase): + def setUp(self): + self.buildpy = load_bootstrap_build_module() self.ap = self.buildpy.create_argument_parser() self.common_args = [ @@ -178,3 +182,50 @@ def test_sdl_orientation_hint_multiple(self): assert "LandscapeLeft" in sdl_orientation_hint assert "Portrait" in sdl_orientation_hint + + +class TestAndroidNumericVersion: + def setup_method(self): + self.buildpy = load_bootstrap_build_module() + + def test_generates_default_three_part_version_code(self): + assert self.buildpy.get_android_numeric_version("1.0.5", 24) == "102410005" + + def test_accepts_and_normalizes_explicit_numeric_version(self): + assert self.buildpy.validate_android_numeric_version("0000001") == "1" + assert self.buildpy.validate_android_numeric_version(2100000000) == "2100000000" + + @pytest.mark.parametrize("numeric_version", ["abc", "1.2", "", None]) + def test_rejects_non_integer_explicit_numeric_versions(self, numeric_version): + with pytest.raises(ValueError, match="--numeric-version.*decimal integer"): + self.buildpy.validate_android_numeric_version(numeric_version) + + @pytest.mark.parametrize("numeric_version", ["0", 0, "-1", -1]) + def test_rejects_non_positive_explicit_numeric_versions(self, numeric_version): + with pytest.raises(ValueError, match="--numeric-version.*greater than 0"): + self.buildpy.validate_android_numeric_version(numeric_version) + + @pytest.mark.parametrize("numeric_version", ["2100000001", 2100000001]) + def test_rejects_oversized_explicit_numeric_versions(self, numeric_version): + with pytest.raises( + ValueError, match="--numeric-version.*2100000000" + ): + self.buildpy.validate_android_numeric_version(numeric_version) + + def test_rejects_generated_overflow_and_mentions_version_name(self): + generated_version = self.buildpy.get_android_numeric_version("1.0.5.1", 24) + + with pytest.raises( + ValueError, + match="Generated Android versionCode .*--version '1\\.0\\.5\\.1'.*--numeric-version.*2100000000", + ): + self.buildpy.validate_android_numeric_version( + generated_version, generated_from_version="1.0.5.1" + ) + + def test_rejects_non_numeric_version_name_for_generation(self): + with pytest.raises( + ValueError, + match="Could not generate Android versionCode from --version '1\\.0\\.beta'.*versionName.*--numeric-version", + ): + self.buildpy.get_android_numeric_version("1.0.beta", 24) From 2206b237eea31dae8e04fd70417410e50f8a3b0f Mon Sep 17 00:00:00 2001 From: Ansh Dadwal Date: Thu, 21 May 2026 17:15:02 +0530 Subject: [PATCH 40/82] Fix libpython link --- pythonforandroid/recipe.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pythonforandroid/recipe.py b/pythonforandroid/recipe.py index d5ff3ad52a..3132a5d39d 100644 --- a/pythonforandroid/recipe.py +++ b/pythonforandroid/recipe.py @@ -1627,6 +1627,7 @@ def get_recipe_env(self, arch, **kwargs): env["RUSTFLAGS"] = "-Clink-args=-L{} -L{}".format( self.ctx.get_libs_dir(arch.arch), join(realpython_dir, "android-build") ) + env["RUSTFLAGS"] += f" -Clink-arg=-lpython{self.ctx.python_recipe.link_version}" env["PYO3_CROSS_LIB_DIR"] = realpath(glob.glob(join( realpython_dir, "android-build", "build", From a184a16852040a9d835bb3258a86f517e7ba933a Mon Sep 17 00:00:00 2001 From: Ansh Dadwal Date: Fri, 22 May 2026 08:39:16 +0530 Subject: [PATCH 41/82] Add patches --- pythonforandroid/recipes/av/__init__.py | 1 + pythonforandroid/recipes/av/libs.patch | 38 +++++++++++++++++++ pythonforandroid/recipes/libshine/__init__.py | 2 +- .../recipes/libshine/fixbuild.patch | 12 ++++++ 4 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 pythonforandroid/recipes/av/libs.patch create mode 100644 pythonforandroid/recipes/libshine/fixbuild.patch diff --git a/pythonforandroid/recipes/av/__init__.py b/pythonforandroid/recipes/av/__init__.py index c765eafe98..ef411ae507 100644 --- a/pythonforandroid/recipes/av/__init__.py +++ b/pythonforandroid/recipes/av/__init__.py @@ -7,6 +7,7 @@ class PyAVRecipe(PyProjectRecipe): name = "av" version = "17.0.0" url = "https://github.com/PyAV-Org/PyAV/archive/v{version}.zip" + patches = ["libs.patch"] depends = ["python3", "ffmpeg", "av_codecs", "openssl"] hostpython_prerequisites = ["cython>=3.1.0"] diff --git a/pythonforandroid/recipes/av/libs.patch b/pythonforandroid/recipes/av/libs.patch new file mode 100644 index 0000000000..74fb90c91f --- /dev/null +++ b/pythonforandroid/recipes/av/libs.patch @@ -0,0 +1,38 @@ +diff '--color=auto' -uNr PyAV-17.0.0/setup.py PyAV-17.0.0.mod/setup.py +--- PyAV-17.0.0/setup.py 2026-03-14 19:42:41.000000000 +0530 ++++ PyAV-17.0.0.mod/setup.py 2026-05-22 08:21:47.438004827 +0530 +@@ -79,20 +79,21 @@ + """ + Get distutils-compatible extension arguments using pkg-config. + """ +- pkg_config = os.environ.get("PKG_CONFIG", "pkg-config") +- try: +- raw_cflags = subprocess.check_output( +- [pkg_config, "--cflags", "--libs"] +- + ["lib" + name for name in FFMPEG_LIBRARIES] +- ) +- except FileNotFoundError: +- print(f"{pkg_config} is required for building PyAV") +- exit(1) +- except subprocess.CalledProcessError: +- print(f"{pkg_config} could not find libraries {FFMPEG_LIBRARIES}") +- exit(1) ++ # pkg_config = os.environ.get("PKG_CONFIG", "pkg-config") ++ # try: ++ # raw_cflags = subprocess.check_output( ++ # [pkg_config, "--cflags", "--libs"] ++ # + ["lib" + name for name in FFMPEG_LIBRARIES] ++ # ) ++ # except FileNotFoundError: ++ # print(f"{pkg_config} is required for building PyAV") ++ # exit(1) ++ # except subprocess.CalledProcessError: ++ # print(f"{pkg_config} could not find libraries {FFMPEG_LIBRARIES}") ++ # exit(1) + +- known, unknown = parse_cflags(raw_cflags.decode("utf-8")) ++ raw_cflags = "-lavdevice -lavfilter -lavformat -lavcodec -lswscale -lswresample -lavutil" ++ known, unknown = parse_cflags(raw_cflags) + if unknown: + print("pkg-config returned flags we don't understand: {}".format(unknown)) + if "-pthread" in unknown: diff --git a/pythonforandroid/recipes/libshine/__init__.py b/pythonforandroid/recipes/libshine/__init__.py index 32fa9e175d..7f385b76db 100644 --- a/pythonforandroid/recipes/libshine/__init__.py +++ b/pythonforandroid/recipes/libshine/__init__.py @@ -9,7 +9,7 @@ class LibShineRecipe(Recipe): version = 'c72aba9031bde18a0995e7c01c9b53f2e08a0e46' url = 'https://github.com/toots/shine/archive/{version}.zip' - + patches = ["fixbuild.patch"] built_libraries = {'libshine.so': 'lib'} def get_recipe_env(self, arch=None, with_flags_in_cc=True): diff --git a/pythonforandroid/recipes/libshine/fixbuild.patch b/pythonforandroid/recipes/libshine/fixbuild.patch new file mode 100644 index 0000000000..be6d0f604e --- /dev/null +++ b/pythonforandroid/recipes/libshine/fixbuild.patch @@ -0,0 +1,12 @@ +diff '--color=auto' -uNr shine-c72aba9031bde18a0995e7c01c9b53f2e08a0e46/src/lib/l3mdct.h shine-c72aba9031bde18a0995e7c01c9b53f2e08a0e46.mod/src/lib/l3mdct.h +--- shine-c72aba9031bde18a0995e7c01c9b53f2e08a0e46/src/lib/l3mdct.h 2017-08-01 19:14:17.000000000 +0530 ++++ shine-c72aba9031bde18a0995e7c01c9b53f2e08a0e46.mod/src/lib/l3mdct.h 2026-05-22 08:30:59.625697302 +0530 +@@ -1,7 +1,7 @@ + #ifndef shine_MDCT_H + #define shine_MDCT_H + +-void shine_mdct_initialise(); ++void shine_mdct_initialise(shine_global_config *config); + void shine_mdct_sub(shine_global_config *config, int stride); + + #endif From 6af08d093120b6dfa6062db4de7ef28f267b086d Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Thu, 21 May 2026 19:10:54 +0000 Subject: [PATCH 42/82] :memo: Document PyProjectRecipe usage Add PyProjectRecipe guidance for modern pyproject.toml packages, including the wheel-oriented build flow and notes on dependency, host build, patch, and environment customization, refs #3326 --- doc/source/recipes.rst | 53 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/doc/source/recipes.rst b/doc/source/recipes.rst index b6e34319b3..93fa5eec7c 100644 --- a/doc/source/recipes.rst +++ b/doc/source/recipes.rst @@ -123,10 +123,11 @@ This is the core of what's necessary to write a recipe, but has not covered any of the details of how one actually writes code to compile for android. This is covered in the next sections, including the `standard mechanisms `_ used as part of the -build, and the details of specific recipe classes for Python, Cython, -and some generic compiled recipes. If your module is one of the -latter, you should use these later classes rather than reimplementing -the functionality from scratch. +build, and the details of specific recipe classes for modern Python +packages, older setup.py-based packages, Cython, and some generic +compiled recipes. If your module is one of the latter, you should use +these later classes rather than reimplementing the functionality from +scratch. .. _standard_mechanisms: @@ -310,6 +311,10 @@ For reference, the code that accomplishes this is the following:: This combines techniques and tools from the above documentation to create a generic mechanism for all Python modules. +For Python packages that use ``pyproject.toml``, you should normally use +``PyProjectRecipe`` instead. ``PythonRecipe`` is based on the older +``setup.py install`` flow. + .. note:: The hostpython is the path to the Python binary that should be used for any kind of installation. You *must* run Python in a similar way if you need to do so in any of your own @@ -380,6 +385,43 @@ patching to remove this import or make it fail quietly. Other than this, these methods follow the techniques in the above documentation to make a generic recipe for most cython based modules. +Using a PyProjectRecipe +----------------------- + +For modern Python packages that contain ``pyproject.toml``, you should +normally use ``PyProjectRecipe``. It builds and installs packages as +wheels, which matches current Python packaging tools more closely than +the older ``setup.py install`` flow. + +For instance:: + + from pythonforandroid.recipe import PyProjectRecipe + + class ExampleRecipe(PyProjectRecipe): + version = '1.2.3' + url = 'https://example.com/example-{version}.tar.gz' + depends = ['pycparser', 'libffi'] + + recipe = ExampleRecipe() + +You do not need to include ``python3`` in ``depends``; even when a recipe +overrides ``depends``, ``PythonRecipe`` adds the ``python3`` dependency. + +The base class uses a wheel-oriented build and install flow. It can use +a compatible prebuilt Android wheel when that path is enabled and a +matching wheel is available. Otherwise, it installs the host build +requirements, runs ``python -m build --wheel``, applies Android platform +tags to the built wheel, optionally copies the wheel to configured +wheel-save directories, and installs the selected wheel into the target +Python install directory. + +You may still need to add normal recipe metadata such as ``depends`` for +libraries or Python packages that must be built first. Packages with +extra host-side build requirements can add ``hostpython_prerequisites``. +Packages that need Android-specific changes may still need patches or a +``get_recipe_env()`` override to adjust compiler flags, include paths, or +other build environment variables. + Using a CompiledComponentsPythonRecipe -------------------------------------- @@ -506,6 +548,3 @@ how to create your own Recipe subclass. .. autoclass:: toolchain.Recipe :members: :member-order: bysource - - - From 4d80da2633f56fb567141dd92a0c6fb361425337 Mon Sep 17 00:00:00 2001 From: Ansh Dadwal Date: Sun, 24 May 2026 00:19:28 +0530 Subject: [PATCH 43/82] `recipes`: add `thorvg` (#3288) * `recipes`: add `thorvg` * kivy thorvg support --- pythonforandroid/recipes/jpeg/__init__.py | 13 ++- .../recipes/jpeg/build-static.patch | 85 --------------- .../recipes/jpeg/remove-version.patch | 12 --- pythonforandroid/recipes/kivy/__init__.py | 11 +- .../recipes/libthorvg/__init__.py | 100 ++++++++++++++++++ .../recipes/libthorvg/meson.patch | 77 ++++++++++++++ .../recipes/thorvg-python/__init__.py | 12 +++ .../recipes/thorvg-python/sharedlib.patch | 43 ++++++++ 8 files changed, 247 insertions(+), 106 deletions(-) delete mode 100644 pythonforandroid/recipes/jpeg/build-static.patch delete mode 100644 pythonforandroid/recipes/jpeg/remove-version.patch create mode 100644 pythonforandroid/recipes/libthorvg/__init__.py create mode 100644 pythonforandroid/recipes/libthorvg/meson.patch create mode 100644 pythonforandroid/recipes/thorvg-python/__init__.py create mode 100644 pythonforandroid/recipes/thorvg-python/sharedlib.patch diff --git a/pythonforandroid/recipes/jpeg/__init__.py b/pythonforandroid/recipes/jpeg/__init__.py index 33a9ba44da..3060c9b8ca 100644 --- a/pythonforandroid/recipes/jpeg/__init__.py +++ b/pythonforandroid/recipes/jpeg/__init__.py @@ -14,9 +14,7 @@ class JpegRecipe(Recipe): name = 'jpeg' version = '2.0.1' url = 'https://github.com/libjpeg-turbo/libjpeg-turbo/archive/{version}.tar.gz' # noqa - built_libraries = {'libjpeg.a': '.', 'libturbojpeg.a': '.'} - # we will require this below patch to build the shared library - # patches = ['remove-version.patch'] + built_libraries = {'libjpeg.so': '.', 'libturbojpeg.so': '.'} def build_arch(self, arch): build_dir = self.get_build_dir(arch.arch) @@ -34,6 +32,8 @@ def build_arch(self, arch): '-DCMAKE_ANDROID_ARCH_ABI={arch}'.format(arch=arch.arch), '-DCMAKE_ANDROID_NDK=' + self.ctx.ndk_dir, '-DCMAKE_C_COMPILER={cc}'.format(cc=arch.get_clang_exe()), + f'-DCMAKE_ASM_COMPILER={arch.get_clang_exe()}', + f'-DCMAKE_ASM_FLAGS=--target={arch.target}', '-DCMAKE_CXX_COMPILER={cc_plus}'.format( cc_plus=arch.get_clang_exe(plus_plus=True)), '-DCMAKE_BUILD_TYPE=Release', @@ -42,12 +42,11 @@ def build_arch(self, arch): '-DANDROID_ABI={arch}'.format(arch=arch.arch), '-DANDROID_ARM_NEON=ON', - '-DENABLE_NEON=ON', - # '-DREQUIRE_SIMD=1', + '-DWITH_SIMD=1', + '-DREQUIRE_SIMD=1', # Force disable shared, with the static ones is enough - '-DENABLE_SHARED=0', - '-DENABLE_STATIC=1', + '-DENABLE_SHARED=1', # Fix cmake compatibility issue '-DCMAKE_POLICY_VERSION_MINIMUM=3.5', diff --git a/pythonforandroid/recipes/jpeg/build-static.patch b/pythonforandroid/recipes/jpeg/build-static.patch deleted file mode 100644 index 0aa9c70a98..0000000000 --- a/pythonforandroid/recipes/jpeg/build-static.patch +++ /dev/null @@ -1,85 +0,0 @@ -diff -Naur jpeg/Android.mk b/Android.mk ---- jpeg/Android.mk 2015-12-14 11:37:25.900190235 -0600 -+++ b/Android.mk 2015-12-14 11:41:27.532182210 -0600 -@@ -54,8 +54,7 @@ - - LOCAL_SRC_FILES:= $(libjpeg_SOURCES_DIST) - --LOCAL_SHARED_LIBRARIES := libcutils --LOCAL_STATIC_LIBRARIES := libsimd -+LOCAL_STATIC_LIBRARIES := libsimd libcutils - - LOCAL_C_INCLUDES := $(LOCAL_PATH) - -@@ -68,7 +67,7 @@ - - LOCAL_MODULE := libjpeg - --include $(BUILD_SHARED_LIBRARY) -+include $(BUILD_STATIC_LIBRARY) - - ###################################################### - ### cjpeg ### -@@ -82,7 +81,7 @@ - - LOCAL_SRC_FILES:= $(cjpeg_SOURCES) - --LOCAL_SHARED_LIBRARIES := libjpeg -+LOCAL_STATIC_LIBRARIES := libjpeg - - LOCAL_C_INCLUDES := $(LOCAL_PATH) \ - $(LOCAL_PATH)/android -@@ -110,7 +109,7 @@ - - LOCAL_SRC_FILES:= $(djpeg_SOURCES) - --LOCAL_SHARED_LIBRARIES := libjpeg -+LOCAL_STATIC_LIBRARIES := libjpeg - - LOCAL_C_INCLUDES := $(LOCAL_PATH) \ - $(LOCAL_PATH)/android -@@ -137,7 +136,7 @@ - - LOCAL_SRC_FILES:= $(jpegtran_SOURCES) - --LOCAL_SHARED_LIBRARIES := libjpeg -+LOCAL_STATIC_LIBRARIES := libjpeg - - LOCAL_C_INCLUDES := $(LOCAL_PATH) \ - $(LOCAL_PATH)/android -@@ -163,7 +162,7 @@ - - LOCAL_SRC_FILES:= $(tjunittest_SOURCES) - --LOCAL_SHARED_LIBRARIES := libjpeg -+LOCAL_STATIC_LIBRARIES := libjpeg - - LOCAL_C_INCLUDES := $(LOCAL_PATH) - -@@ -189,7 +188,7 @@ - - LOCAL_SRC_FILES:= $(tjbench_SOURCES) - --LOCAL_SHARED_LIBRARIES := libjpeg -+LOCAL_STATIC_LIBRARIES := libjpeg - - LOCAL_C_INCLUDES := $(LOCAL_PATH) - -@@ -215,7 +214,7 @@ - - LOCAL_SRC_FILES:= $(rdjpgcom_SOURCES) - --LOCAL_SHARED_LIBRARIES := libjpeg -+LOCAL_STATIC_LIBRARIES := libjpeg - - LOCAL_C_INCLUDES := $(LOCAL_PATH) - -@@ -240,7 +239,7 @@ - - LOCAL_SRC_FILES:= $(wrjpgcom_SOURCES) - --LOCAL_SHARED_LIBRARIES := libjpeg -+LOCAL_STATIC_LIBRARIES := libjpeg - - LOCAL_C_INCLUDES := $(LOCAL_PATH) - diff --git a/pythonforandroid/recipes/jpeg/remove-version.patch b/pythonforandroid/recipes/jpeg/remove-version.patch deleted file mode 100644 index 311aa33bc4..0000000000 --- a/pythonforandroid/recipes/jpeg/remove-version.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- jpeg/CMakeLists.txt.orig 2018-11-12 20:20:28.000000000 +0100 -+++ jpeg/CMakeLists.txt 2018-12-14 12:43:45.338704504 +0100 -@@ -573,6 +573,9 @@ - add_library(turbojpeg SHARED ${TURBOJPEG_SOURCES}) - set_property(TARGET turbojpeg PROPERTY COMPILE_FLAGS - "-DBMP_SUPPORTED -DPPM_SUPPORTED") -+ set_property(TARGET jpeg PROPERTY NO_SONAME 1) -+ set_property(TARGET turbojpeg PROPERTY NO_SONAME 1) -+ set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "") - if(WIN32) - set_target_properties(turbojpeg PROPERTIES DEFINE_SYMBOL DLLDEFINE) - endif() diff --git a/pythonforandroid/recipes/kivy/__init__.py b/pythonforandroid/recipes/kivy/__init__.py index 2446c2101b..247e252215 100644 --- a/pythonforandroid/recipes/kivy/__init__.py +++ b/pythonforandroid/recipes/kivy/__init__.py @@ -3,7 +3,7 @@ import packaging.version import sh -from pythonforandroid.recipe import PyProjectRecipe +from pythonforandroid.recipe import PyProjectRecipe, Recipe from pythonforandroid.toolchain import current_directory, shprint @@ -33,7 +33,7 @@ class KivyRecipe(PyProjectRecipe): url = 'https://github.com/kivy/kivy/archive/{version}.zip' name = 'kivy' - depends = [('sdl2', 'sdl3'), 'pyjnius', 'setuptools', 'android'] + depends = [('sdl2', 'sdl3'), 'pyjnius', 'setuptools', 'android', 'libthorvg'] python_depends = ['certifi', 'chardet', 'idna', 'requests', 'urllib3', 'filetype'] hostpython_prerequisites = ["cython>=0.29.1,<=3.0.12"] @@ -70,6 +70,13 @@ def get_recipe_env(self, arch, **kwargs): if not is_kivy_less_than_3(self, arch): env['KIVY_CROSS_PLATFORM'] = 'android' + # thorvg headers + env['KIVY_THORVG_LIB_DIR'] = self.ctx.get_libs_dir(arch.arch) + env['KIVY_THORVG_INCLUDE_DIR'] = join( + Recipe.get_recipe('libthorvg', self.ctx).get_include_dir(arch), + 'thorvg-1' + ) + if 'sdl2' in self.ctx.recipe_build_order: env['USE_SDL2'] = '1' env['KIVY_SPLIT_EXAMPLES'] = '1' diff --git a/pythonforandroid/recipes/libthorvg/__init__.py b/pythonforandroid/recipes/libthorvg/__init__.py new file mode 100644 index 0000000000..bb05c37a1f --- /dev/null +++ b/pythonforandroid/recipes/libthorvg/__init__.py @@ -0,0 +1,100 @@ +from pythonforandroid.recipe import Recipe, MesonRecipe +from os.path import join +from pythonforandroid.util import ensure_dir, current_directory +from pythonforandroid.logger import shprint +from multiprocessing import cpu_count +from glob import glob +import sh + + +class LibThorVGRecipe(MesonRecipe): + name = "libthorvg" + version = "1.0.5" + url = "https://github.com/thorvg/thorvg/archive/refs/tags/v{version}.tar.gz" + config_otps = [ + "-Dsimd=true", + "-Dbindings=capi", + "-Dtools=all", + "-Dengines=cpu,gl", + "-Dloaders=svg,png,jpg,ttf,webp", + "-Dextra=opengl_es,lottie_exp,openmp", + ] + need_stl_shared = True + skip_python = True + depends = ["png", "libwebp", "jpeg"] + patches = ["meson.patch"] + bins = ["tvg-lottie2gif", "tvg-svg2png"] + built_libraries = { + "libthorvg-1.so": "install/lib", + "libomp.so": "install/lib" + } + for bin in bins: + built_libraries[f"lib{bin}bin.so"] = "install/bin" + + def should_build(self, arch): + return Recipe.should_build(self, arch) + + def get_include_dir(self, arch): + return join(self.get_build_dir(arch.arch), "install", "include") + + def build_arch(self, arch): + super().build_arch(arch) + build_dir = self.get_build_dir(arch.arch) + install_dir = join(build_dir, "install") + ensure_dir(install_dir) + env = self.get_recipe_env(arch) + + lib_dir = self.ctx.get_libs_dir(arch.arch) + png_include = self.get_recipe("png", self.ctx).get_build_dir(arch.arch) + webp_include = join( + self.get_recipe("libwebp", self.ctx).get_build_dir(arch.arch), "src" + ) + jpg_dir = self.get_recipe("jpeg", self.ctx).get_build_dir(arch.arch) + + with current_directory(build_dir): + + shprint( + sh.meson, + "setup", + "builddir", + "--cross-file", + join("/tmp", "android.meson.cross"), + f"--prefix={install_dir}", + # config opts + *self.config_otps, + # deps + f"-Dpng_include_dir={png_include}", + f"-Dpng_lib_dir={lib_dir}", + f"-Dwebp_include_dir={webp_include}", + f"-Dwebp_lib_dir={lib_dir}", + f"-Djpg_include_dir={jpg_dir}", + f"-Djpg_lib_dir={jpg_dir}", + _env=env, + ) + + shprint(sh.ninja, "-C", "builddir", "-j", str(cpu_count()), _env=env) + shprint(sh.rm, "-rf", install_dir) + shprint(sh.mkdir, install_dir) + shprint(sh.ninja, "-C", "builddir", "install", _env=env) + + # copy libomp.so + arch_map = { + "arm64-v8a": "aarch64", + "armeabi-v7a": "arm", + "x86": "i386", + "x86_64": "x86_64", + } + lib_arch = arch_map[arch.arch] + # clang version directory is variable, so glob it + pattern = join(self.ctx.ndk.llvm_prebuilt_dir, "lib/clang/*/lib/linux", lib_arch) + clang_lib_dir = glob(pattern)[0] + libomp = join(clang_lib_dir, "libomp.so") + shprint(sh.cp, libomp, join("install", "lib")) + + # setup bins + bin_dir = join("install", "bin") + for bin in self.bins: + shprint(sh.cp, join(bin_dir, bin), join(bin_dir, f"lib{bin}bin.so")) + + +recipe = LibThorVGRecipe() diff --git a/pythonforandroid/recipes/libthorvg/meson.patch b/pythonforandroid/recipes/libthorvg/meson.patch new file mode 100644 index 0000000000..ffdbdf5616 --- /dev/null +++ b/pythonforandroid/recipes/libthorvg/meson.patch @@ -0,0 +1,77 @@ +diff '--color=auto' -uNr thorvg/meson_options.txt thorvg.mod/meson_options.txt +--- thorvg/meson_options.txt 2026-02-12 21:02:13.000000000 +0530 ++++ thorvg.mod/meson_options.txt 2026-03-06 11:11:43.111722092 +0530 +@@ -68,3 +68,11 @@ + choices: ['', 'opengl_es', 'lottie_exp', 'openmp'], + value: ['lottie_exp', 'openmp'], + description: 'Enable support for extra options') ++ ++ ++option('png_include_dir', type: 'string', value: '', description: 'Path to PNG headers') ++option('png_lib_dir', type: 'string', value: '', description: 'Path to PNG library') ++option('webp_include_dir', type: 'string', value: '', description: 'Path to WEBP headers') ++option('webp_lib_dir', type: 'string', value: '', description: 'Path to WEBP library') ++option('jpg_include_dir', type: 'string', value: '', description: 'Path to JPG headers') ++option('jpg_lib_dir', type: 'string', value: '', description: 'Path to JPG library') +diff '--color=auto' -uNr thorvg/src/loaders/external_jpg/meson.build thorvg.mod/src/loaders/external_jpg/meson.build +--- thorvg/src/loaders/external_jpg/meson.build 2026-02-12 21:02:13.000000000 +0530 ++++ thorvg.mod/src/loaders/external_jpg/meson.build 2026-03-06 11:16:26.360504907 +0530 +@@ -3,11 +3,12 @@ + 'tvgJpgLoader.cpp', + ] + +-jpg_dep = dependency('libturbojpeg', required: false) +- +-if not jpg_dep.found() +- jpg_dep = cc.find_library('turbojpeg', required: false) +-endif ++jpg_inc = include_directories(get_option('jpg_include_dir')) ++jpg_lib = cc.find_library('turbojpeg', dirs: [get_option('jpg_lib_dir')], required: true) ++jpg_dep = declare_dependency( ++ include_directories: jpg_inc, ++ dependencies: [jpg_lib] ++) + + if jpg_dep.found() + subloader_dep += [declare_dependency( +diff '--color=auto' -uNr thorvg/src/loaders/external_png/meson.build thorvg.mod/src/loaders/external_png/meson.build +--- thorvg/src/loaders/external_png/meson.build 2026-02-12 21:02:13.000000000 +0530 ++++ thorvg.mod/src/loaders/external_png/meson.build 2026-03-06 10:59:38.966203768 +0530 +@@ -3,7 +3,12 @@ + 'tvgPngLoader.cpp', + ] + +-png_dep = dependency('libpng', required: false) ++png_inc = include_directories(get_option('png_include_dir')) ++png_lib = cc.find_library('png16', dirs: [get_option('png_lib_dir')], required: true) ++png_dep = declare_dependency( ++ include_directories: png_inc, ++ dependencies: [png_lib] ++) + + if png_dep.found() + subloader_dep += [declare_dependency( +diff '--color=auto' -uNr thorvg/src/loaders/external_webp/meson.build thorvg.mod/src/loaders/external_webp/meson.build +--- thorvg/src/loaders/external_webp/meson.build 2026-02-12 21:02:13.000000000 +0530 ++++ thorvg.mod/src/loaders/external_webp/meson.build 2026-03-06 11:03:55.626148453 +0530 +@@ -3,7 +3,12 @@ + 'tvgWebpLoader.cpp', + ] + +-webp_dep = dependency('libwebp', required: false) ++webp_inc = include_directories(get_option('webp_include_dir')) ++webp_lib = cc.find_library('webp', dirs: [get_option('webp_lib_dir')], required: true) ++webp_dep = declare_dependency( ++ include_directories: webp_inc, ++ dependencies: [webp_lib] ++) + + if webp_dep.found() + subloader_dep += [declare_dependency( +@@ -11,4 +16,4 @@ + dependencies : webp_dep, + sources : source_file + )] +-endif +\ No newline at end of file ++endif diff --git a/pythonforandroid/recipes/thorvg-python/__init__.py b/pythonforandroid/recipes/thorvg-python/__init__.py new file mode 100644 index 0000000000..f2d1c79eda --- /dev/null +++ b/pythonforandroid/recipes/thorvg-python/__init__.py @@ -0,0 +1,12 @@ +from pythonforandroid.recipe import PyProjectRecipe + + +class ThorVGPythonRecipe(PyProjectRecipe): + site_packages_name = "thorvg_python" + version = "1.1.3" + url = "https://github.com/laggykiller/thorvg-python/archive/refs/tags/v{version}.tar.gz" + depends = ["libthorvg"] + patches = ["sharedlib.patch"] + + +recipe = ThorVGPythonRecipe() diff --git a/pythonforandroid/recipes/thorvg-python/sharedlib.patch b/pythonforandroid/recipes/thorvg-python/sharedlib.patch new file mode 100644 index 0000000000..971c29ae31 --- /dev/null +++ b/pythonforandroid/recipes/thorvg-python/sharedlib.patch @@ -0,0 +1,43 @@ +diff '--color=auto' -uNr thorvg-python-1.1.1/pyproject.toml thorvg-python-1.1.1.mod/pyproject.toml +--- thorvg-python-1.1.1/pyproject.toml 2026-02-28 01:45:23.000000000 +0530 ++++ thorvg-python-1.1.1.mod/pyproject.toml 2026-03-06 13:36:02.822762758 +0530 +@@ -34,7 +34,6 @@ + + [build-system] + requires = [ +- "conan>=2.0", + "setuptools>=45" + ] + build-backend = "setuptools.build_meta" +@@ -45,4 +44,4 @@ + + [tool.mypy] + python_version = "3.9" +-files = ["src", "tests"] +\ No newline at end of file ++files = ["src", "tests"] +diff '--color=auto' -uNr thorvg-python-1.1.1/setup.py thorvg-python-1.1.1.mod/setup.py +--- thorvg-python-1.1.1/setup.py 2026-02-28 01:45:23.000000000 +0530 ++++ thorvg-python-1.1.1.mod/setup.py 2026-03-06 13:32:56.878441668 +0530 +@@ -213,10 +213,4 @@ + packages=find_packages(where="src"), + package_dir={"": "src"}, + include_package_data=True, +- package_data={ +- "thorvg_python": ["*.dll", "*.dylib", "*.so"], +- }, +- cmdclass={ +- "build_py": build_py_custom, +- }, + ) +diff '--color=auto' -uNr thorvg-python-1.1.1/src/thorvg_python/engine.py thorvg-python-1.1.1.mod/src/thorvg_python/engine.py +--- thorvg-python-1.1.1/src/thorvg_python/engine.py 2026-02-28 01:45:23.000000000 +0530 ++++ thorvg-python-1.1.1.mod/src/thorvg_python/engine.py 2026-03-06 16:42:11.625316343 +0530 +@@ -14,6 +14,7 @@ + ) -> Optional[ctypes.CDLL]: + package_dir = os.path.dirname(__file__) + thorvg_lib_name = lib_prefix + "thorvg" + lib_suffix ++ return ctypes.cdll.LoadLibrary(thorvg_lib_name) + thorvg_lib_path_local = os.path.join(package_dir, thorvg_lib_name) + + if os.path.isfile(thorvg_lib_path_local): From e35747916c743ecb856edd700d2dee26c2e38ed5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 24 May 2026 02:33:14 +0000 Subject: [PATCH 44/82] Bump dessant/support-requests from 4 to 5 in the github-actions group Bumps the github-actions group with 1 update: [dessant/support-requests](https://github.com/dessant/support-requests). Updates `dessant/support-requests` from 4 to 5 - [Release notes](https://github.com/dessant/support-requests/releases) - [Changelog](https://github.com/dessant/support-requests/blob/main/CHANGELOG.md) - [Commits](https://github.com/dessant/support-requests/compare/v4...v5) --- updated-dependencies: - dependency-name: dessant/support-requests dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/support.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/support.yml b/.github/workflows/support.yml index a0693e7632..a9e5b7ca05 100644 --- a/.github/workflows/support.yml +++ b/.github/workflows/support.yml @@ -16,7 +16,7 @@ jobs: action: runs-on: ubuntu-latest steps: - - uses: dessant/support-requests@v4 + - uses: dessant/support-requests@v5 with: github-token: ${{ github.token }} support-label: 'support' From afe50a8b0e21a0d4aee1a33175e65e73f2a6080a Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 25 May 2026 15:43:23 +0000 Subject: [PATCH 45/82] :bug: Resolve Meson tools through recipe env MesonRecipe installs meson and ninja as hostpython prerequisites and PyProjectRecipe exposes those executables by prepending the hostpython bin directories to the recipe environment PATH. Recipes that call sh.meson or sh.ninja directly can fail before _env is applied when those tools are not also visible on the current Python process PATH. Add shared MesonRecipe helpers that resolve commands against the recipe env PATH and return explicit sh.Command instances. Use those helpers in the libthorvg and libcairo manual Meson/Ninja build steps. Add a regression test that reproduces the environment-sensitive lookup failure and verifies the helper resolves meson from env PATH. --- pythonforandroid/recipe.py | 12 +++++++ pythonforandroid/recipes/libcairo/__init__.py | 14 ++++++-- .../recipes/libthorvg/__init__.py | 14 ++++++-- tests/test_recipe.py | 32 ++++++++++++++++++- 4 files changed, 65 insertions(+), 7 deletions(-) diff --git a/pythonforandroid/recipe.py b/pythonforandroid/recipe.py index 3132a5d39d..1d5e3e9104 100644 --- a/pythonforandroid/recipe.py +++ b/pythonforandroid/recipe.py @@ -1567,6 +1567,18 @@ def ensure_args(self, *args): if arg not in self.extra_build_args: self.extra_build_args.append(arg) + def get_recipe_env_command(self, command, env): + command_path = shutil.which(command, path=env["PATH"]) + if command_path is None: + raise sh.CommandNotFound(command) + return sh.Command(command_path) + + def get_meson_command(self, env): + return self.get_recipe_env_command("meson", env) + + def get_ninja_command(self, env): + return self.get_recipe_env_command("ninja", env) + def build_arch(self, arch): cross_file = join("/tmp", "android.meson.cross") info("Writing cross file at: {}".format(cross_file)) diff --git a/pythonforandroid/recipes/libcairo/__init__.py b/pythonforandroid/recipes/libcairo/__init__.py index 14ca37d531..fef4f39ddc 100644 --- a/pythonforandroid/recipes/libcairo/__init__.py +++ b/pythonforandroid/recipes/libcairo/__init__.py @@ -56,7 +56,7 @@ def build_arch(self, arch): _env=env ) - shprint(sh.meson, 'setup', 'builddir', + shprint(self.get_meson_command(env), 'setup', 'builddir', '--cross-file', join("/tmp", "android.meson.cross"), f'--prefix={install_dir}', '-Dpng=enabled', @@ -72,14 +72,22 @@ def build_arch(self, arch): f'-Dfreetype_lib_dir={lib_dir}', _env=env) - shprint(sh.ninja, '-C', 'builddir', '-j', str(cpu_count()), _env=env) + shprint( + self.get_ninja_command(env), + '-C', 'builddir', '-j', str(cpu_count()), + _env=env + ) # macOS fix: sometimes Ninja creates a dummy 'lib' file instead of a directory. # So we remove and recreate the install directory using shell commands, # since os.remove/os.makedirs behave inconsistently in this build env. shprint(sh.rm, '-rf', install_dir) shprint(sh.mkdir, install_dir) - shprint(sh.ninja, '-C', 'builddir', 'install', _env=env) + shprint( + self.get_ninja_command(env), + '-C', 'builddir', 'install', + _env=env + ) recipe = LibCairoRecipe() diff --git a/pythonforandroid/recipes/libthorvg/__init__.py b/pythonforandroid/recipes/libthorvg/__init__.py index bb05c37a1f..c9eaefc90f 100644 --- a/pythonforandroid/recipes/libthorvg/__init__.py +++ b/pythonforandroid/recipes/libthorvg/__init__.py @@ -54,7 +54,7 @@ def build_arch(self, arch): with current_directory(build_dir): shprint( - sh.meson, + self.get_meson_command(env), "setup", "builddir", "--cross-file", @@ -72,10 +72,18 @@ def build_arch(self, arch): _env=env, ) - shprint(sh.ninja, "-C", "builddir", "-j", str(cpu_count()), _env=env) + shprint( + self.get_ninja_command(env), + "-C", "builddir", "-j", str(cpu_count()), + _env=env, + ) shprint(sh.rm, "-rf", install_dir) shprint(sh.mkdir, install_dir) - shprint(sh.ninja, "-C", "builddir", "install", _env=env) + shprint( + self.get_ninja_command(env), + "-C", "builddir", "install", + _env=env, + ) # copy libomp.so arch_map = { diff --git a/tests/test_recipe.py b/tests/test_recipe.py index e2e0e9d826..d4e1dc551a 100644 --- a/tests/test_recipe.py +++ b/tests/test_recipe.py @@ -1,5 +1,6 @@ import os import pytest +import sh import tempfile import types import unittest @@ -7,7 +8,9 @@ from unittest import mock from pythonforandroid.build import Context -from pythonforandroid.recipe import Recipe, TargetPythonRecipe, import_recipe +from pythonforandroid.recipe import ( + MesonRecipe, Recipe, TargetPythonRecipe, import_recipe +) from pythonforandroid.archs import ArchAarch_64 from pythonforandroid.bootstrap import Bootstrap from tests.test_bootstrap import BaseClassSetupBootstrap @@ -198,6 +201,33 @@ class DummyTargetPythonRecipe(TargetPythonRecipe): assert recipe.major_minor_version_string == '1.2' +class TestMesonRecipe(unittest.TestCase): + + def test_get_recipe_env_command_uses_env_path(self): + """ + Meson commands can be installed in the hostpython environment without + being visible on the current Python process PATH. + """ + with tempfile.TemporaryDirectory() as temp_dir: + bin_dir = os.path.join(temp_dir, "bin") + os.mkdir(bin_dir) + meson_path = os.path.join(bin_dir, "meson") + with open(meson_path, "w") as file: + file.write("#!/bin/sh\necho fake meson\n") + os.chmod(meson_path, 0o755) + + env = {"PATH": bin_dir} + recipe = MesonRecipe() + + with mock.patch.dict(os.environ, {"PATH": os.devnull}): + with pytest.raises(sh.CommandNotFound): + sh.meson("--version", _env=env) + + meson = recipe.get_meson_command(env) + + assert meson("--version").strip() == "fake meson" + + class TestLibraryRecipe(BaseClassSetupBootstrap, unittest.TestCase): def setUp(self): """ From 7c6e6f342110f50fb0434d7eaa00fd03d2968dd0 Mon Sep 17 00:00:00 2001 From: lazycat11 <59393906+lazycat11@users.noreply.github.com> Date: Fri, 29 May 2026 02:22:56 +0800 Subject: [PATCH 46/82] Fix android recipe linking with Qt bootstrap (#3312) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: lanmao Co-authored-by: Mathias Lindström <8863149+kuzeyron@users.noreply.github.com> --- pythonforandroid/recipes/android/__init__.py | 7 ++++++- pythonforandroid/recipes/android/src/setup.py | 5 ++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/pythonforandroid/recipes/android/__init__.py b/pythonforandroid/recipes/android/__init__.py index c6c15ec04a..fcf2c069ba 100644 --- a/pythonforandroid/recipes/android/__init__.py +++ b/pythonforandroid/recipes/android/__init__.py @@ -20,6 +20,10 @@ class AndroidRecipe(IncludedFilesBehaviour, PyProjectRecipe): def get_recipe_env(self, arch, **kwargs): env = super().get_recipe_env(arch, **kwargs) env.update(self.config_env) + + if self.ctx.bootstrap.name == "qt": + env['ANDROID_MAIN_LIB'] = f'main_{arch.arch}' + return env def prebuild_arch(self, arch): @@ -50,8 +54,9 @@ def prebuild_arch(self, arch): 'IS_SDL2': int(bootstrap_name == "sdl2"), 'IS_SDL3': int(bootstrap_name == "sdl3"), 'PY2': 0, - 'ANDROID_LIBS_DIR': "{}:{}".format( + 'ANDROID_LIBS_DIR': "{}:{}:{}".format( self.ctx.get_libs_dir(arch.arch), + join(self.ctx.bootstrap.build_dir, 'libs', arch.arch), join(self.ctx.bootstrap.build_dir, 'obj', 'local', arch.arch) ), 'JAVA_NAMESPACE': java_ns, diff --git a/pythonforandroid/recipes/android/src/setup.py b/pythonforandroid/recipes/android/src/setup.py index 8182ba9c58..030f5fb126 100755 --- a/pythonforandroid/recipes/android/src/setup.py +++ b/pythonforandroid/recipes/android/src/setup.py @@ -7,7 +7,10 @@ 'sdl2': ['SDL2', 'SDL2_image', 'SDL2_mixer', 'SDL2_ttf'], 'sdl3': ['SDL3', 'SDL3_image', 'SDL3_mixer', 'SDL3_ttf'], } -sdl_libs = lib_dict.get(os.environ['BOOTSTRAP'], ['main']) +sdl_libs = lib_dict.get( + os.environ['BOOTSTRAP'], + [os.environ.get('ANDROID_MAIN_LIB', 'main')] +) modules = [ Extension('android._android', From eec8c0ab8ceb63460f23443766068685be55a4dc Mon Sep 17 00:00:00 2001 From: Kenechukwu Akubue Date: Fri, 29 May 2026 12:16:22 +0100 Subject: [PATCH 47/82] Add dark mode listener support across all Android bootstraps (#3306) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add dark mode listener support across all Android bootstraps Introduce `DarkModeListener` interface to detect and handle system dark mode changes. Update Java and Python APIs to support listener registration for monitoring and reacting to dark mode state changes. Document usage in APIs. * Refactor `DarkModeListener` to use dynamic activity class namespace and standardize method signature formatting --------- Co-authored-by: Mathias Lindström <8863149+kuzeyron@users.noreply.github.com> --- doc/source/apis.rst | 30 ++++++++++ .../java/org/kivy/android/PythonActivity.java | 23 ++++++++ .../java/org/kivy/android/PythonActivity.java | 23 ++++++++ .../java/org/kivy/android/PythonActivity.java | 23 ++++++++ .../java/org/kivy/android/PythonActivity.java | 23 ++++++++ .../recipes/android/src/android/darkmode.py | 57 +++++++++++++++++++ 6 files changed, 179 insertions(+) create mode 100644 pythonforandroid/recipes/android/src/android/darkmode.py diff --git a/doc/source/apis.rst b/doc/source/apis.rst index c9e30699ce..0f139c5192 100644 --- a/doc/source/apis.rst +++ b/doc/source/apis.rst @@ -388,6 +388,36 @@ This can be used to prevent errors like: Because the python function is called from the PythonActivity thread, you need to be careful about your own calls. +Handling DarkMode +~~~~~~~~~~~~~~~~~ + +The ``android.darkmode`` module provides functionality to detect and respond to +system dark mode changes on Android devices. + +You can set up a listener to monitor dark mode state changes using the +``set_dark_mode_listener`` function:: + + from android.darkmode import set_dark_mode_listener + + def on_dark_mode_changed(is_dark_mode): + if is_dark_mode: + print('Dark mode is now enabled') + # Update your app's theme to dark mode + else: + print('Dark mode is now disabled') + # Update your app's theme to light mode + + # Register the listener + set_dark_mode_listener(on_dark_mode_changed) + +To remove the listener, simply pass ``None``:: + + set_dark_mode_listener(None) + +The callback function receives a single boolean parameter ``is_dark_mode`` that +indicates whether dark mode is currently enabled (``True``) or disabled (``False``). + + Advanced Android API use ------------------------ 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 index 9c1415db0c..cb40427747 100644 --- 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 @@ -3,6 +3,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.content.res.Configuration; import android.os.Bundle; import android.os.PowerManager; import android.os.SystemClock; @@ -233,4 +234,26 @@ public static void _do_start_service( public static void stop_service() { PythonServiceIntent.stop(PythonActivity.mActivity, PythonService.class); } + + public interface DarkModeListener { + void onDarkModeChanged(boolean isDarkMode); + } + + private DarkModeListener darkModeListener = null; + + public void setDarkModeListener(DarkModeListener listener) { + darkModeListener = listener; + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + int currentNightMode = newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK; + boolean isDarkMode = currentNightMode == Configuration.UI_MODE_NIGHT_YES; + + if (darkModeListener != null) { + darkModeListener.onDarkModeChanged(isDarkMode); + } + + super.onConfigurationChanged(newConfig); + } } diff --git a/pythonforandroid/bootstraps/sdl2/build/src/main/java/org/kivy/android/PythonActivity.java b/pythonforandroid/bootstraps/sdl2/build/src/main/java/org/kivy/android/PythonActivity.java index a5d494213e..ffad225c0b 100644 --- a/pythonforandroid/bootstraps/sdl2/build/src/main/java/org/kivy/android/PythonActivity.java +++ b/pythonforandroid/bootstraps/sdl2/build/src/main/java/org/kivy/android/PythonActivity.java @@ -5,6 +5,7 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; +import android.content.res.Configuration; import android.content.res.Resources.NotFoundException; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -615,6 +616,28 @@ public void requestPermissions(String[] permissions) { requestPermissionsWithRequestCode(permissions, 1); } + public interface DarkModeListener { + void onDarkModeChanged(boolean isDarkMode); + } + + private DarkModeListener darkModeListener = null; + + public void setDarkModeListener(DarkModeListener listener) { + darkModeListener = listener; + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + int currentNightMode = newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK; + boolean isDarkMode = currentNightMode == Configuration.UI_MODE_NIGHT_YES; + + if (darkModeListener != null) { + darkModeListener.onDarkModeChanged(isDarkMode); + } + + super.onConfigurationChanged(newConfig); + } + public static void changeKeyboard(int inputType) { if (SDLActivity.keyboardInputType != inputType) { SDLActivity.keyboardInputType = inputType; diff --git a/pythonforandroid/bootstraps/sdl3/build/src/main/java/org/kivy/android/PythonActivity.java b/pythonforandroid/bootstraps/sdl3/build/src/main/java/org/kivy/android/PythonActivity.java index abc4afbf15..7f4a58c58c 100644 --- a/pythonforandroid/bootstraps/sdl3/build/src/main/java/org/kivy/android/PythonActivity.java +++ b/pythonforandroid/bootstraps/sdl3/build/src/main/java/org/kivy/android/PythonActivity.java @@ -5,6 +5,7 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; +import android.content.res.Configuration; import android.content.res.Resources.NotFoundException; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -614,6 +615,28 @@ public void requestPermissions(String[] permissions) { requestPermissionsWithRequestCode(permissions, 1); } + public interface DarkModeListener { + void onDarkModeChanged(boolean isDarkMode); + } + + private DarkModeListener darkModeListener = null; + + public void setDarkModeListener(DarkModeListener listener) { + darkModeListener = listener; + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + int currentNightMode = newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK; + boolean isDarkMode = currentNightMode == Configuration.UI_MODE_NIGHT_YES; + + if (darkModeListener != null) { + darkModeListener.onDarkModeChanged(isDarkMode); + } + + super.onConfigurationChanged(newConfig); + } + public static void changeKeyboard(int inputType) { /* if (SDLActivity.keyboardInputType != inputType){ diff --git a/pythonforandroid/bootstraps/webview/build/src/main/java/org/kivy/android/PythonActivity.java b/pythonforandroid/bootstraps/webview/build/src/main/java/org/kivy/android/PythonActivity.java index f0e384adaa..23f0b24077 100644 --- a/pythonforandroid/bootstraps/webview/build/src/main/java/org/kivy/android/PythonActivity.java +++ b/pythonforandroid/bootstraps/webview/build/src/main/java/org/kivy/android/PythonActivity.java @@ -6,6 +6,7 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; +import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; @@ -542,6 +543,28 @@ public void requestPermissionsWithRequestCode(String[] permissions, int requestC public void requestPermissions(String[] permissions) { requestPermissionsWithRequestCode(permissions, 1); } + + public interface DarkModeListener { + void onDarkModeChanged(boolean isDarkMode); + } + + private DarkModeListener darkModeListener = null; + + public void setDarkModeListener(DarkModeListener listener) { + darkModeListener = listener; + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + int currentNightMode = newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK; + boolean isDarkMode = currentNightMode == Configuration.UI_MODE_NIGHT_YES; + + if (darkModeListener != null) { + darkModeListener.onDarkModeChanged(isDarkMode); + } + + super.onConfigurationChanged(newConfig); + } } class PythonMain implements Runnable { diff --git a/pythonforandroid/recipes/android/src/android/darkmode.py b/pythonforandroid/recipes/android/src/android/darkmode.py new file mode 100644 index 0000000000..6e06662de8 --- /dev/null +++ b/pythonforandroid/recipes/android/src/android/darkmode.py @@ -0,0 +1,57 @@ +from typing import Callable + +from jnius import PythonJavaClass, java_method, autoclass +from android.config import ACTIVITY_CLASS_NAME, ACTIVITY_CLASS_NAMESPACE + +_listener = None + + +class DarkModeListener(PythonJavaClass): + """ + A listener class for detecting and handling dark mode changes. + + This class implements the `DarkModeListener` interface in a Python-Java + hybrid context through Kivy Android functionality. It listens for changes + in the system's dark mode settings and executes a callback upon detecting + a change. + + Attributes: + on_dark_mode_changed (Callable[[bool], None]): A callback function to + handle the event when dark mode status changes. The callback + receives a single parameter `is_dark_mode`, which is a boolean + indicating whether dark mode is currently enabled. + """ + __javacontext__ = "app" + __javainterfaces__ = [ACTIVITY_CLASS_NAMESPACE + '$DarkModeListener'] + + def __init__(self, on_dark_mode_changed: Callable[[bool], None]): + self.on_dark_mode_changed = on_dark_mode_changed + + @java_method('(Z)V') + def onDarkModeChanged(self, is_dark_mode): + self.on_dark_mode_changed(is_dark_mode) + + +def set_dark_mode_listener(on_dark_mode_changed: Callable[[bool], None] | None) -> None: + """ + Sets a listener to monitor changes in the dark mode state. + + This function assigns a provided callback to handle changes in the + dark mode settings. The callback will be invoked with a boolean + argument indicating the current dark mode state. + + Args: + on_dark_mode_changed: A callable that accepts a single boolean + parameter indicating whether dark mode is active. + + Returns: + None + """ + global _listener + activity = autoclass(ACTIVITY_CLASS_NAME).mActivity + if on_dark_mode_changed: + _listener = DarkModeListener(on_dark_mode_changed) + activity.setDarkModeListener(_listener) + else: + activity.setDarkModeListener(on_dark_mode_changed) + _listener = None From 74b559a3c3b5bb7d18cf54fd0d22ffa1b7294c16 Mon Sep 17 00:00:00 2001 From: Ansh Dadwal Date: Fri, 29 May 2026 19:22:25 +0530 Subject: [PATCH 48/82] numpy: enable openblas (#3305) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * numpy: enable openblas * libopenblas: disable dynamic arch * Add doc for numpy --------- Co-authored-by: Mathias Lindström <8863149+kuzeyron@users.noreply.github.com> --- doc/source/apis.rst | 11 +++++++++++ pythonforandroid/recipes/libopenblas/__init__.py | 1 + pythonforandroid/recipes/numpy/__init__.py | 14 ++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/doc/source/apis.rst b/doc/source/apis.rst index 0f139c5192..f188dd197d 100644 --- a/doc/source/apis.rst +++ b/doc/source/apis.rst @@ -80,6 +80,17 @@ https://developer.android.com/reference/android/Manifest.permission Other common tasks ------------------ +Using NumPY +~~~~~~~~~~~ + +It should work out of the box; just ensure `numpy` is included in your requirements. +If you want better performance, you can also add `libopenblas` to the requirements. +This allows NumPy to use BLAS/LAPACK acceleration, which can significantly improve linear algebra operations. + +Keep in mind that `libopenblas` is a fairly large library (~12 MB per architecture), +so it will increase your app size. For example, if you build for 4 architectures, +the APK size may increase by roughly `12 × 4 = 48 MB` (before compression). + Running executables ~~~~~~~~~~~~~~~~~~~ diff --git a/pythonforandroid/recipes/libopenblas/__init__.py b/pythonforandroid/recipes/libopenblas/__init__.py index e88feb6686..cf18914044 100644 --- a/pythonforandroid/recipes/libopenblas/__init__.py +++ b/pythonforandroid/recipes/libopenblas/__init__.py @@ -33,6 +33,7 @@ def build_arch(self, arch): "-DCMAKE_BUILD_TYPE=Release", "-DBUILD_SHARED_LIBS=ON", "-DC_LAPACK=ON", + "-DDYNAMIC_ARCH=0", "-DTARGET={target}".format( target={ "arm64-v8a": "ARMV8", diff --git a/pythonforandroid/recipes/numpy/__init__.py b/pythonforandroid/recipes/numpy/__init__.py index df1d294438..e3f72f0ed2 100644 --- a/pythonforandroid/recipes/numpy/__init__.py +++ b/pythonforandroid/recipes/numpy/__init__.py @@ -11,6 +11,7 @@ class NumpyRecipe(MesonRecipe): version = "v2.3.0" url = "git+https://github.com/numpy/numpy" extra_build_args = ["-Csetup-args=-Dblas=none", "-Csetup-args=-Dlapack=none"] + opt_depends = ["libopenblas"] need_stl_shared = True min_ndk_api_support = 24 @@ -41,6 +42,19 @@ def get_recipe_env(self, arch, **kwargs): "android-build", "python", ) + blas_dir = join(Recipe.get_recipe("libopenblas", self.ctx + ).get_build_dir(arch.arch), "build") + blas_incdir = blas_dir + blas_libdir = join(blas_dir, "lib") + env["CXXFLAGS"] += f" -I{blas_incdir} -L{blas_libdir}" + + if 'libopenblas' in self.ctx.recipe_build_order: + self.extra_build_args = [ + "-Csetup-args=-Dblas=auto", + "-Csetup-args=-Dlapack=auto", + "-Csetup-args=-Dallow-noblas=False", + ] + return env def get_hostrecipe_env(self, arch=None): From 70f922439f43e3e4923ed4944744ace500762fc6 Mon Sep 17 00:00:00 2001 From: Kartavya Shukla <87070473+Novfensec@users.noreply.github.com> Date: Sun, 31 May 2026 13:58:35 +0530 Subject: [PATCH 49/82] Handling system bars and Edge-to-Edge enforcement (android 15+) (#3278) * Add update_system_ui for status and navigation bar colors Implement update_system_ui function for Android UI customization. * Update apis.rst * Update utils.py * Update utils.py * Update code quality and readbility * Create a _global_listener to prevent garbage collection * Update utils.py * Set _global_listener to None in utils.py Initialize _global_listener to None. * Move existing logic to display_cutout * Bug fixes * Update docs * Update docs for right version of the func * Just just --- doc/source/apis.rst | 34 +++ .../build/templates/strings.tmpl.xml | 2 +- .../android/src/android/display_cutout.py | 237 ++++++++++++++++-- 3 files changed, 249 insertions(+), 24 deletions(-) diff --git a/doc/source/apis.rst b/doc/source/apis.rst index f188dd197d..7af4e54665 100644 --- a/doc/source/apis.rst +++ b/doc/source/apis.rst @@ -5,6 +5,40 @@ Working on Android This page gives details on accessing Android APIs and managing other interactions on Android. +Handling system bars and Edge-to-Edge enforcement +------------------------------------------------- + +**Egde-to-Edge is enforced on all android apis >=35 by default i.e. Android 15 and above.** + +You can control the overall layout and system bars appearance in following ways:: + + from android.display_cutout import update_system_ui + + update_system_ui( + "#0f62fe", # status_bar_color: hex color code or rgba (tuple or list) values + [0.059, 0.384, 0.996, 1.000], # navigation_bar_color: hex color code or rgba (tuple or list) values + "Light", # icon_style: "Dark" means dark icons will be drawn, "Light" means light icons will be drawn, Literal["Dark", or "Light"] + True, # pad_status: Adds a padding to top of content_view, Will take effect on Android 15+ + True, # pad_nav: Adds a padding to bottom of content_view, Will take effect on Android 15+ + ) + + +Handling Immersive Mode +~~~~~~~~~~~~~~~~~~~~~~~ + +Immersive mode allows your application to hide the system bars (status bar and navigation bar) for a true full-screen experience, commonly used in games or media players. + +You can control the immersive mode behavior and how system bars reappear using the following way:: + + from android.display_cutout import set_immersive_mode + + set_immersive_mode( + False, # hide_status: True explicitly targets hiding the top status bar, False leaves it visible + False, # hide_nav: True explicitly targets hiding the bottom navigation bar/gestural pill, False leaves it visible + True, # remove_contrast: True disables the default system-enforced background scrim/contrast behind the bars, ensuring complete transparency when they peek + ) + + Storage paths ------------- diff --git a/pythonforandroid/bootstraps/_sdl_common/build/templates/strings.tmpl.xml b/pythonforandroid/bootstraps/_sdl_common/build/templates/strings.tmpl.xml index 17e376adbd..90700b6805 100644 --- a/pythonforandroid/bootstraps/_sdl_common/build/templates/strings.tmpl.xml +++ b/pythonforandroid/bootstraps/_sdl_common/build/templates/strings.tmpl.xml @@ -3,7 +3,7 @@