Skip to content

Commit e8a5c8e

Browse files
committed
Merge branch 'upstream_develop' into develop
2 parents 007a3b2 + 1fc0269 commit e8a5c8e

56 files changed

Lines changed: 2232 additions & 1304 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/push.yml

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,26 @@ jobs:
3030
pip install tox>=2.0
3131
tox -e pep8
3232
33+
spotless:
34+
name: Java Spotless check
35+
runs-on: ubuntu-latest
36+
steps:
37+
- name: Checkout python-for-android
38+
uses: actions/checkout@v5
39+
- name: Set up Java 17
40+
uses: actions/setup-java@v4
41+
with:
42+
distribution: 'temurin'
43+
java-version: '17'
44+
- name: Set up Gradle
45+
uses: gradle/actions/setup-gradle@v4
46+
- name: Run Spotless check
47+
working-directory: pythonforandroid/bootstraps
48+
run: ./common/build/gradlew spotlessCheck
49+
3350
test:
3451
name: Pytest [Python ${{ matrix.python-version }} | ${{ matrix.os }}]
35-
needs: flake8
52+
needs: [flake8, spotless]
3653
runs-on: ${{ matrix.os }}
3754
strategy:
3855
fail-fast: false
@@ -61,9 +78,8 @@ jobs:
6178

6279
ubuntu_build:
6380
name: Build test APP [ ${{ matrix.runs_on }} | ${{ matrix.bootstrap.name }} ]
64-
needs: [flake8]
81+
needs: [flake8, spotless]
6582
runs-on: ${{ matrix.runs_on }}
66-
continue-on-error: true
6783
strategy:
6884
matrix:
6985
runs_on: [ubuntu-latest]
@@ -79,6 +95,16 @@ jobs:
7995
- name: qt
8096
target: testapps-qt
8197
steps:
98+
- name: Maximize build space
99+
uses: easimon/maximize-build-space@v10
100+
with:
101+
root-reserve-mb: 30720
102+
swap-size-mb: 1024
103+
remove-dotnet: 'true'
104+
remove-android: 'true'
105+
remove-haskell: 'true'
106+
remove-codeql: 'true'
107+
remove-docker-images: 'true'
82108
- name: Checkout python-for-android
83109
uses: actions/checkout@v5
84110
- name: Build python-for-android docker image
@@ -111,9 +137,8 @@ jobs:
111137

112138
macos_build:
113139
name: Build test APP [ ${{ matrix.runs_on }} | ${{ matrix.bootstrap.name }} ]
114-
needs: [flake8]
140+
needs: [flake8, spotless]
115141
runs-on: ${{ matrix.runs_on }}
116-
continue-on-error: true
117142
strategy:
118143
matrix:
119144
# macos-latest (ATM macos-15) runs on Apple Silicon,
@@ -186,28 +211,30 @@ jobs:
186211

187212
ubuntu_rebuild_updated_recipes:
188213
name: Test updated recipes for arch ${{ matrix.android_arch }} [ ubuntu-latest ]
189-
needs: [flake8]
214+
needs: [flake8, spotless]
190215
runs-on: ubuntu-latest
216+
# continue on error to see failures across all architectures
191217
continue-on-error: true
192218
strategy:
193219
matrix:
194220
android_arch: ["arm64-v8a", "armeabi-v7a", "x86_64", "x86"]
195221
env:
196222
REBUILD_UPDATED_RECIPES_EXTRA_ARGS: --arch=${{ matrix.android_arch }}
197223
steps:
224+
- name: Maximize build space
225+
uses: easimon/maximize-build-space@v10
226+
with:
227+
root-reserve-mb: 30720
228+
swap-size-mb: 1024
229+
remove-dotnet: 'true'
230+
remove-android: 'true'
231+
remove-haskell: 'true'
232+
remove-codeql: 'true'
233+
remove-docker-images: 'true'
198234
- name: Checkout python-for-android (all-history)
199235
uses: actions/checkout@v5
200236
with:
201237
fetch-depth: 0
202-
# helps with GitHub runner getting out of space
203-
- name: Free disk space
204-
run: |
205-
df -h
206-
sudo swapoff -a
207-
sudo rm -f /swapfile
208-
sudo apt -y clean
209-
docker images -q | xargs -r docker rmi
210-
df -h
211238
- name: Pull docker image
212239
run: |
213240
make docker/pull
@@ -217,8 +244,9 @@ jobs:
217244
218245
macos_rebuild_updated_recipes:
219246
name: Test updated recipes for arch ${{ matrix.android_arch }} [ ${{ matrix.runs_on }} ]
220-
needs: [flake8]
247+
needs: [flake8, spotless]
221248
runs-on: ${{ matrix.runs_on }}
249+
# continue on error to see failures across all architectures
222250
continue-on-error: true
223251
strategy:
224252
matrix:

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,9 @@ coverage.xml
3636
# testapp's build folder
3737
testapps/build/
3838

39+
# Gradle build artifacts (Java linting)
40+
pythonforandroid/bootstraps/.gradle/
41+
pythonforandroid/bootstraps/build/
42+
3943
# Dolphin (the KDE file manager autogenerates the file `.directory`)
4044
.directory

CONTRIBUTING.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,60 @@ latest python-for-android release that supported building Python 2 was version
6666
On August 2021, we added support for Android App Bundle (aab). As a
6767
collateral benefit, we now support multi-arch apk.
6868

69+
## Code Quality
70+
71+
### Python Linting
72+
73+
Python code is linted using flake8. Run it locally with:
74+
75+
```bash
76+
tox -e pep8
77+
```
78+
79+
### Java Linting
80+
81+
Java source files in the bootstrap directories are linted using
82+
[Spotless](https://github.com/diffplug/spotless) with Google Java Format
83+
(AOSP style). The CI runs this check automatically.
84+
85+
**Local execution** (requires Java 17+):
86+
87+
```bash
88+
# Check for violations
89+
make java-lint
90+
91+
# Auto-fix violations
92+
make java-lint-fix
93+
```
94+
95+
The Makefile uses the Gradle wrapper (`gradlew`), which automatically downloads
96+
the correct Gradle version on first run. No manual Gradle installation is required.
97+
98+
**Using Docker** (if you don't have Java 17):
99+
100+
```bash
101+
# Check for violations
102+
make docker/java-lint
103+
104+
# Auto-fix violations
105+
make docker/java-lint-fix
106+
```
107+
108+
The Docker approach builds the project's Docker image (which includes Java 17)
109+
and runs the linting inside the container.
110+
111+
**What gets linted:**
112+
113+
- All `.java` files in `pythonforandroid/bootstraps/*/build/src/main/java/`
114+
- Excludes third-party code (`org/kamranzafar/jtar/`)
115+
116+
**Formatting rules applied:**
117+
118+
- Google Java Format with AOSP style (Android-friendly indentation)
119+
- Removal of unused imports
120+
- Trailing whitespace trimming
121+
- Files end with newline
122+
69123
## Creating a new release
70124

71125
(These instructions are for core developers, not casual contributors.)

Makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,20 @@ virtualenv: $(VIRTUAL_ENV)
2424
test:
2525
$(TOX) -- tests/ --ignore tests/test_pythonpackage.py
2626

27+
# Java linting using Spotless (requires Java 17+, uses Gradle wrapper)
28+
java-lint:
29+
cd pythonforandroid/bootstraps && ./common/build/gradlew spotlessCheck
30+
31+
java-lint-fix:
32+
cd pythonforandroid/bootstraps && ./common/build/gradlew spotlessApply
33+
34+
# Java linting via Docker (no local Java required)
35+
docker/java-lint: docker/build
36+
docker run --rm -v $(CURDIR):/home/user/app -w /home/user/app/pythonforandroid/bootstraps $(DOCKER_IMAGE) ./common/build/gradlew spotlessCheck
37+
38+
docker/java-lint-fix: docker/build
39+
docker run --rm -v $(CURDIR):/home/user/app -w /home/user/app/pythonforandroid/bootstraps $(DOCKER_IMAGE) ./common/build/gradlew spotlessApply
40+
2741
# Also install and configure rust
2842
rebuild_updated_recipes: virtualenv
2943
. $(ACTIVATE) && \

doc/source/apis.rst

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,53 @@ https://developer.android.com/reference/android/Manifest.permission
8080
Other common tasks
8181
------------------
8282

83+
Running executables
84+
~~~~~~~~~~~~~~~~~~~
85+
86+
Android restricts executing files from application data directories.
87+
``python-for-android`` works around this by creating symbolic links to a
88+
small set of supported executables inside an internal executable
89+
directory that is added to ``PATH``.
90+
91+
During startup, ``start.c`` (compiled into ``libmain.so``) scans loaded
92+
native libraries and creates symlinks for any library matching::
93+
94+
lib<binary_name>bin.so
95+
96+
Each matching library is exposed at runtime as::
97+
98+
<binary_name>
99+
100+
For example::
101+
102+
libffmpegbin.so -> ffmpeg
103+
104+
Recipe developers may expose additional executables by renaming them
105+
using the same naming convention.
106+
107+
The following example performs a minimal FFmpeg sanity check using an
108+
in-memory test source and discards the output::
109+
110+
import subprocess
111+
112+
subprocess.run(
113+
["ffmpeg", "-f", "lavfi", "-i", "testsrc", "-t", "1", "-f", "null", "-"],
114+
check=True
115+
)
116+
117+
This verifies that ``ffmpeg`` is available and executable on the device.
118+
Ensure ``ffmpeg`` is included in your ``requirements``.
119+
120+
If video encoding is required, the following codec options must also be
121+
enabled in the build configuration:
122+
123+
- ``av_codecs``
124+
- ``libx264``
125+
126+
Without these, FFmpeg may be present but lack the required codec support.
127+
128+
See also: `APK native library execution restrictions <https://github.com/agnostic-apollo/Android-Docs/blob/master/site/pages/en/projects/docs/apps/processes/app-data-file-execute-restrictions.md>`_
129+
83130
Dismissing the splash screen
84131
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
85132

@@ -140,7 +187,7 @@ With Kivy, add an ``on_pause`` method to your App class, which returns True::
140187

141188
With the webview bootstrap, pausing should work automatically.
142189

143-
Under SDL2, you can handle the `appropriate events <https://wiki.libsdl.org/SDL_EventType>`__ (see SDL_APP_WILLENTERBACKGROUND etc.).
190+
Under SDL2, you can handle the `appropriate events <https://wiki.libsdl.org/SDL3/SDL_EventType>`__ (see SDL_APP_WILLENTERBACKGROUND etc.).
144191

145192

146193
Observing Activity result

doc/source/conf.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,3 +321,15 @@ def get_version():
321321
r"https://github.com/kivy/python-for-android/blob.*",
322322
]
323323

324+
# Allow redirects for URLs where we prefer to keep the original form
325+
linkcheck_allowed_redirects = {
326+
# Kivy chat redirects to Discord invite
327+
r"https://chat\.kivy\.org/": r"https://discord\.com/.*",
328+
# GitHub archive URLs redirect to codeload
329+
r"https://github\.com/kivy/python-for-android/archive/.*": r"https://codeload\.github\.com/.*",
330+
# GitHub gist homepage redirects to starred
331+
r"https://gist\.github\.com/$": r"https://gist\.github\.com/.*",
332+
# Google Play Store redirects
333+
r"https://play\.google\.com/store/$": r"https://play\.google\.com/store/.*",
334+
}
335+

doc/source/index.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ It can generate:
1818

1919
It supports multiple CPU architectures.
2020

21-
It supports apps developed with `Kivy framework <http://kivy.org>`_, but was
21+
It supports apps developed with `Kivy framework <https://kivy.org/>`_, but was
2222
built to be flexible about the backend libraries (through "bootstraps"), and
2323
also supports `PySDL2 <https://pypi.org/project/PySDL2/>`_, and a
2424
`WebView <https://developer.android.com/reference/android/webkit/WebView>`_ with
@@ -34,7 +34,7 @@ dependencies for Android devices, and bundling it with the app's python code
3434
and dependencies. The Python code is then interpreted on the Android device.
3535

3636
It is recommended that python-for-android be used via
37-
`Buildozer <https://buildozer.readthedocs.io/>`_, which ensures the correct
37+
`Buildozer <https://buildozer.readthedocs.io/en/latest/>`_, which ensures the correct
3838
dependencies are pre-installed, and centralizes the configuration. However,
3939
python-for-android is not limited to being used with Buildozer.
4040

doc/source/services.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,15 @@ The ``PATH_TO_SERVICE_PY`` is the relative path to the service entry point (like
6464
You can optionally specify the following parameters:
6565
- :code:`:foreground` for launching a service as an Android foreground service
6666
- :code:`:sticky` for launching a service that gets restarted by the Android OS on exit/error
67+
- :code:`:foregroundServiceType=TYPE` to specify the type of foreground service,
68+
where TYPE is one of the valid Android foreground service types
69+
(see `Android documentation <https://developer.android.com/develop/background-work/services/fgs/service-types>`__
70+
for more details). You can specify multiple types separated by a pipe
71+
character "|", e.g. :code:`:foregroundServiceType=location|mediaPlayback`. Mandatory
72+
if :code:`:foreground` is used on Android 14+.
6773
6874
Full command with all the optional parameters included would be:
69-
:code:`--service=myservice:services/myservice.py:foreground:sticky`
75+
:code:`--service=myservice:services/myservice.py:foreground:sticky:foregroundServiceType=location`
7076

7177
You can add multiple
7278
:code:`--service` arguments to include multiple services, or separate

pythonforandroid/androidndk.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ def llvm_readelf(self):
6666
def llvm_strip(self):
6767
return f"{self.llvm_binutils_prefix}strip"
6868

69+
@property
70+
def llvm_nm(self):
71+
return f"{self.llvm_binutils_prefix}nm"
72+
6973
@property
7074
def sysroot(self):
7175
return os.path.join(self.llvm_prebuilt_dir, "sysroot")

0 commit comments

Comments
 (0)