Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,26 @@ jobs:
pip install tox>=2.0
tox -e pep8

spotless:
name: Java Spotless check
runs-on: ubuntu-latest
steps:
- name: Checkout python-for-android
uses: actions/checkout@v5
- name: Set up Java 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v4
- name: Run Spotless check
working-directory: pythonforandroid/bootstraps
run: ./common/build/gradlew spotlessCheck

test:
name: Pytest [Python ${{ matrix.python-version }} | ${{ matrix.os }}]
needs: flake8
needs: [flake8, spotless]
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
Expand Down Expand Up @@ -61,7 +78,7 @@ jobs:

ubuntu_build:
name: Build test APP [ ${{ matrix.runs_on }} | ${{ matrix.bootstrap.name }} ]
needs: [flake8]
needs: [flake8, spotless]
runs-on: ${{ matrix.runs_on }}
strategy:
matrix:
Expand Down Expand Up @@ -120,7 +137,7 @@ jobs:

macos_build:
name: Build test APP [ ${{ matrix.runs_on }} | ${{ matrix.bootstrap.name }} ]
needs: [flake8]
needs: [flake8, spotless]
runs-on: ${{ matrix.runs_on }}
strategy:
matrix:
Expand Down Expand Up @@ -194,7 +211,7 @@ jobs:

ubuntu_rebuild_updated_recipes:
name: Test updated recipes for arch ${{ matrix.android_arch }} [ ubuntu-latest ]
needs: [flake8]
needs: [flake8, spotless]
runs-on: ubuntu-latest
# continue on error to see failures across all architectures
continue-on-error: true
Expand Down Expand Up @@ -227,7 +244,7 @@ jobs:

macos_rebuild_updated_recipes:
name: Test updated recipes for arch ${{ matrix.android_arch }} [ ${{ matrix.runs_on }} ]
needs: [flake8]
needs: [flake8, spotless]
runs-on: ${{ matrix.runs_on }}
# continue on error to see failures across all architectures
continue-on-error: true
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,9 @@ coverage.xml
# testapp's build folder
testapps/build/

# Gradle build artifacts (Java linting)
pythonforandroid/bootstraps/.gradle/
pythonforandroid/bootstraps/build/

# Dolphin (the KDE file manager autogenerates the file `.directory`)
.directory
54 changes: 54 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,60 @@ latest python-for-android release that supported building Python 2 was version
On August 2021, we added support for Android App Bundle (aab). As a
collateral benefit, we now support multi-arch apk.

## Code Quality

### Python Linting

Python code is linted using flake8. Run it locally with:

```bash
tox -e pep8
```

### Java Linting

Java source files in the bootstrap directories are linted using
[Spotless](https://github.com/diffplug/spotless) with Google Java Format
(AOSP style). The CI runs this check automatically.

**Local execution** (requires Java 17+):

```bash
# Check for violations
make java-lint

# Auto-fix violations
make java-lint-fix
```

The Makefile uses the Gradle wrapper (`gradlew`), which automatically downloads
the correct Gradle version on first run. No manual Gradle installation is required.

**Using Docker** (if you don't have Java 17):

```bash
# Check for violations
make docker/java-lint

# Auto-fix violations
make docker/java-lint-fix
```

The Docker approach builds the project's Docker image (which includes Java 17)
and runs the linting inside the container.

**What gets linted:**

- All `.java` files in `pythonforandroid/bootstraps/*/build/src/main/java/`
- Excludes third-party code (`org/kamranzafar/jtar/`)

**Formatting rules applied:**

- Google Java Format with AOSP style (Android-friendly indentation)
- Removal of unused imports
- Trailing whitespace trimming
- Files end with newline

## Creating a new release

(These instructions are for core developers, not casual contributors.)
Expand Down
14 changes: 14 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@ virtualenv: $(VIRTUAL_ENV)
test:
$(TOX) -- tests/ --ignore tests/test_pythonpackage.py

# Java linting using Spotless (requires Java 17+, uses Gradle wrapper)
java-lint:
cd pythonforandroid/bootstraps && ./common/build/gradlew spotlessCheck

java-lint-fix:
cd pythonforandroid/bootstraps && ./common/build/gradlew spotlessApply

# Java linting via Docker (no local Java required)
docker/java-lint: docker/build
docker run --rm -v $(CURDIR):/home/user/app -w /home/user/app/pythonforandroid/bootstraps $(DOCKER_IMAGE) ./common/build/gradlew spotlessCheck

docker/java-lint-fix: docker/build
docker run --rm -v $(CURDIR):/home/user/app -w /home/user/app/pythonforandroid/bootstraps $(DOCKER_IMAGE) ./common/build/gradlew spotlessApply

# Also install and configure rust
rebuild_updated_recipes: virtualenv
. $(ACTIVATE) && \
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
package org.kivy.android.launcher;

import java.io.UnsupportedEncodingException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;
import java.util.Properties;

import android.util.Log;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;


/**
* This represents a project we've scanned for.
*/
/** This represents a project we've scanned for. */
public class Project {

public String dir = null;
Expand All @@ -30,9 +26,8 @@ static String decode(String s) {
}

/**
* Scans directory for a android.txt file. If it finds one,
* and it looks valid enough, then it creates a new Project,
* and returns that. Otherwise, returns null.
* Scans directory for a android.txt file. If it finds one, and it looks valid enough, then it
* creates a new Project, and returns that. Otherwise, returns null.
*/
public static Project scanDirectory(File dir) {

Expand Down Expand Up @@ -61,7 +56,7 @@ public static Project scanDirectory(File dir) {
}

// Make sure we're dealing with a directory.
if (! dir.isDirectory()) {
if (!dir.isDirectory()) {
return null;
}

Expand Down Expand Up @@ -94,6 +89,5 @@ public static Project scanDirectory(File dir) {
}

return null;

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import android.widget.ImageView;

import android.widget.TextView;
import org.renpy.android.ResourceManager;

public class ProjectAdapter extends ArrayAdapter<Project> {

private ResourceManager resourceManager;

public ProjectAdapter(Activity context) {
super(context, 0);
resourceManager = new ResourceManager(context);
Expand All @@ -29,7 +28,7 @@ public View getView(int position, View convertView, ViewGroup parent) {
title.setText(p.title);
author.setText(p.author);
icon.setImageBitmap(p.icon);
return v;

return v;
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
package org.kivy.android.launcher;

import android.app.Activity;

import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView;
import android.os.Environment;

import java.io.File;
import java.util.Arrays;
import android.net.Uri;

import org.renpy.android.ResourceManager;

public class ProjectChooser extends Activity implements AdapterView.OnItemClickListener {
Expand All @@ -22,8 +19,7 @@ public class ProjectChooser extends Activity implements AdapterView.OnItemClickL
String urlScheme;

@Override
public void onStart()
{
public void onStart() {
super.onStart();

resourceManager = new ResourceManager(this);
Expand Down Expand Up @@ -55,12 +51,12 @@ public void onStart()
}
}

if (projectAdapter.getCount() != 0) {
if (projectAdapter.getCount() != 0) {

View v = resourceManager.inflateView("project_chooser");
ListView l = (ListView) resourceManager.getViewById(v, "projectList");

l.setAdapter(projectAdapter);
l.setAdapter(projectAdapter);
l.setOnItemClickListener(this);

setContentView(v);
Expand All @@ -70,7 +66,10 @@ public void onStart()
View v = resourceManager.inflateView("project_empty");
TextView emptyText = (TextView) resourceManager.getViewById(v, "emptyText");

emptyText.setText("No projects are available to launch. Please place a project into " + dir + " and restart this application. Press the back button to exit.");
emptyText.setText(
"No projects are available to launch. Please place a project into "
+ dir
+ " and restart this application. Press the back button to exit.");

setContentView(v);
}
Expand All @@ -79,9 +78,7 @@ public void onStart()
public void onItemClick(AdapterView parent, View view, int position, long id) {
Project p = (Project) parent.getItemAtPosition(position);

Intent intent = new Intent(
"org.kivy.LAUNCH",
Uri.fromParts(urlScheme, p.dir, ""));
Intent intent = new Intent("org.kivy.LAUNCH", Uri.fromParts(urlScheme, p.dir, ""));

intent.setClassName(getPackageName(), "org.kivy.android.PythonActivity");
this.startActivity(intent);
Expand Down
60 changes: 60 additions & 0 deletions pythonforandroid/bootstraps/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Java Lint Configuration for python-for-android
// This file configures Spotless to lint Java source files across all bootstraps

plugins {
id 'java'
id 'com.diffplug.spotless' version '6.25.0'
}

// Repositories for plugin dependencies (e.g., google-java-format)
repositories {
mavenCentral()
}

// Define the root directory for bootstrap Java sources
def bootstrapsDir = "${rootProject.projectDir}"

// Collect all Java source directories from all bootstraps
def javaSourceDirs = []
file(bootstrapsDir).eachDir { bootstrapDir ->
def srcDir = new File(bootstrapDir, 'build/src/main/java')
if (srcDir.exists()) {
javaSourceDirs.add(srcDir.absolutePath)
}
}

sourceSets {
main {
java {
srcDirs = javaSourceDirs
}
}
}

spotless {
java {
// Target all Java files from the source directories
target fileTree(bootstrapsDir) {
include '**/build/src/main/java/**/*.java'
// Exclude third-party vendored code
exclude '**/org/kamranzafar/jtar/**'
}

// Use Google Java Format with AOSP style (Android-friendly, slightly relaxed)
googleJavaFormat('1.19.2').aosp()

// Remove unused imports
removeUnusedImports()

// Trim trailing whitespace
trimTrailingWhitespace()

// Ensure files end with a newline
endWithNewline()
}
}

// Disable compilation - we only want to lint, not build
tasks.withType(JavaCompile).configureEach {
enabled = false
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.kivy.android;

import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.Context;
import android.content.Intent;

public class GenericBroadcastReceiver extends BroadcastReceiver {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package org.kivy.android;

import android.content.Intent;
import android.content.Context;
import android.content.Intent;

public interface GenericBroadcastReceiverCallback {
void onReceive(Context context, Intent intent);
};
}
;
Loading