diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 85d0fe2231..6054a68dc7 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -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 @@ -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: @@ -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: @@ -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 @@ -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 diff --git a/.gitignore b/.gitignore index f36a2f3572..5f55723fd5 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2e118304bd..1987de13b1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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.) diff --git a/Makefile b/Makefile index 03c4ff3e52..f2724e0256 100644 --- a/Makefile +++ b/Makefile @@ -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) && \ diff --git a/pythonforandroid/bootstraps/_sdl_common/build/src/main/java/org/kivy/android/launcher/Project.java b/pythonforandroid/bootstraps/_sdl_common/build/src/main/java/org/kivy/android/launcher/Project.java index 9177b43bb7..b3d7dbc35c 100644 --- a/pythonforandroid/bootstraps/_sdl_common/build/src/main/java/org/kivy/android/launcher/Project.java +++ b/pythonforandroid/bootstraps/_sdl_common/build/src/main/java/org/kivy/android/launcher/Project.java @@ -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; @@ -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) { @@ -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; } @@ -94,6 +89,5 @@ public static Project scanDirectory(File dir) { } return null; - } } diff --git a/pythonforandroid/bootstraps/_sdl_common/build/src/main/java/org/kivy/android/launcher/ProjectAdapter.java b/pythonforandroid/bootstraps/_sdl_common/build/src/main/java/org/kivy/android/launcher/ProjectAdapter.java index 457f83f79b..62e31f8a79 100644 --- a/pythonforandroid/bootstraps/_sdl_common/build/src/main/java/org/kivy/android/launcher/ProjectAdapter.java +++ b/pythonforandroid/bootstraps/_sdl_common/build/src/main/java/org/kivy/android/launcher/ProjectAdapter.java @@ -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 { private ResourceManager resourceManager; - + public ProjectAdapter(Activity context) { super(context, 0); resourceManager = new ResourceManager(context); @@ -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; } } diff --git a/pythonforandroid/bootstraps/_sdl_common/build/src/main/java/org/kivy/android/launcher/ProjectChooser.java b/pythonforandroid/bootstraps/_sdl_common/build/src/main/java/org/kivy/android/launcher/ProjectChooser.java index 486f88bae4..da31e59e53 100644 --- a/pythonforandroid/bootstraps/_sdl_common/build/src/main/java/org/kivy/android/launcher/ProjectChooser.java +++ b/pythonforandroid/bootstraps/_sdl_common/build/src/main/java/org/kivy/android/launcher/ProjectChooser.java @@ -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 { @@ -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); @@ -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); @@ -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); } @@ -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); diff --git a/pythonforandroid/bootstraps/build.gradle b/pythonforandroid/bootstraps/build.gradle new file mode 100644 index 0000000000..42d1da7064 --- /dev/null +++ b/pythonforandroid/bootstraps/build.gradle @@ -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 +} diff --git a/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/GenericBroadcastReceiver.java b/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/GenericBroadcastReceiver.java index 58a1c5edf8..2fe7e28aed 100644 --- a/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/GenericBroadcastReceiver.java +++ b/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/GenericBroadcastReceiver.java @@ -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 { diff --git a/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/GenericBroadcastReceiverCallback.java b/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/GenericBroadcastReceiverCallback.java index 1a87c98b2d..5216bf9a58 100644 --- a/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/GenericBroadcastReceiverCallback.java +++ b/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/GenericBroadcastReceiverCallback.java @@ -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); -}; +} +; diff --git a/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonService.java b/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonService.java index f28946d501..8433aa4691 100644 --- a/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonService.java +++ b/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonService.java @@ -1,23 +1,21 @@ package org.kivy.android; -import android.os.Build; -import java.lang.reflect.Method; -import java.lang.reflect.InvocationTargetException; -import android.app.Service; -import android.os.IBinder; -import android.os.Bundle; -import android.content.Intent; -import android.content.Context; -import android.util.Log; import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.os.Build; +import android.os.Bundle; +import android.os.IBinder; import android.os.Process; +import android.util.Log; import java.io.File; - -//imports for channel definition -import android.app.NotificationManager; -import android.app.NotificationChannel; -import android.graphics.Color; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; public class PythonService extends Service implements Runnable { @@ -34,7 +32,6 @@ public class PythonService extends Service implements Runnable { // Argument to pass to Python code, private String pythonServiceArgument; - public static PythonService mService = null; private Intent startIntent = null; @@ -64,7 +61,7 @@ public int onStartCommand(Intent intent, int flags, int startId) { Log.v("python service", "service exists, do not start again"); return startType(); } - //intent is null if OS restarts a STICKY service + // intent is null if OS restarts a STICKY service if (intent == null) { Context context = getApplicationContext(); intent = getThisDefaultIntent(context, ""); @@ -78,9 +75,8 @@ public int onStartCommand(Intent intent, int flags, int startId) { pythonName = extras.getString("pythonName"); pythonHome = extras.getString("pythonHome"); pythonPath = extras.getString("pythonPath"); - boolean serviceStartAsForeground = ( - extras.getString("serviceStartAsForeground").equals("true") - ); + boolean serviceStartAsForeground = + (extras.getString("serviceStartAsForeground").equals("true")); pythonServiceArgument = extras.getString("pythonServiceArgument"); pythonThread = new Thread(this); pythonThread.start(); @@ -108,51 +104,68 @@ protected void doStartForeground(Bundle extras) { Notification notification; Context context = getApplicationContext(); Intent contextIntent = new Intent(context, PythonActivity.class); - PendingIntent pIntent = PendingIntent.getActivity(context, 0, contextIntent, - PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT); - - // Unspecified icon uses default. - int smallIconId = context.getApplicationInfo().icon; - if (smallIconName != null) { - if (!smallIconName.equals("")){ - int resId = getResources().getIdentifier(smallIconName, "mipmap", - getPackageName()); - if (resId ==0) { - resId = getResources().getIdentifier(smallIconName, "drawable", - getPackageName()); - } - if (resId !=0) { - smallIconId = resId; + PendingIntent pIntent = + PendingIntent.getActivity( + context, + 0, + contextIntent, + PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT); + + // Unspecified icon uses default. + int smallIconId = context.getApplicationInfo().icon; + if (smallIconName != null) { + if (!smallIconName.equals("")) { + int resId = getResources().getIdentifier(smallIconName, "mipmap", getPackageName()); + if (resId == 0) { + resId = + getResources() + .getIdentifier(smallIconName, "drawable", getPackageName()); + } + if (resId != 0) { + smallIconId = resId; + } } } - } - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { - // This constructor is deprecated - notification = new Notification( - smallIconId, serviceTitle, System.currentTimeMillis()); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + // This constructor is deprecated + notification = new Notification(smallIconId, serviceTitle, System.currentTimeMillis()); try { // prevent using NotificationCompat, this saves 100kb on apk - Method func = notification.getClass().getMethod( - "setLatestEventInfo", Context.class, CharSequence.class, - CharSequence.class, PendingIntent.class); + Method func = + notification + .getClass() + .getMethod( + "setLatestEventInfo", + Context.class, + CharSequence.class, + CharSequence.class, + PendingIntent.class); func.invoke(notification, context, contentTitle, contentText, pIntent); - } catch (NoSuchMethodException | IllegalAccessException | - IllegalArgumentException | InvocationTargetException e) { + } catch (NoSuchMethodException + | IllegalAccessException + | IllegalArgumentException + | InvocationTargetException e) { } } else { // for android 8+ we need to create our own channel // https://stackoverflow.com/questions/47531742/startforeground-fail-after-upgrade-to-android-8-1 String NOTIFICATION_CHANNEL_ID = "org.kivy.p4a" + getServiceId(); String channelName = "Background Service" + getServiceId(); - NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_NONE); + NotificationChannel chan = + new NotificationChannel( + NOTIFICATION_CHANNEL_ID, + channelName, + NotificationManager.IMPORTANCE_NONE); chan.setLightColor(Color.BLUE); chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); - NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + NotificationManager manager = + (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); manager.createNotificationChannel(chan); - Notification.Builder builder = new Notification.Builder(context, NOTIFICATION_CHANNEL_ID); + Notification.Builder builder = + new Notification.Builder(context, NOTIFICATION_CHANNEL_ID); builder.setContentTitle(contentTitle); builder.setContentText(contentText); builder.setContentIntent(pIntent); @@ -174,37 +187,42 @@ public void onDestroy() { } /** - * Stops the task gracefully when killed. - * Calling stopSelf() will trigger a onDestroy() call from the system. + * Stops the task gracefully when killed. Calling stopSelf() will trigger a onDestroy() call + * from the system. */ @Override public void onTaskRemoved(Intent rootIntent) { super.onTaskRemoved(rootIntent); - //sticky service runtime/restart is managed by the OS. leave it running when app is closed + // sticky service runtime/restart is managed by the OS. leave it running when app is closed if (startType() != START_STICKY) { stopSelf(); } } @Override - public void run(){ - String app_root = getFilesDir().getAbsolutePath() + "/app"; + public void run() { + String app_root = getFilesDir().getAbsolutePath() + "/app"; File app_root_file = new File(app_root); - PythonUtil.loadLibraries(app_root_file, - new File(getApplicationInfo().nativeLibraryDir)); + PythonUtil.loadLibraries(app_root_file, new File(getApplicationInfo().nativeLibraryDir)); this.mService = this; nativeStart( - androidPrivate, androidArgument, - serviceEntrypoint, pythonName, - pythonHome, pythonPath, - pythonServiceArgument); + androidPrivate, + androidArgument, + serviceEntrypoint, + pythonName, + pythonHome, + pythonPath, + pythonServiceArgument); stopSelf(); } // Native part public static native void nativeStart( - String androidPrivate, String androidArgument, - String serviceEntrypoint, String pythonName, - String pythonHome, String pythonPath, + String androidPrivate, + String androidArgument, + String serviceEntrypoint, + String pythonName, + String pythonHome, + String pythonPath, String pythonServiceArgument); } 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 abf21dd47b..b406942605 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 @@ -1,29 +1,27 @@ package org.kivy.android; -import java.io.InputStream; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.File; - import android.app.Activity; import android.content.Context; import android.content.res.Resources; import android.util.Log; import android.widget.Toast; - +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; import java.util.ArrayList; import java.util.regex.Pattern; - import org.renpy.android.AssetExtract; public class PythonUtil { - private static final String TAG = "pythonutil"; + private static final String TAG = "pythonutil"; - protected static void addLibraryIfExists(ArrayList libsList, String pattern, File libsDir) { + protected static void addLibraryIfExists( + ArrayList libsList, String pattern, File libsDir) { // pattern should be the name of the lib file, without the // preceding "lib" or suffix ".so", for instance "ssl.*" will // match files of the form "libssl.*.so". - File [] files = libsDir.listFiles(); + File[] files = libsDir.listFiles(); pattern = "lib" + pattern + "\\.so"; Pattern p = Pattern.compile(pattern); @@ -42,9 +40,19 @@ protected static ArrayList getLibraries(File libsDir) { ArrayList libsList = new ArrayList<>(); String[] libNames = { - "sqlite3", "ffi", "png16", "ssl.*", "crypto.*", - "SDL2", "SDL2_image", "SDL2_mixer", "SDL2_ttf", - "SDL3", "SDL3_image", "SDL3_mixer", "SDL3_ttf" + "sqlite3", + "ffi", + "png16", + "ssl.*", + "crypto.*", + "SDL2", + "SDL2_image", + "SDL2_mixer", + "SDL2_ttf", + "SDL3", + "SDL3_image", + "SDL3_mixer", + "SDL3_ttf" }; for (String name : libNames) { @@ -63,14 +71,16 @@ public static void loadLibraries(File filesDir, File libsDir) { boolean foundPython = false; for (String lib : getLibraries(libsDir)) { - if (lib.startsWith("python") && foundPython) {continue;} + if (lib.startsWith("python") && foundPython) { + continue; + } Log.v(TAG, "Loading library: " + lib); try { System.loadLibrary(lib); if (lib.startsWith("python")) { foundPython = true; } - } catch(UnsatisfiedLinkError e) { + } catch (UnsatisfiedLinkError e) { // If this is the last possible libpython // load, and it has failed, give a more // general error @@ -101,15 +111,14 @@ public static String getResourceString(Context ctx, String name) { return res.getString(id); } - /** - * Show an error using a toast. (Only makes sense from non-UI threads.) - */ + /** Show an error using a toast. (Only makes sense from non-UI threads.) */ protected static void toastError(final Activity activity, final String msg) { - activity.runOnUiThread(new Runnable () { - public void run() { - Toast.makeText(activity, msg, Toast.LENGTH_LONG).show(); - } - }); + activity.runOnUiThread( + new Runnable() { + public void run() { + Toast.makeText(activity, msg, Toast.LENGTH_LONG).show(); + } + }); // Wait to show the error. synchronized (activity) { @@ -130,10 +139,7 @@ protected static void recursiveDelete(File f) { } public static void unpackAsset( - Context ctx, - final String resource, - File target, - boolean cleanup_on_version_update) { + Context ctx, final String resource, File target, boolean cleanup_on_version_update) { Log.v(TAG, "Unpacking " + resource + " " + target.getName()); @@ -163,7 +169,7 @@ public static void unpackAsset( } // If the disk data is out of date, extract it and write the version file. - if (! dataVersion.equals(diskVersion)) { + if (!dataVersion.equals(diskVersion)) { Log.v(TAG, "Extracting " + resource + " assets."); if (cleanup_on_version_update) { @@ -175,7 +181,7 @@ public static void unpackAsset( if (!ae.extractTar(resource + ".tar", target.getAbsolutePath(), "private")) { String msg = "Could not extract " + resource + " data."; if (ctx instanceof Activity) { - toastError((Activity)ctx, msg); + toastError((Activity) ctx, msg); } else { Log.v(TAG, msg); } @@ -196,10 +202,7 @@ public static void unpackAsset( } public static void unpackPyBundle( - Context ctx, - final String resource, - File target, - boolean cleanup_on_version_update) { + Context ctx, final String resource, File target, boolean cleanup_on_version_update) { Log.v(TAG, "Unpacking " + resource + " " + target.getName()); @@ -228,7 +231,7 @@ public static void unpackPyBundle( diskVersion = ""; } - if (! dataVersion.equals(diskVersion)) { + if (!dataVersion.equals(diskVersion)) { // If the disk data is out of date, extract it and write the version file. Log.v(TAG, "Extracting " + resource + " assets."); @@ -241,7 +244,7 @@ public static void unpackPyBundle( if (!ae.extractTar(resource + ".so", target.getAbsolutePath(), "pybundle")) { String msg = "Could not extract " + resource + " data."; if (ctx instanceof Activity) { - toastError((Activity)ctx, msg); + toastError((Activity) ctx, msg); } else { Log.v(TAG, msg); } diff --git a/pythonforandroid/bootstraps/common/build/src/main/java/org/renpy/android/AssetExtract.java b/pythonforandroid/bootstraps/common/build/src/main/java/org/renpy/android/AssetExtract.java index 0a5dda6567..dc8f54738e 100644 --- a/pythonforandroid/bootstraps/common/build/src/main/java/org/renpy/android/AssetExtract.java +++ b/pythonforandroid/bootstraps/common/build/src/main/java/org/renpy/android/AssetExtract.java @@ -3,21 +3,18 @@ package org.renpy.android; import android.content.Context; +import android.content.res.AssetManager; import android.util.Log; - import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.FileOutputStream; -import java.io.FileNotFoundException; -import java.io.File; -import java.io.FileInputStream; - import java.util.zip.GZIPInputStream; - -import android.content.res.AssetManager; import org.kamranzafar.jtar.TarEntry; import org.kamranzafar.jtar.TarInputStream; @@ -37,13 +34,17 @@ public boolean extractTar(String asset, String target, String method) { TarInputStream tis = null; try { - if(method == "private"){ + if (method == "private") { assetStream = mAssetManager.open(asset, AssetManager.ACCESS_STREAMING); } else if (method == "pybundle") { assetStream = new FileInputStream(asset); } - - tis = new TarInputStream(new BufferedInputStream(new GZIPInputStream(new BufferedInputStream(assetStream, 8192)), 8192)); + + tis = + new TarInputStream( + new BufferedInputStream( + new GZIPInputStream(new BufferedInputStream(assetStream, 8192)), + 8192)); } catch (IOException e) { Log.e("python", "opening up extract tar", e); return false; @@ -54,12 +55,12 @@ public boolean extractTar(String asset, String target, String method) { try { entry = tis.getNextEntry(); - } catch ( IOException e ) { + } catch (IOException e) { Log.e("python", "extracting tar", e); return false; } - if ( entry == null ) { + if (entry == null) { break; } @@ -68,8 +69,10 @@ public boolean extractTar(String asset, String target, String method) { if (entry.isDirectory()) { try { - new File(target +"/" + entry.getName()).mkdirs(); - } catch ( SecurityException e ) { }; + new File(target + "/" + entry.getName()).mkdirs(); + } catch (SecurityException e) { + } + ; continue; } @@ -79,9 +82,10 @@ public boolean extractTar(String asset, String target, String method) { try { out = new BufferedOutputStream(new FileOutputStream(path), 8192); - } catch ( FileNotFoundException | SecurityException e ) {} + } catch (FileNotFoundException | SecurityException e) { + } - if ( out == null ) { + if (out == null) { Log.e("python", "could not open " + path); return false; } @@ -99,7 +103,7 @@ public boolean extractTar(String asset, String target, String method) { out.flush(); out.close(); - } catch ( IOException e ) { + } catch (IOException e) { Log.e("python", "extracting zip", e); return false; } diff --git a/pythonforandroid/bootstraps/common/build/src/main/java/org/renpy/android/Hardware.java b/pythonforandroid/bootstraps/common/build/src/main/java/org/renpy/android/Hardware.java index 8ed165233d..13348fcfde 100644 --- a/pythonforandroid/bootstraps/common/build/src/main/java/org/renpy/android/Hardware.java +++ b/pythonforandroid/bootstraps/common/build/src/main/java/org/renpy/android/Hardware.java @@ -1,41 +1,36 @@ package org.renpy.android; +import android.content.BroadcastReceiver; import android.content.Context; -import android.os.Vibrator; +import android.content.Intent; +import android.content.IntentFilter; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.net.wifi.ScanResult; +import android.net.wifi.WifiManager; +import android.os.Vibrator; import android.util.DisplayMetrics; -import android.view.inputmethod.InputMethodManager; import android.view.View; - +import android.view.inputmethod.InputMethodManager; import java.util.List; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiManager; -import android.content.BroadcastReceiver; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; - import org.kivy.android.PythonActivity; /** - * Methods that are expected to be called via JNI, to access the - * device's non-screen hardware. (For example, the vibration and - * accelerometer.) + * Methods that are expected to be called via JNI, to access the device's non-screen hardware. (For + * example, the vibration and accelerometer.) */ public class Hardware { // The context. static Context context; static View view; - public static final float defaultRv[] = { 0f, 0f, 0f }; + public static final float defaultRv[] = {0f, 0f, 0f}; - /** - * Vibrate for s seconds. - */ + /** Vibrate for s seconds. */ public static void vibrate(double s) { Vibrator v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); if (v != null) { @@ -43,9 +38,7 @@ public static void vibrate(double s) { } } - /** - * Get an Overview of all Hardware Sensors of an Android Device - */ + /** Get an Overview of all Hardware Sensors of an Android Device */ public static String getHardwareSensors() { SensorManager sm = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); List allSensors = sm.getSensorList(Sensor.TYPE_ALL); @@ -58,7 +51,7 @@ public static String getHardwareSensors() { resultString += String.format(",Version=" + s.getVersion()); resultString += String.format(",MaximumRange=" + s.getMaximumRange()); // XXX MinDelay is not in the 2.2 - //resultString += String.format(",MinDelay=" + s.getMinDelay()); + // resultString += String.format(",MinDelay=" + s.getMinDelay()); resultString += String.format(",Power=" + s.getPower()); resultString += String.format(",Type=" + s.getType() + "\n"); } @@ -67,7 +60,6 @@ public static String getHardwareSensors() { return ""; } - /** * Get Access to 3 Axis Hardware Sensors Accelerometer, Orientation and Magnetic Field Sensors */ @@ -79,20 +71,17 @@ public static class generic3AxisSensor implements SensorEventListener { public generic3AxisSensor(int sensorType) { sSensorType = sensorType; - sSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE); + sSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); sSensor = sSensorManager.getDefaultSensor(sSensorType); } - public void onAccuracyChanged(Sensor sensor, int accuracy) { - } + public void onAccuracyChanged(Sensor sensor, int accuracy) {} public void onSensorChanged(SensorEvent event) { sSensorEvent = event; } - /** - * Enable or disable the Sensor by registering/unregistering - */ + /** Enable or disable the Sensor by registering/unregistering */ public void changeStatus(boolean enable) { if (enable) { sSensorManager.registerListener(this, sSensor, SensorManager.SENSOR_DELAY_NORMAL); @@ -101,9 +90,7 @@ public void changeStatus(boolean enable) { } } - /** - * Read the Sensor - */ + /** Read the Sensor */ public float[] readSensor() { if (sSensorEvent != null) { return sSensorEvent.values; @@ -117,46 +104,43 @@ public float[] readSensor() { public static generic3AxisSensor orientationSensor = null; public static generic3AxisSensor magneticFieldSensor = null; - /** - * functions for backward compatibility reasons - */ - + /** functions for backward compatibility reasons */ public static void accelerometerEnable(boolean enable) { - if ( accelerometerSensor == null ) + if (accelerometerSensor == null) accelerometerSensor = new generic3AxisSensor(Sensor.TYPE_ACCELEROMETER); accelerometerSensor.changeStatus(enable); } + public static float[] accelerometerReading() { - if ( accelerometerSensor == null ) - return defaultRv; + if (accelerometerSensor == null) return defaultRv; return (float[]) accelerometerSensor.readSensor(); } + public static void orientationSensorEnable(boolean enable) { - if ( orientationSensor == null ) + if (orientationSensor == null) orientationSensor = new generic3AxisSensor(Sensor.TYPE_ORIENTATION); orientationSensor.changeStatus(enable); } + public static float[] orientationSensorReading() { - if ( orientationSensor == null ) - return defaultRv; + if (orientationSensor == null) return defaultRv; return (float[]) orientationSensor.readSensor(); } + public static void magneticFieldSensorEnable(boolean enable) { - if ( magneticFieldSensor == null ) + if (magneticFieldSensor == null) magneticFieldSensor = new generic3AxisSensor(Sensor.TYPE_MAGNETIC_FIELD); magneticFieldSensor.changeStatus(enable); } + public static float[] magneticFieldSensorReading() { - if ( magneticFieldSensor == null ) - return defaultRv; + if (magneticFieldSensor == null) return defaultRv; return (float[]) magneticFieldSensor.readSensor(); } - static public DisplayMetrics metrics = new DisplayMetrics(); + public static DisplayMetrics metrics = new DisplayMetrics(); - /** - * Get display DPI. - */ + /** Get display DPI. */ public static int getDPI() { // AND: Shouldn't have to get the metrics like this every time... PythonActivity.mActivity.getWindowManager().getDefaultDisplay().getMetrics(metrics); @@ -169,7 +153,8 @@ public static int getDPI() { // public static void showKeyboard(int input_type) { // //Log.i("python", "hardware.Java show_keyword " input_type); - // InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); + // InputMethodManager imm = (InputMethodManager) + // context.getSystemService(Context.INPUT_METHOD_SERVICE); // SDLSurfaceView vw = (SDLSurfaceView) view; @@ -183,47 +168,43 @@ public static int getDPI() { // imm.showSoftInput(view, InputMethodManager.SHOW_FORCED); // } - /** - * Hide the soft keyboard. - */ + /** Hide the soft keyboard. */ public static void hideKeyboard() { - InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); + InputMethodManager imm = + (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } - /** - * Scan WiFi networks - */ + /** Scan WiFi networks */ static List latestResult; - public static void enableWifiScanner() - { + public static void enableWifiScanner() { IntentFilter i = new IntentFilter(); i.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); - context.registerReceiver(new BroadcastReceiver() { - - @Override - public void onReceive(Context c, Intent i) { - // Code to execute when SCAN_RESULTS_AVAILABLE_ACTION event occurs - WifiManager w = (WifiManager) c.getSystemService(Context.WIFI_SERVICE); - latestResult = w.getScanResults(); // Returns a of scanResults - } - - }, i); - + context.registerReceiver( + new BroadcastReceiver() { + + @Override + public void onReceive(Context c, Intent i) { + // Code to execute when SCAN_RESULTS_AVAILABLE_ACTION event occurs + WifiManager w = (WifiManager) c.getSystemService(Context.WIFI_SERVICE); + latestResult = w.getScanResults(); // Returns a of scanResults + } + }, + i); } public static String scanWifi() { // Now you can call this and it should execute the broadcastReceiver's // onReceive() - if (latestResult != null){ + if (latestResult != null) { String latestResultString = ""; - for (ScanResult result : latestResult) - { - latestResultString += String.format("%s\t%s\t%d\n", result.SSID, result.BSSID, result.level); + for (ScanResult result : latestResult) { + latestResultString += + String.format("%s\t%s\t%d\n", result.SSID, result.BSSID, result.level); } return latestResultString; @@ -232,22 +213,18 @@ public static String scanWifi() { return ""; } - /** - * network state - */ - + /** network state */ public static boolean network_state = false; /** * Check network state directly * - * (only one connection can be active at a given moment, detects all network type) - * + *

(only one connection can be active at a given moment, detects all network type) */ - public static boolean checkNetwork() - { + public static boolean checkNetwork() { boolean state = false; - final ConnectivityManager conMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + final ConnectivityManager conMgr = + (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); final NetworkInfo activeNetwork = conMgr.getActiveNetworkInfo(); if (activeNetwork != null && activeNetwork.isConnected()) { @@ -259,21 +236,18 @@ public static boolean checkNetwork() return state; } - /** - * To receive network state changes - */ - public static void registerNetworkCheck() - { + /** To receive network state changes */ + public static void registerNetworkCheck() { IntentFilter i = new IntentFilter(); i.addAction(ConnectivityManager.CONNECTIVITY_ACTION); - context.registerReceiver(new BroadcastReceiver() { - - @Override - public void onReceive(Context c, Intent i) { - network_state = checkNetwork(); - } - - }, i); + context.registerReceiver( + new BroadcastReceiver() { + + @Override + public void onReceive(Context c, Intent i) { + network_state = checkNetwork(); + } + }, + i); } - } diff --git a/pythonforandroid/bootstraps/common/build/src/main/java/org/renpy/android/ResourceManager.java b/pythonforandroid/bootstraps/common/build/src/main/java/org/renpy/android/ResourceManager.java index a170c846b4..3cebc80c6c 100644 --- a/pythonforandroid/bootstraps/common/build/src/main/java/org/renpy/android/ResourceManager.java +++ b/pythonforandroid/bootstraps/common/build/src/main/java/org/renpy/android/ResourceManager.java @@ -1,16 +1,13 @@ /** - * This class takes care of managing resources for us. In our code, we - * can't use R, since the name of the package containing R will - * change. So this is the next best thing. + * This class takes care of managing resources for us. In our code, we can't use R, since the name + * of the package containing R will change. So this is the next best thing. */ - package org.renpy.android; import android.app.Activity; import android.content.res.Resources; -import android.view.View; - import android.util.Log; +import android.view.View; public class ResourceManager { @@ -49,5 +46,4 @@ public View getViewById(View v, String name) { int id = getIdentifier(name, "id"); return v.findViewById(id); } - } diff --git a/pythonforandroid/bootstraps/common/build/templates/Service.tmpl.java b/pythonforandroid/bootstraps/common/build/templates/Service.tmpl.java index 9406f91d89..bbce7bed4f 100644 --- a/pythonforandroid/bootstraps/common/build/templates/Service.tmpl.java +++ b/pythonforandroid/bootstraps/common/build/templates/Service.tmpl.java @@ -17,12 +17,12 @@ public int startType() { protected int getServiceId() { return {{ service_id }}; } - + static private void _start(Context ctx, String smallIconName, - String contentTitle, String contentText, - String pythonServiceArgument) { + String contentTitle, String contentText, + String pythonServiceArgument) { Intent intent = getDefaultIntent(ctx, smallIconName, contentTitle, - contentText, pythonServiceArgument); + contentText, pythonServiceArgument); ctx.startService(intent); } @@ -31,13 +31,13 @@ static public void start(Context ctx, String pythonServiceArgument) { } static public void start(Context ctx, String smallIconName, - String contentTitle, String contentText, + String contentTitle, String contentText, String pythonServiceArgument) { - _start(ctx, smallIconName, contentTitle, contentText, pythonServiceArgument); - } + _start(ctx, smallIconName, contentTitle, contentText, pythonServiceArgument); + } static public Intent getDefaultIntent(Context ctx, String smallIconName, - String contentTitle, String contentText, + String contentTitle, String contentText, String pythonServiceArgument) { Intent intent = new Intent(ctx, Service{{ name|capitalize }}.class); String argument = ctx.getFilesDir().getAbsolutePath() + "/app"; @@ -58,8 +58,8 @@ static public Intent getDefaultIntent(Context ctx, String smallIconName, @Override protected Intent getThisDefaultIntent(Context ctx, String pythonServiceArgument) { - return Service{{ name|capitalize }}.getDefaultIntent(ctx, "", "", "", - pythonServiceArgument); + return Service{{ name|capitalize }}.getDefaultIntent(ctx, "", "", "", + pythonServiceArgument); } static public void stop(Context ctx) { diff --git a/pythonforandroid/bootstraps/gradle.properties b/pythonforandroid/bootstraps/gradle.properties new file mode 100644 index 0000000000..350d8b0889 --- /dev/null +++ b/pythonforandroid/bootstraps/gradle.properties @@ -0,0 +1,9 @@ +# Gradle properties for Java lint project +# Disable daemon for CI environments +org.gradle.daemon=false + +# Use parallel execution where possible +org.gradle.parallel=true + +# Configure JVM memory +org.gradle.jvmargs=-Xmx512m 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 169fd323bf..01bdd96805 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 @@ -1,25 +1,19 @@ package org.kivy.android; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.os.PowerManager; import android.os.SystemClock; - +import android.util.Log; +import android.view.KeyEvent; +import android.widget.Toast; import java.io.File; +import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.ArrayList; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.DialogInterface; -import android.content.Intent; -import android.view.KeyEvent; -import android.util.Log; -import android.widget.Toast; -import android.os.Bundle; -import android.os.PowerManager; -import android.content.Context; -import android.content.pm.PackageManager; - import org.qtproject.qt.android.bindings.QtActivity; public class PythonActivity extends QtActivity { @@ -32,16 +26,16 @@ public class PythonActivity extends QtActivity { private PowerManager.WakeLock mWakeLock = null; public String getAppRoot() { - String app_root = getFilesDir().getAbsolutePath() + "/app"; + String app_root = getFilesDir().getAbsolutePath() + "/app"; return app_root; } public String getEntryPoint(String search_dir) { /* Get the main file (.pyc|.py) depending on if we * have a compiled version or not. - */ + */ List entryPoints = new ArrayList(); - entryPoints.add("main.pyc"); // python 3 compiled files + entryPoints.add("main.pyc"); // python 3 compiled files for (String value : entryPoints) { File mainFile = new File(search_dir + "/" + value); if (mainFile.exists()) { @@ -52,9 +46,7 @@ public String getEntryPoint(String search_dir) { } public void setEnvironmentVariable(String key, String value) { - /** - * Sets an environment variable based on key/value. - **/ + /** Sets an environment variable based on key/value. */ try { android.system.Os.setenv(key, value, true); } catch (Exception e) { @@ -69,7 +61,11 @@ public void onCreate(Bundle savedInstanceState) { Log.v(TAG, "Ready to unpack"); File app_root_file = new File(getAppRoot()); PythonUtil.unpackAsset(mActivity, "private", app_root_file, true); - PythonUtil.unpackPyBundle(mActivity, getApplicationInfo().nativeLibraryDir + "/" + "libpybundle", app_root_file, false); + PythonUtil.unpackPyBundle( + mActivity, + getApplicationInfo().nativeLibraryDir + "/" + "libpybundle", + app_root_file, + false); Log.v("Python", "Device: " + android.os.Build.DEVICE); Log.v("Python", "Model: " + android.os.Build.MODEL); @@ -96,12 +92,17 @@ public void onCreate(Bundle savedInstanceState) { this.mActivity = this; try { Log.v(TAG, "Access to our meta-data..."); - mActivity.mMetaData = mActivity.getPackageManager().getApplicationInfo( - mActivity.getPackageName(), PackageManager.GET_META_DATA).metaData; + mActivity.mMetaData = + mActivity + .getPackageManager() + .getApplicationInfo( + mActivity.getPackageName(), PackageManager.GET_META_DATA) + .metaData; PowerManager pm = (PowerManager) mActivity.getSystemService(Context.POWER_SERVICE); - if ( mActivity.mMetaData.getInt("wakelock") == 1 ) { - mActivity.mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "Screen On"); + if (mActivity.mMetaData.getInt("wakelock") == 1) { + mActivity.mWakeLock = + pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "Screen On"); mActivity.mWakeLock.acquire(); } } catch (PackageManager.NameNotFoundException e) { @@ -118,14 +119,14 @@ public void onDestroy() { } long lastBackClick = SystemClock.elapsedRealtime(); + @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // If it wasn't the Back key or there's no web page history, bubble up to the default // system behavior (probably exit the activity) - if (SystemClock.elapsedRealtime() - lastBackClick > 2000){ + if (SystemClock.elapsedRealtime() - lastBackClick > 2000) { lastBackClick = SystemClock.elapsedRealtime(); - Toast.makeText(this, "Click again to close the app", - Toast.LENGTH_LONG).show(); + Toast.makeText(this, "Click again to close the app", Toast.LENGTH_LONG).show(); return true; } @@ -133,8 +134,7 @@ public boolean onKeyDown(int keyCode, KeyEvent event) { return super.onKeyDown(keyCode, event); } - - //---------------------------------------------------------------------------- + // ---------------------------------------------------------------------------- // Listener interface for onNewIntent // @@ -145,31 +145,30 @@ public interface NewIntentListener { private List newIntentListeners = null; public void registerNewIntentListener(NewIntentListener listener) { - if ( this.newIntentListeners == null ) - this.newIntentListeners = Collections.synchronizedList(new ArrayList()); + if (this.newIntentListeners == null) + this.newIntentListeners = + Collections.synchronizedList(new ArrayList()); this.newIntentListeners.add(listener); } public void unregisterNewIntentListener(NewIntentListener listener) { - if ( this.newIntentListeners == null ) - return; + if (this.newIntentListeners == null) return; this.newIntentListeners.remove(listener); } @Override protected void onNewIntent(Intent intent) { - if ( this.newIntentListeners == null ) - return; + if (this.newIntentListeners == null) return; this.onResume(); - synchronized ( this.newIntentListeners ) { + synchronized (this.newIntentListeners) { Iterator iterator = this.newIntentListeners.iterator(); - while ( iterator.hasNext() ) { + while (iterator.hasNext()) { (iterator.next()).onNewIntent(intent); } } } - //---------------------------------------------------------------------------- + // ---------------------------------------------------------------------------- // Listener interface for onActivityResult // @@ -180,55 +179,43 @@ public interface ActivityResultListener { private List activityResultListeners = null; public void registerActivityResultListener(ActivityResultListener listener) { - if ( this.activityResultListeners == null ) - this.activityResultListeners = Collections.synchronizedList(new ArrayList()); + if (this.activityResultListeners == null) + this.activityResultListeners = + Collections.synchronizedList(new ArrayList()); this.activityResultListeners.add(listener); } public void unregisterActivityResultListener(ActivityResultListener listener) { - if ( this.activityResultListeners == null ) - return; + if (this.activityResultListeners == null) return; this.activityResultListeners.remove(listener); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { - if ( this.activityResultListeners == null ) - return; + if (this.activityResultListeners == null) return; this.onResume(); - synchronized ( this.activityResultListeners ) { + synchronized (this.activityResultListeners) { Iterator iterator = this.activityResultListeners.iterator(); - while ( iterator.hasNext() ) + while (iterator.hasNext()) (iterator.next()).onActivityResult(requestCode, resultCode, intent); } } public static void start_service( - String serviceTitle, - String serviceDescription, - String pythonServiceArgument - ) { - _do_start_service( - serviceTitle, serviceDescription, pythonServiceArgument, true - ); + String serviceTitle, String serviceDescription, String pythonServiceArgument) { + _do_start_service(serviceTitle, serviceDescription, pythonServiceArgument, true); } public static void start_service_not_as_foreground( - String serviceTitle, - String serviceDescription, - String pythonServiceArgument - ) { - _do_start_service( - serviceTitle, serviceDescription, pythonServiceArgument, false - ); + String serviceTitle, String serviceDescription, String pythonServiceArgument) { + _do_start_service(serviceTitle, serviceDescription, pythonServiceArgument, false); } public static void _do_start_service( String serviceTitle, String serviceDescription, String pythonServiceArgument, - boolean showForegroundNotification - ) { + boolean showForegroundNotification) { Intent serviceIntent = new Intent(PythonActivity.mActivity, PythonService.class); String argument = PythonActivity.mActivity.getFilesDir().getAbsolutePath(); String app_root_dir = PythonActivity.mActivity.getAppRoot(); @@ -239,9 +226,8 @@ public static void _do_start_service( 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( + "serviceStartAsForeground", (showForegroundNotification ? "true" : "false")); serviceIntent.putExtra("serviceTitle", serviceTitle); serviceIntent.putExtra("serviceDescription", serviceDescription); serviceIntent.putExtra("pythonServiceArgument", pythonServiceArgument); @@ -252,5 +238,4 @@ public static void stop_service() { Intent serviceIntent = new Intent(PythonActivity.mActivity, PythonService.class); PythonActivity.mActivity.stopService(serviceIntent); } - } 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 361975a4cf..04d3eee30a 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 @@ -1,22 +1,11 @@ package org.kivy.android; -import java.io.InputStream; -import java.io.FileWriter; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Timer; -import java.util.TimerTask; - import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; +import android.content.res.Resources.NotFoundException; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; @@ -25,21 +14,27 @@ import android.os.Bundle; import android.os.PowerManager; import android.util.Log; -import android.view.inputmethod.InputMethodManager; import android.view.SurfaceView; -import android.view.ViewGroup; import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; import android.widget.ImageView; import android.widget.Toast; -import android.content.res.Resources.NotFoundException; - -import org.libsdl.app.SDLActivity; - +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; import org.kivy.android.launcher.Project; - +import org.libsdl.app.SDLActivity; import org.renpy.android.ResourceManager; - public class PythonActivity extends SDLActivity { private static final String TAG = "PythonActivity"; @@ -50,7 +45,7 @@ public class PythonActivity extends SDLActivity { private PowerManager.WakeLock mWakeLock = null; public String getAppRoot() { - String app_root = getFilesDir().getAbsolutePath() + "/app"; + String app_root = getFilesDir().getAbsolutePath() + "/app"; return app_root; } @@ -72,23 +67,20 @@ protected void onCreate(Bundle savedInstanceState) { public void loadLibraries() { String app_root = new String(getAppRoot()); File app_root_file = new File(app_root); - PythonUtil.loadLibraries(app_root_file, - new File(getApplicationInfo().nativeLibraryDir)); + PythonUtil.loadLibraries(app_root_file, new File(getApplicationInfo().nativeLibraryDir)); } - /** - * Show an error using a toast. (Only makes sense from non-UI - * threads.) - */ + /** Show an error using a toast. (Only makes sense from non-UI threads.) */ public void toastError(final String msg) { final Activity thisActivity = this; - runOnUiThread(new Runnable () { - public void run() { - Toast.makeText(thisActivity, msg, Toast.LENGTH_LONG).show(); - } - }); + runOnUiThread( + new Runnable() { + public void run() { + Toast.makeText(thisActivity, msg, Toast.LENGTH_LONG).show(); + } + }); // Wait to show the error. synchronized (this) { @@ -105,7 +97,11 @@ protected String doInBackground(String... params) { File app_root_file = new File(params[0]); Log.v(TAG, "Ready to unpack"); PythonUtil.unpackAsset(mActivity, "private", app_root_file, true); - PythonUtil.unpackPyBundle(mActivity, getApplicationInfo().nativeLibraryDir + "/" + "libpybundle", app_root_file, false); + PythonUtil.unpackPyBundle( + mActivity, + getApplicationInfo().nativeLibraryDir + "/" + "libpybundle", + app_root_file, + false); return null; } @@ -127,8 +123,9 @@ protected void onPostExecute(String result) { mActivity.showLoadingScreen(getLoadingScreen()); String app_root_dir = getAppRoot(); - if (getIntent() != null && getIntent().getAction() != null && - getIntent().getAction().equals("org.kivy.LAUNCH")) { + if (getIntent() != null + && getIntent().getAction() != null + && getIntent().getAction().equals("org.kivy.LAUNCH")) { File path = new File(getIntent().getData().getSchemeSpecificPart()); Project p = Project.scanDirectory(path); @@ -170,15 +167,20 @@ protected void onPostExecute(String result) { try { Log.v(TAG, "Access to our meta-data..."); - mActivity.mMetaData = mActivity.getPackageManager().getApplicationInfo( - mActivity.getPackageName(), PackageManager.GET_META_DATA).metaData; + mActivity.mMetaData = + mActivity + .getPackageManager() + .getApplicationInfo( + mActivity.getPackageName(), PackageManager.GET_META_DATA) + .metaData; PowerManager pm = (PowerManager) mActivity.getSystemService(Context.POWER_SERVICE); - if ( mActivity.mMetaData.getInt("wakelock") == 1 ) { - mActivity.mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "Screen On"); + if (mActivity.mMetaData.getInt("wakelock") == 1) { + mActivity.mWakeLock = + pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "Screen On"); mActivity.mWakeLock.acquire(); } - if ( mActivity.mMetaData.getInt("surface.transparent") != 0 ) { + if (mActivity.mMetaData.getInt("surface.transparent") != 0) { Log.v(TAG, "Surface will be transparent."); getSurface().setZOrderOnTop(true); getSurface().getHolder().setFormat(PixelFormat.TRANSPARENT); @@ -189,14 +191,14 @@ protected void onPostExecute(String result) { } // Launch app if that hasn't been done yet: - if (mActivity.mHasFocus && ( + if (mActivity.mHasFocus + && ( // never went into proper resume state: - mActivity.mCurrentNativeState == NativeState.INIT || - ( - // resumed earlier but wasn't ready yet - mActivity.mCurrentNativeState == NativeState.RESUMED && - mActivity.mSDLThread == null - ))) { + mActivity.mCurrentNativeState == NativeState.INIT + || ( + // resumed earlier but wasn't ready yet + mActivity.mCurrentNativeState == NativeState.RESUMED + && mActivity.mSDLThread == null))) { // Because sometimes the app will get stuck here and never // actually run, ensure that it gets launched if we're active: mActivity.resumeNativeThread(); @@ -204,23 +206,21 @@ protected void onPostExecute(String result) { } @Override - protected void onPreExecute() { - } + protected void onPreExecute() {} @Override - protected void onProgressUpdate(Void... values) { - } + protected void onProgressUpdate(Void... values) {} } public static ViewGroup getLayout() { - return mLayout; + return mLayout; } public static SurfaceView getSurface() { - return mSurface; + return mSurface; } - //---------------------------------------------------------------------------- + // ---------------------------------------------------------------------------- // Listener interface for onNewIntent // @@ -231,31 +231,30 @@ public interface NewIntentListener { private List newIntentListeners = null; public void registerNewIntentListener(NewIntentListener listener) { - if ( this.newIntentListeners == null ) - this.newIntentListeners = Collections.synchronizedList(new ArrayList()); + if (this.newIntentListeners == null) + this.newIntentListeners = + Collections.synchronizedList(new ArrayList()); this.newIntentListeners.add(listener); } public void unregisterNewIntentListener(NewIntentListener listener) { - if ( this.newIntentListeners == null ) - return; + if (this.newIntentListeners == null) return; this.newIntentListeners.remove(listener); } @Override protected void onNewIntent(Intent intent) { - if ( this.newIntentListeners == null ) - return; + if (this.newIntentListeners == null) return; this.onResume(); - synchronized ( this.newIntentListeners ) { + synchronized (this.newIntentListeners) { Iterator iterator = this.newIntentListeners.iterator(); - while ( iterator.hasNext() ) { + while (iterator.hasNext()) { (iterator.next()).onNewIntent(intent); } } } - //---------------------------------------------------------------------------- + // ---------------------------------------------------------------------------- // Listener interface for onActivityResult // @@ -266,55 +265,43 @@ public interface ActivityResultListener { private List activityResultListeners = null; public void registerActivityResultListener(ActivityResultListener listener) { - if ( this.activityResultListeners == null ) - this.activityResultListeners = Collections.synchronizedList(new ArrayList()); + if (this.activityResultListeners == null) + this.activityResultListeners = + Collections.synchronizedList(new ArrayList()); this.activityResultListeners.add(listener); } public void unregisterActivityResultListener(ActivityResultListener listener) { - if ( this.activityResultListeners == null ) - return; + if (this.activityResultListeners == null) return; this.activityResultListeners.remove(listener); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { - if ( this.activityResultListeners == null ) - return; + if (this.activityResultListeners == null) return; this.onResume(); - synchronized ( this.activityResultListeners ) { + synchronized (this.activityResultListeners) { Iterator iterator = this.activityResultListeners.iterator(); - while ( iterator.hasNext() ) + while (iterator.hasNext()) (iterator.next()).onActivityResult(requestCode, resultCode, intent); } } public static void start_service( - String serviceTitle, - String serviceDescription, - String pythonServiceArgument - ) { - _do_start_service( - serviceTitle, serviceDescription, pythonServiceArgument, true - ); + String serviceTitle, String serviceDescription, String pythonServiceArgument) { + _do_start_service(serviceTitle, serviceDescription, pythonServiceArgument, true); } public static void start_service_not_as_foreground( - String serviceTitle, - String serviceDescription, - String pythonServiceArgument - ) { - _do_start_service( - serviceTitle, serviceDescription, pythonServiceArgument, false - ); + String serviceTitle, String serviceDescription, String pythonServiceArgument) { + _do_start_service(serviceTitle, serviceDescription, pythonServiceArgument, false); } public static void _do_start_service( String serviceTitle, String serviceDescription, String pythonServiceArgument, - boolean showForegroundNotification - ) { + boolean showForegroundNotification) { Intent serviceIntent = new Intent(PythonActivity.mActivity, PythonService.class); String argument = PythonActivity.mActivity.getFilesDir().getAbsolutePath(); String app_root_dir = PythonActivity.mActivity.getAppRoot(); @@ -325,9 +312,8 @@ public static void _do_start_service( 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( + "serviceStartAsForeground", (showForegroundNotification ? "true" : "false")); serviceIntent.putExtra("serviceTitle", serviceTitle); serviceIntent.putExtra("serviceDescription", serviceDescription); serviceIntent.putExtra("pythonServiceArgument", pythonServiceArgument); @@ -339,13 +325,16 @@ public static void stop_service() { PythonActivity.mActivity.stopService(serviceIntent); } - /** Loading screen view **/ + /** Loading screen view * */ public static ImageView mImageView = null; + public static View mLottieView = null; - /** Whether main routine/actual app has started yet **/ + + /** Whether main routine/actual app has started yet * */ protected boolean mAppConfirmedActive = false; - /** Timer for delayed loading screen removal. **/ - protected Timer loadingScreenRemovalTimer = null; + + /** Timer for delayed loading screen removal. * */ + protected Timer loadingScreenRemovalTimer = null; // Overridden since it's called often, to check whether to remove the // loading screen: @@ -355,9 +344,8 @@ protected boolean sendCommand(int command, Object data) { considerLoadingScreenRemoval(); return result; } - - /** Confirm that the app's main routine has been launched. - **/ + + /** Confirm that the app's main routine has been launched. */ @Override public void appConfirmedActive() { if (!mAppConfirmedActive) { @@ -367,64 +355,69 @@ public void appConfirmedActive() { } } - /** This is called from various places to check whether the app's main - * routine has been launched already, and if it has, then the loading - * screen will be removed. - **/ + /** + * This is called from various places to check whether the app's main routine has been launched + * already, and if it has, then the loading screen will be removed. + */ public void considerLoadingScreenRemoval() { - if (loadingScreenRemovalTimer != null) - return; - runOnUiThread(new Runnable() { - public void run() { - if (((PythonActivity)PythonActivity.mSingleton).mAppConfirmedActive && - loadingScreenRemovalTimer == null) { - // Remove loading screen but with a delay. - // (app can use p4a's android.loadingscreen module to - // do it quicker if it wants to) - // get a handler (call from main thread) - // this will run when timer elapses - TimerTask removalTask = new TimerTask() { - @Override - public void run() { - // post a runnable to the handler - runOnUiThread(new Runnable() { - @Override - public void run() { - PythonActivity activity = - ((PythonActivity)PythonActivity.mSingleton); - if (activity != null) - activity.removeLoadingScreen(); - } - }); + if (loadingScreenRemovalTimer != null) return; + runOnUiThread( + new Runnable() { + public void run() { + if (((PythonActivity) PythonActivity.mSingleton).mAppConfirmedActive + && loadingScreenRemovalTimer == null) { + // Remove loading screen but with a delay. + // (app can use p4a's android.loadingscreen module to + // do it quicker if it wants to) + // get a handler (call from main thread) + // this will run when timer elapses + TimerTask removalTask = + new TimerTask() { + @Override + public void run() { + // post a runnable to the handler + runOnUiThread( + new Runnable() { + @Override + public void run() { + PythonActivity activity = + ((PythonActivity) + PythonActivity + .mSingleton); + if (activity != null) + activity.removeLoadingScreen(); + } + }); + } + }; + loadingScreenRemovalTimer = new Timer(); + loadingScreenRemovalTimer.schedule(removalTask, 5000); } - }; - loadingScreenRemovalTimer = new Timer(); - loadingScreenRemovalTimer.schedule(removalTask, 5000); - } - } - }); + } + }); } public void removeLoadingScreen() { - runOnUiThread(new Runnable() { - public void run() { - View view = mLottieView != null ? mLottieView : mImageView; - if (view != null && view.getParent() != null) { - ((ViewGroup)view.getParent()).removeView(view); - mLottieView = null; - mImageView = null; - } - } - }); + runOnUiThread( + new Runnable() { + public void run() { + View view = mLottieView != null ? mLottieView : mImageView; + if (view != null && view.getParent() != null) { + ((ViewGroup) view.getParent()).removeView(view); + mLottieView = null; + mImageView = null; + } + } + }); } public String getEntryPoint(String search_dir) { /* Get the main file (.pyc|.py) depending on if we * have a compiled version or not. - */ + */ List entryPoints = new ArrayList(); - entryPoints.add("main.pyc"); // python 3 compiled files - for (String value : entryPoints) { + entryPoints.add("main.pyc"); // python 3 compiled files + for (String value : entryPoints) { File mainFile = new File(search_dir + "/" + value); if (mainFile.exists()) { return value; @@ -463,7 +456,8 @@ protected void setBackgroundColor(View view) { if (backgroundColor != null) { try { view.setBackgroundColor(Color.parseColor(backgroundColor)); - } catch (IllegalArgumentException e) {} + } catch (IllegalArgumentException e) { + } } } @@ -478,11 +472,12 @@ protected View getLoadingScreen() { // first try to load the lottie one try { - mLottieView = getLayoutInflater().inflate( - this.resourceManager.getIdentifier("lottie", "layout"), - mLayout, - false - ); + mLottieView = + getLayoutInflater() + .inflate( + this.resourceManager.getIdentifier("lottie", "layout"), + mLayout, + false); try { if (mLayout == null) { setContentView(mLottieView); @@ -497,8 +492,7 @@ protected View getLoadingScreen() { } setBackgroundColor(mLottieView); return mLottieView; - } - catch (NotFoundException e) { + } catch (NotFoundException e) { Log.v("SDL", "couldn't find lottie layout or animation, trying static splash"); } @@ -511,16 +505,18 @@ protected View getLoadingScreen() { } finally { try { is.close(); - } catch (IOException e) {}; + } catch (IOException e) { + } + ; } mImageView = new ImageView(this); mImageView.setImageBitmap(bitmap); setBackgroundColor(mImageView); - mImageView.setLayoutParams(new ViewGroup.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, - ViewGroup.LayoutParams.FILL_PARENT)); + mImageView.setLayoutParams( + new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); mImageView.setScaleType(ImageView.ScaleType.FIT_CENTER); return mImageView; } @@ -567,9 +563,9 @@ public void onWindowFocusChanged(boolean hasFocus) { } /** - * Used by android.permissions p4a module to register a call back after - * requesting runtime permissions - **/ + * Used by android.permissions p4a module to register a call back after requesting runtime + * permissions + */ public interface PermissionsCallback { void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults); } @@ -584,7 +580,8 @@ public void addPermissionsCallback(PermissionsCallback callback) { } @Override - public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + public void onRequestPermissionsResult( + int requestCode, String[] permissions, int[] grantResults) { Log.v(TAG, "onRequestPermissionsResult()"); if (havePermissionsCallback) { Log.v(TAG, "onRequestPermissionsResult passed to callback"); @@ -593,39 +590,29 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in super.onRequestPermissionsResult(requestCode, permissions, grantResults); } - /** - * Used by android.permissions p4a module to check a permission - **/ + /** Used by android.permissions p4a module to check a permission */ public boolean checkCurrentPermission(String permission) { - if (android.os.Build.VERSION.SDK_INT < 23) - return true; + if (android.os.Build.VERSION.SDK_INT < 23) return true; try { java.lang.reflect.Method methodCheckPermission = - Activity.class.getMethod("checkSelfPermission", String.class); + Activity.class.getMethod("checkSelfPermission", String.class); Object resultObj = methodCheckPermission.invoke(this, permission); int result = Integer.parseInt(resultObj.toString()); - if (result == PackageManager.PERMISSION_GRANTED) - return true; - } catch (IllegalAccessException | NoSuchMethodException | - InvocationTargetException e) { + if (result == PackageManager.PERMISSION_GRANTED) return true; + } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { } return false; } - /** - * Used by android.permissions p4a module to request runtime permissions - **/ + /** Used by android.permissions p4a module to request runtime permissions */ public void requestPermissionsWithRequestCode(String[] permissions, int requestCode) { - if (android.os.Build.VERSION.SDK_INT < 23) - return; + if (android.os.Build.VERSION.SDK_INT < 23) return; try { java.lang.reflect.Method methodRequestPermission = - Activity.class.getMethod("requestPermissions", - String[].class, int.class); + Activity.class.getMethod("requestPermissions", String[].class, int.class); methodRequestPermission.invoke(this, permissions, requestCode); - } catch (IllegalAccessException | NoSuchMethodException | - InvocationTargetException e) { + } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { } } @@ -634,10 +621,12 @@ public void requestPermissions(String[] permissions) { } public static void changeKeyboard(int inputType) { - if (SDLActivity.keyboardInputType != inputType){ - SDLActivity.keyboardInputType = inputType; - InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - imm.restartInput(mTextEdit); - } + if (SDLActivity.keyboardInputType != inputType) { + SDLActivity.keyboardInputType = inputType; + InputMethodManager imm = + (InputMethodManager) + getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.restartInput(mTextEdit); + } } } 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 0a9c884cc4..8feed58ee4 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 @@ -1,22 +1,11 @@ package org.kivy.android; -import java.io.InputStream; -import java.io.FileWriter; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Timer; -import java.util.TimerTask; - import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; +import android.content.res.Resources.NotFoundException; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; @@ -25,21 +14,26 @@ import android.os.Bundle; import android.os.PowerManager; import android.util.Log; -import android.view.inputmethod.InputMethodManager; import android.view.SurfaceView; -import android.view.ViewGroup; import android.view.View; +import android.view.ViewGroup; import android.widget.ImageView; import android.widget.Toast; -import android.content.res.Resources.NotFoundException; - -import org.libsdl.app.SDLActivity; - +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; import org.kivy.android.launcher.Project; - +import org.libsdl.app.SDLActivity; import org.renpy.android.ResourceManager; - public class PythonActivity extends SDLActivity { private static final String TAG = "PythonActivity"; @@ -50,7 +44,7 @@ public class PythonActivity extends SDLActivity { private PowerManager.WakeLock mWakeLock = null; public String getAppRoot() { - String app_root = getFilesDir().getAbsolutePath() + "/app"; + String app_root = getFilesDir().getAbsolutePath() + "/app"; return app_root; } @@ -72,23 +66,20 @@ protected void onCreate(Bundle savedInstanceState) { public void loadLibraries() { String app_root = new String(getAppRoot()); File app_root_file = new File(app_root); - PythonUtil.loadLibraries(app_root_file, - new File(getApplicationInfo().nativeLibraryDir)); + PythonUtil.loadLibraries(app_root_file, new File(getApplicationInfo().nativeLibraryDir)); } - /** - * Show an error using a toast. (Only makes sense from non-UI - * threads.) - */ + /** Show an error using a toast. (Only makes sense from non-UI threads.) */ public void toastError(final String msg) { final Activity thisActivity = this; - runOnUiThread(new Runnable () { - public void run() { - Toast.makeText(thisActivity, msg, Toast.LENGTH_LONG).show(); - } - }); + runOnUiThread( + new Runnable() { + public void run() { + Toast.makeText(thisActivity, msg, Toast.LENGTH_LONG).show(); + } + }); // Wait to show the error. synchronized (this) { @@ -105,7 +96,11 @@ protected String doInBackground(String... params) { File app_root_file = new File(params[0]); Log.v(TAG, "Ready to unpack"); PythonUtil.unpackAsset(mActivity, "private", app_root_file, true); - PythonUtil.unpackPyBundle(mActivity, getApplicationInfo().nativeLibraryDir + "/" + "libpybundle", app_root_file, false); + PythonUtil.unpackPyBundle( + mActivity, + getApplicationInfo().nativeLibraryDir + "/" + "libpybundle", + app_root_file, + false); return null; } @@ -127,8 +122,9 @@ protected void onPostExecute(String result) { mActivity.showLoadingScreen(getLoadingScreen()); String app_root_dir = getAppRoot(); - if (getIntent() != null && getIntent().getAction() != null && - getIntent().getAction().equals("org.kivy.LAUNCH")) { + if (getIntent() != null + && getIntent().getAction() != null + && getIntent().getAction().equals("org.kivy.LAUNCH")) { File path = new File(getIntent().getData().getSchemeSpecificPart()); Project p = Project.scanDirectory(path); @@ -170,15 +166,20 @@ protected void onPostExecute(String result) { try { Log.v(TAG, "Access to our meta-data..."); - mActivity.mMetaData = mActivity.getPackageManager().getApplicationInfo( - mActivity.getPackageName(), PackageManager.GET_META_DATA).metaData; + mActivity.mMetaData = + mActivity + .getPackageManager() + .getApplicationInfo( + mActivity.getPackageName(), PackageManager.GET_META_DATA) + .metaData; PowerManager pm = (PowerManager) mActivity.getSystemService(Context.POWER_SERVICE); - if ( mActivity.mMetaData.getInt("wakelock") == 1 ) { - mActivity.mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "Screen On"); + if (mActivity.mMetaData.getInt("wakelock") == 1) { + mActivity.mWakeLock = + pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "Screen On"); mActivity.mWakeLock.acquire(); } - if ( mActivity.mMetaData.getInt("surface.transparent") != 0 ) { + if (mActivity.mMetaData.getInt("surface.transparent") != 0) { Log.v(TAG, "Surface will be transparent."); getSurface().setZOrderOnTop(true); getSurface().getHolder().setFormat(PixelFormat.TRANSPARENT); @@ -189,14 +190,14 @@ protected void onPostExecute(String result) { } // Launch app if that hasn't been done yet: - if (mActivity.mHasFocus && ( + if (mActivity.mHasFocus + && ( // never went into proper resume state: - mActivity.mCurrentNativeState == NativeState.INIT || - ( - // resumed earlier but wasn't ready yet - mActivity.mCurrentNativeState == NativeState.RESUMED && - mActivity.mSDLThread == null - ))) { + mActivity.mCurrentNativeState == NativeState.INIT + || ( + // resumed earlier but wasn't ready yet + mActivity.mCurrentNativeState == NativeState.RESUMED + && mActivity.mSDLThread == null))) { // Because sometimes the app will get stuck here and never // actually run, ensure that it gets launched if we're active: mActivity.resumeNativeThread(); @@ -204,23 +205,21 @@ protected void onPostExecute(String result) { } @Override - protected void onPreExecute() { - } + protected void onPreExecute() {} @Override - protected void onProgressUpdate(Void... values) { - } + protected void onProgressUpdate(Void... values) {} } public static ViewGroup getLayout() { - return mLayout; + return mLayout; } public static SurfaceView getSurface() { - return mSurface; + return mSurface; } - //---------------------------------------------------------------------------- + // ---------------------------------------------------------------------------- // Listener interface for onNewIntent // @@ -231,31 +230,30 @@ public interface NewIntentListener { private List newIntentListeners = null; public void registerNewIntentListener(NewIntentListener listener) { - if ( this.newIntentListeners == null ) - this.newIntentListeners = Collections.synchronizedList(new ArrayList()); + if (this.newIntentListeners == null) + this.newIntentListeners = + Collections.synchronizedList(new ArrayList()); this.newIntentListeners.add(listener); } public void unregisterNewIntentListener(NewIntentListener listener) { - if ( this.newIntentListeners == null ) - return; + if (this.newIntentListeners == null) return; this.newIntentListeners.remove(listener); } @Override protected void onNewIntent(Intent intent) { - if ( this.newIntentListeners == null ) - return; + if (this.newIntentListeners == null) return; this.onResume(); - synchronized ( this.newIntentListeners ) { + synchronized (this.newIntentListeners) { Iterator iterator = this.newIntentListeners.iterator(); - while ( iterator.hasNext() ) { + while (iterator.hasNext()) { (iterator.next()).onNewIntent(intent); } } } - //---------------------------------------------------------------------------- + // ---------------------------------------------------------------------------- // Listener interface for onActivityResult // @@ -266,55 +264,43 @@ public interface ActivityResultListener { private List activityResultListeners = null; public void registerActivityResultListener(ActivityResultListener listener) { - if ( this.activityResultListeners == null ) - this.activityResultListeners = Collections.synchronizedList(new ArrayList()); + if (this.activityResultListeners == null) + this.activityResultListeners = + Collections.synchronizedList(new ArrayList()); this.activityResultListeners.add(listener); } public void unregisterActivityResultListener(ActivityResultListener listener) { - if ( this.activityResultListeners == null ) - return; + if (this.activityResultListeners == null) return; this.activityResultListeners.remove(listener); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { - if ( this.activityResultListeners == null ) - return; + if (this.activityResultListeners == null) return; this.onResume(); - synchronized ( this.activityResultListeners ) { + synchronized (this.activityResultListeners) { Iterator iterator = this.activityResultListeners.iterator(); - while ( iterator.hasNext() ) + while (iterator.hasNext()) (iterator.next()).onActivityResult(requestCode, resultCode, intent); } } public static void start_service( - String serviceTitle, - String serviceDescription, - String pythonServiceArgument - ) { - _do_start_service( - serviceTitle, serviceDescription, pythonServiceArgument, true - ); + String serviceTitle, String serviceDescription, String pythonServiceArgument) { + _do_start_service(serviceTitle, serviceDescription, pythonServiceArgument, true); } public static void start_service_not_as_foreground( - String serviceTitle, - String serviceDescription, - String pythonServiceArgument - ) { - _do_start_service( - serviceTitle, serviceDescription, pythonServiceArgument, false - ); + String serviceTitle, String serviceDescription, String pythonServiceArgument) { + _do_start_service(serviceTitle, serviceDescription, pythonServiceArgument, false); } public static void _do_start_service( String serviceTitle, String serviceDescription, String pythonServiceArgument, - boolean showForegroundNotification - ) { + boolean showForegroundNotification) { Intent serviceIntent = new Intent(PythonActivity.mActivity, PythonService.class); String argument = PythonActivity.mActivity.getFilesDir().getAbsolutePath(); String app_root_dir = PythonActivity.mActivity.getAppRoot(); @@ -325,9 +311,8 @@ public static void _do_start_service( 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( + "serviceStartAsForeground", (showForegroundNotification ? "true" : "false")); serviceIntent.putExtra("serviceTitle", serviceTitle); serviceIntent.putExtra("serviceDescription", serviceDescription); serviceIntent.putExtra("pythonServiceArgument", pythonServiceArgument); @@ -339,13 +324,16 @@ public static void stop_service() { PythonActivity.mActivity.stopService(serviceIntent); } - /** Loading screen view **/ + /** Loading screen view * */ public static ImageView mImageView = null; + public static View mLottieView = null; - /** Whether main routine/actual app has started yet **/ + + /** Whether main routine/actual app has started yet * */ protected boolean mAppConfirmedActive = false; - /** Timer for delayed loading screen removal. **/ - protected Timer loadingScreenRemovalTimer = null; + + /** Timer for delayed loading screen removal. * */ + protected Timer loadingScreenRemovalTimer = null; // Overridden since it's called often, to check whether to remove the // loading screen: @@ -355,9 +343,8 @@ protected boolean sendCommand(int command, Object data) { considerLoadingScreenRemoval(); return result; } - - /** Confirm that the app's main routine has been launched. - **/ + + /** Confirm that the app's main routine has been launched. */ @Override public void appConfirmedActive() { if (!mAppConfirmedActive) { @@ -367,64 +354,69 @@ public void appConfirmedActive() { } } - /** This is called from various places to check whether the app's main - * routine has been launched already, and if it has, then the loading - * screen will be removed. - **/ + /** + * This is called from various places to check whether the app's main routine has been launched + * already, and if it has, then the loading screen will be removed. + */ public void considerLoadingScreenRemoval() { - if (loadingScreenRemovalTimer != null) - return; - runOnUiThread(new Runnable() { - public void run() { - if (((PythonActivity)PythonActivity.mSingleton).mAppConfirmedActive && - loadingScreenRemovalTimer == null) { - // Remove loading screen but with a delay. - // (app can use p4a's android.loadingscreen module to - // do it quicker if it wants to) - // get a handler (call from main thread) - // this will run when timer elapses - TimerTask removalTask = new TimerTask() { - @Override - public void run() { - // post a runnable to the handler - runOnUiThread(new Runnable() { - @Override - public void run() { - PythonActivity activity = - ((PythonActivity)PythonActivity.mSingleton); - if (activity != null) - activity.removeLoadingScreen(); - } - }); + if (loadingScreenRemovalTimer != null) return; + runOnUiThread( + new Runnable() { + public void run() { + if (((PythonActivity) PythonActivity.mSingleton).mAppConfirmedActive + && loadingScreenRemovalTimer == null) { + // Remove loading screen but with a delay. + // (app can use p4a's android.loadingscreen module to + // do it quicker if it wants to) + // get a handler (call from main thread) + // this will run when timer elapses + TimerTask removalTask = + new TimerTask() { + @Override + public void run() { + // post a runnable to the handler + runOnUiThread( + new Runnable() { + @Override + public void run() { + PythonActivity activity = + ((PythonActivity) + PythonActivity + .mSingleton); + if (activity != null) + activity.removeLoadingScreen(); + } + }); + } + }; + loadingScreenRemovalTimer = new Timer(); + loadingScreenRemovalTimer.schedule(removalTask, 5000); } - }; - loadingScreenRemovalTimer = new Timer(); - loadingScreenRemovalTimer.schedule(removalTask, 5000); - } - } - }); + } + }); } public void removeLoadingScreen() { - runOnUiThread(new Runnable() { - public void run() { - View view = mLottieView != null ? mLottieView : mImageView; - if (view != null && view.getParent() != null) { - ((ViewGroup)view.getParent()).removeView(view); - mLottieView = null; - mImageView = null; - } - } - }); + runOnUiThread( + new Runnable() { + public void run() { + View view = mLottieView != null ? mLottieView : mImageView; + if (view != null && view.getParent() != null) { + ((ViewGroup) view.getParent()).removeView(view); + mLottieView = null; + mImageView = null; + } + } + }); } public String getEntryPoint(String search_dir) { /* Get the main file (.pyc|.py) depending on if we * have a compiled version or not. - */ + */ List entryPoints = new ArrayList(); - entryPoints.add("main.pyc"); // python 3 compiled files - for (String value : entryPoints) { + entryPoints.add("main.pyc"); // python 3 compiled files + for (String value : entryPoints) { File mainFile = new File(search_dir + "/" + value); if (mainFile.exists()) { return value; @@ -463,7 +455,8 @@ protected void setBackgroundColor(View view) { if (backgroundColor != null) { try { view.setBackgroundColor(Color.parseColor(backgroundColor)); - } catch (IllegalArgumentException e) {} + } catch (IllegalArgumentException e) { + } } } @@ -478,11 +471,12 @@ protected View getLoadingScreen() { // first try to load the lottie one try { - mLottieView = getLayoutInflater().inflate( - this.resourceManager.getIdentifier("lottie", "layout"), - mLayout, - false - ); + mLottieView = + getLayoutInflater() + .inflate( + this.resourceManager.getIdentifier("lottie", "layout"), + mLayout, + false); try { if (mLayout == null) { setContentView(mLottieView); @@ -497,8 +491,7 @@ protected View getLoadingScreen() { } setBackgroundColor(mLottieView); return mLottieView; - } - catch (NotFoundException e) { + } catch (NotFoundException e) { Log.v("SDL", "couldn't find lottie layout or animation, trying static splash"); } @@ -511,16 +504,18 @@ protected View getLoadingScreen() { } finally { try { is.close(); - } catch (IOException e) {}; + } catch (IOException e) { + } + ; } mImageView = new ImageView(this); mImageView.setImageBitmap(bitmap); setBackgroundColor(mImageView); - mImageView.setLayoutParams(new ViewGroup.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, - ViewGroup.LayoutParams.FILL_PARENT)); + mImageView.setLayoutParams( + new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); mImageView.setScaleType(ImageView.ScaleType.FIT_CENTER); return mImageView; } @@ -567,9 +562,9 @@ public void onWindowFocusChanged(boolean hasFocus) { } /** - * Used by android.permissions p4a module to register a call back after - * requesting runtime permissions - **/ + * Used by android.permissions p4a module to register a call back after requesting runtime + * permissions + */ public interface PermissionsCallback { void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults); } @@ -584,7 +579,8 @@ public void addPermissionsCallback(PermissionsCallback callback) { } @Override - public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + public void onRequestPermissionsResult( + int requestCode, String[] permissions, int[] grantResults) { Log.v(TAG, "onRequestPermissionsResult()"); if (havePermissionsCallback) { Log.v(TAG, "onRequestPermissionsResult passed to callback"); @@ -593,39 +589,29 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in super.onRequestPermissionsResult(requestCode, permissions, grantResults); } - /** - * Used by android.permissions p4a module to check a permission - **/ + /** Used by android.permissions p4a module to check a permission */ public boolean checkCurrentPermission(String permission) { - if (android.os.Build.VERSION.SDK_INT < 23) - return true; + if (android.os.Build.VERSION.SDK_INT < 23) return true; try { java.lang.reflect.Method methodCheckPermission = - Activity.class.getMethod("checkSelfPermission", String.class); + Activity.class.getMethod("checkSelfPermission", String.class); Object resultObj = methodCheckPermission.invoke(this, permission); int result = Integer.parseInt(resultObj.toString()); - if (result == PackageManager.PERMISSION_GRANTED) - return true; - } catch (IllegalAccessException | NoSuchMethodException | - InvocationTargetException e) { + if (result == PackageManager.PERMISSION_GRANTED) return true; + } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { } return false; } - /** - * Used by android.permissions p4a module to request runtime permissions - **/ + /** Used by android.permissions p4a module to request runtime permissions */ public void requestPermissionsWithRequestCode(String[] permissions, int requestCode) { - if (android.os.Build.VERSION.SDK_INT < 23) - return; + if (android.os.Build.VERSION.SDK_INT < 23) return; try { java.lang.reflect.Method methodRequestPermission = - Activity.class.getMethod("requestPermissions", - String[].class, int.class); + Activity.class.getMethod("requestPermissions", String[].class, int.class); methodRequestPermission.invoke(this, permissions, requestCode); - } catch (IllegalAccessException | NoSuchMethodException | - InvocationTargetException e) { + } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { } } @@ -634,12 +620,12 @@ public void requestPermissions(String[] permissions) { } public static void changeKeyboard(int inputType) { - /* - if (SDLActivity.keyboardInputType != inputType){ - SDLActivity.keyboardInputType = inputType; - InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - imm.restartInput(mTextEdit); - } - */ + /* + if (SDLActivity.keyboardInputType != inputType){ + SDLActivity.keyboardInputType = inputType; + InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.restartInput(mTextEdit); + } + */ } } diff --git a/pythonforandroid/bootstraps/service_library/build/src/main/java/org/kivy/android/PythonActivity.java b/pythonforandroid/bootstraps/service_library/build/src/main/java/org/kivy/android/PythonActivity.java index 7be751da56..3930867ee0 100644 --- a/pythonforandroid/bootstraps/service_library/build/src/main/java/org/kivy/android/PythonActivity.java +++ b/pythonforandroid/bootstraps/service_library/build/src/main/java/org/kivy/android/PythonActivity.java @@ -6,4 +6,3 @@ public class PythonActivity extends Activity { public static PythonActivity mActivity = null; } - 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 57112dd555..5d532de29a 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 @@ -1,25 +1,22 @@ package org.kivy.android; -import android.os.SystemClock; - -import java.io.File; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.ArrayList; - import android.app.Activity; import android.app.AlertDialog; +import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.view.KeyEvent; -import android.util.Log; -import android.widget.Toast; +import android.content.pm.PackageManager; import android.os.Bundle; import android.os.PowerManager; -import android.content.Context; -import android.content.pm.PackageManager; - +import android.os.SystemClock; +import android.util.Log; +import android.view.KeyEvent; +import android.widget.Toast; +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; import org.renpy.android.ResourceManager; public class PythonActivity extends Activity { @@ -41,17 +38,17 @@ public class PythonActivity extends Activity { private PowerManager.WakeLock mWakeLock = null; public String getAppRoot() { - String app_root = getFilesDir().getAbsolutePath() + "/app"; + String app_root = getFilesDir().getAbsolutePath() + "/app"; return app_root; } public String getEntryPoint(String search_dir) { /* Get the main file (.pyc|.py) depending on if we * have a compiled version or not. - */ + */ List entryPoints = new ArrayList(); - entryPoints.add("main.pyc"); // python 3 compiled files - for (String value : entryPoints) { + entryPoints.add("main.pyc"); // python 3 compiled files + for (String value : entryPoints) { File mainFile = new File(search_dir + "/" + value); if (mainFile.exists()) { return value; @@ -61,8 +58,10 @@ public String getEntryPoint(String search_dir) { } public static void initialize() { - // The static nature of the singleton and Android quirkiness force us to initialize everything here - // Otherwise, when exiting the app and returning to it, these variables *keep* their pre exit values + // The static nature of the singleton and Android quirkiness force us to initialize + // everything here + // Otherwise, when exiting the app and returning to it, these variables *keep* their pre + // exit values mBrokenLibraries = false; } @@ -74,19 +73,23 @@ protected void onCreate(Bundle savedInstanceState) { Log.v(TAG, "Ready to unpack"); File app_root_file = new File(getAppRoot()); PythonUtil.unpackAsset(mActivity, "private", app_root_file, true); - PythonUtil.unpackPyBundle(mActivity, getApplicationInfo().nativeLibraryDir + "/" + "libpybundle", app_root_file, false); + PythonUtil.unpackPyBundle( + mActivity, + getApplicationInfo().nativeLibraryDir + "/" + "libpybundle", + app_root_file, + false); Log.v(TAG, "About to do super onCreate"); super.onCreate(savedInstanceState); Log.v(TAG, "Did super onCreate"); this.mActivity = this; - //this.showLoadingScreen(); + // this.showLoadingScreen(); Log.v("Python", "Device: " + android.os.Build.DEVICE); Log.v("Python", "Model: " + android.os.Build.MODEL); - //Log.v(TAG, "Ready to unpack"); - //new UnpackFilesTask().execute(getAppRoot()); + // Log.v(TAG, "Ready to unpack"); + // new UnpackFilesTask().execute(getAppRoot()); PythonActivity.initialize(); @@ -94,36 +97,38 @@ protected void onCreate(Bundle savedInstanceState) { String errorMsgBrokenLib = ""; try { loadLibraries(); - } catch(UnsatisfiedLinkError e) { + } catch (UnsatisfiedLinkError e) { System.err.println(e.getMessage()); mBrokenLibraries = true; errorMsgBrokenLib = e.getMessage(); - } catch(Exception e) { + } catch (Exception e) { System.err.println(e.getMessage()); mBrokenLibraries = true; errorMsgBrokenLib = e.getMessage(); } - if (mBrokenLibraries) - { - AlertDialog.Builder dlgAlert = new AlertDialog.Builder(this); - dlgAlert.setMessage("An error occurred while trying to load the application libraries. Please try again and/or reinstall." - + System.getProperty("line.separator") - + System.getProperty("line.separator") - + "Error: " + errorMsgBrokenLib); + if (mBrokenLibraries) { + AlertDialog.Builder dlgAlert = new AlertDialog.Builder(this); + dlgAlert.setMessage( + "An error occurred while trying to load the application libraries. Please try again and/or reinstall." + + System.getProperty("line.separator") + + System.getProperty("line.separator") + + "Error: " + + errorMsgBrokenLib); dlgAlert.setTitle("Python Error"); - dlgAlert.setPositiveButton("Exit", - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog,int id) { - // if this button is clicked, close current activity - PythonActivity.mActivity.finish(); - } - }); - dlgAlert.setCancelable(false); - dlgAlert.create().show(); - - return; + dlgAlert.setPositiveButton( + "Exit", + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + // if this button is clicked, close current activity + PythonActivity.mActivity.finish(); + } + }); + dlgAlert.setCancelable(false); + dlgAlert.create().show(); + + return; } // Set up the Python environment @@ -143,12 +148,17 @@ public void onClick(DialogInterface dialog,int id) { try { Log.v(TAG, "Access to our meta-data..."); - mActivity.mMetaData = mActivity.getPackageManager().getApplicationInfo( - mActivity.getPackageName(), PackageManager.GET_META_DATA).metaData; + mActivity.mMetaData = + mActivity + .getPackageManager() + .getApplicationInfo( + mActivity.getPackageName(), PackageManager.GET_META_DATA) + .metaData; PowerManager pm = (PowerManager) mActivity.getSystemService(Context.POWER_SERVICE); - if ( mActivity.mMetaData.getInt("wakelock") == 1 ) { - mActivity.mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "Screen On"); + if (mActivity.mMetaData.getInt("wakelock") == 1) { + mActivity.mWakeLock = + pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "Screen On"); mActivity.mWakeLock.acquire(); } } catch (PackageManager.NameNotFoundException e) { @@ -157,7 +167,6 @@ public void onClick(DialogInterface dialog,int id) { final Thread pythonThread = new Thread(new PythonMain(), "PythonThread"); PythonActivity.mPythonThread = pythonThread; pythonThread.start(); - } @Override @@ -172,18 +181,18 @@ public void onDestroy() { public void loadLibraries() { String app_root = new String(getAppRoot()); File app_root_file = new File(app_root); - PythonUtil.loadLibraries(app_root_file, - new File(getApplicationInfo().nativeLibraryDir)); + PythonUtil.loadLibraries(app_root_file, new File(getApplicationInfo().nativeLibraryDir)); } long lastBackClick = 0; + @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // Check if the key event was the Back button if (keyCode == KeyEvent.KEYCODE_BACK) { // If there's no web page history, bubble up to the default // system behavior (probably exit the activity) - if (SystemClock.elapsedRealtime() - lastBackClick > 2000){ + if (SystemClock.elapsedRealtime() - lastBackClick > 2000) { lastBackClick = SystemClock.elapsedRealtime(); Toast.makeText(this, "Tap again to close the app", Toast.LENGTH_LONG).show(); return true; @@ -195,8 +204,7 @@ public boolean onKeyDown(int keyCode, KeyEvent event) { return super.onKeyDown(keyCode, event); } - - //---------------------------------------------------------------------------- + // ---------------------------------------------------------------------------- // Listener interface for onNewIntent // @@ -207,31 +215,30 @@ public interface NewIntentListener { private List newIntentListeners = null; public void registerNewIntentListener(NewIntentListener listener) { - if ( this.newIntentListeners == null ) - this.newIntentListeners = Collections.synchronizedList(new ArrayList()); + if (this.newIntentListeners == null) + this.newIntentListeners = + Collections.synchronizedList(new ArrayList()); this.newIntentListeners.add(listener); } public void unregisterNewIntentListener(NewIntentListener listener) { - if ( this.newIntentListeners == null ) - return; + if (this.newIntentListeners == null) return; this.newIntentListeners.remove(listener); } @Override protected void onNewIntent(Intent intent) { - if ( this.newIntentListeners == null ) - return; + if (this.newIntentListeners == null) return; this.onResume(); - synchronized ( this.newIntentListeners ) { + synchronized (this.newIntentListeners) { Iterator iterator = this.newIntentListeners.iterator(); - while ( iterator.hasNext() ) { + while (iterator.hasNext()) { (iterator.next()).onNewIntent(intent); } } } - //---------------------------------------------------------------------------- + // ---------------------------------------------------------------------------- // Listener interface for onActivityResult // @@ -242,55 +249,43 @@ public interface ActivityResultListener { private List activityResultListeners = null; public void registerActivityResultListener(ActivityResultListener listener) { - if ( this.activityResultListeners == null ) - this.activityResultListeners = Collections.synchronizedList(new ArrayList()); + if (this.activityResultListeners == null) + this.activityResultListeners = + Collections.synchronizedList(new ArrayList()); this.activityResultListeners.add(listener); } public void unregisterActivityResultListener(ActivityResultListener listener) { - if ( this.activityResultListeners == null ) - return; + if (this.activityResultListeners == null) return; this.activityResultListeners.remove(listener); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { - if ( this.activityResultListeners == null ) - return; + if (this.activityResultListeners == null) return; this.onResume(); - synchronized ( this.activityResultListeners ) { + synchronized (this.activityResultListeners) { Iterator iterator = this.activityResultListeners.iterator(); - while ( iterator.hasNext() ) + while (iterator.hasNext()) (iterator.next()).onActivityResult(requestCode, resultCode, intent); } } public static void start_service( - String serviceTitle, - String serviceDescription, - String pythonServiceArgument - ) { - _do_start_service( - serviceTitle, serviceDescription, pythonServiceArgument, true - ); + String serviceTitle, String serviceDescription, String pythonServiceArgument) { + _do_start_service(serviceTitle, serviceDescription, pythonServiceArgument, true); } public static void start_service_not_as_foreground( - String serviceTitle, - String serviceDescription, - String pythonServiceArgument - ) { - _do_start_service( - serviceTitle, serviceDescription, pythonServiceArgument, false - ); + String serviceTitle, String serviceDescription, String pythonServiceArgument) { + _do_start_service(serviceTitle, serviceDescription, pythonServiceArgument, false); } public static void _do_start_service( String serviceTitle, String serviceDescription, String pythonServiceArgument, - boolean showForegroundNotification - ) { + boolean showForegroundNotification) { Intent serviceIntent = new Intent(PythonActivity.mActivity, PythonService.class); String argument = PythonActivity.mActivity.getFilesDir().getAbsolutePath(); String app_root_dir = PythonActivity.mActivity.getAppRoot(); @@ -301,9 +296,8 @@ public static void _do_start_service( 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( + "serviceStartAsForeground", (showForegroundNotification ? "true" : "false")); serviceIntent.putExtra("serviceTitle", serviceTitle); serviceIntent.putExtra("serviceDescription", serviceDescription); serviceIntent.putExtra("pythonServiceArgument", pythonServiceArgument); @@ -315,13 +309,11 @@ public static void stop_service() { PythonActivity.mActivity.stopService(serviceIntent); } - public static native void nativeSetenv(String name, String value); - public static native int nativeInit(Object arguments); + public static native int nativeInit(Object arguments); } - class PythonMain implements Runnable { @Override public void run() { diff --git a/pythonforandroid/bootstraps/settings.gradle b/pythonforandroid/bootstraps/settings.gradle new file mode 100644 index 0000000000..0b26195231 --- /dev/null +++ b/pythonforandroid/bootstraps/settings.gradle @@ -0,0 +1,3 @@ +// Java Lint Project Settings +// This project is used for linting Java source files in CI +rootProject.name = 'p4a-java-lint' 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 2f0afdc6f4..9ad9503a6f 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 @@ -1,43 +1,38 @@ package org.kivy.android; -import android.os.SystemClock; - -import java.io.InputStream; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.ArrayList; - -import android.view.ViewGroup; -import android.view.KeyEvent; import android.app.Activity; import android.app.AlertDialog; +import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.util.Log; -import android.widget.Toast; -import android.os.AsyncTask; -import android.os.Bundle; -import android.os.PowerManager; -import android.content.Context; import android.content.pm.PackageManager; -import android.widget.ImageView; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; - -import android.widget.AbsoluteLayout; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.PowerManager; +import android.os.SystemClock; +import android.util.Log; +import android.view.KeyEvent; +import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; - +import android.webkit.CookieManager; import android.webkit.WebBackForwardList; -import android.webkit.WebViewClient; import android.webkit.WebView; -import android.webkit.CookieManager; -import android.net.Uri; - +import android.webkit.WebViewClient; +import android.widget.AbsoluteLayout; +import android.widget.ImageView; +import android.widget.Toast; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; import org.renpy.android.ResourceManager; public class PythonActivity extends Activity { @@ -63,16 +58,16 @@ public class PythonActivity extends Activity { private PowerManager.WakeLock mWakeLock = null; public String getAppRoot() { - String app_root = getFilesDir().getAbsolutePath() + "/app"; + String app_root = getFilesDir().getAbsolutePath() + "/app"; return app_root; } public String getEntryPoint(String search_dir) { /* Get the main file (.pyc|.py) depending on if we * have a compiled version or not. - */ + */ List entryPoints = new ArrayList(); - entryPoints.add("main.pyc"); // python 3 compiled files + entryPoints.add("main.pyc"); // python 3 compiled files for (String value : entryPoints) { File mainFile = new File(search_dir + "/" + value); if (mainFile.exists()) { @@ -83,8 +78,10 @@ public String getEntryPoint(String search_dir) { } public static void initialize() { - // The static nature of the singleton and Android quirkyness force us to initialize everything here - // Otherwise, when exiting the app and returning to it, these variables *keep* their pre exit values + // The static nature of the singleton and Android quirkyness force us to initialize + // everything here + // Otherwise, when exiting the app and returning to it, these variables *keep* their pre + // exit values mWebView = null; mLayout = null; mBrokenLibraries = false; @@ -107,7 +104,11 @@ protected String doInBackground(String... params) { File app_root_file = new File(params[0]); Log.v(TAG, "Ready to unpack"); PythonUtil.unpackAsset(mActivity, "private", app_root_file, true); - PythonUtil.unpackPyBundle(mActivity, getApplicationInfo().nativeLibraryDir + "/" + "libpybundle", app_root_file, false); + PythonUtil.unpackPyBundle( + mActivity, + getApplicationInfo().nativeLibraryDir + "/" + "libpybundle", + app_root_file, + false); return null; } @@ -122,36 +123,38 @@ protected void onPostExecute(String result) { String errorMsgBrokenLib = ""; try { loadLibraries(); - } catch(UnsatisfiedLinkError e) { + } catch (UnsatisfiedLinkError e) { System.err.println(e.getMessage()); mBrokenLibraries = true; errorMsgBrokenLib = e.getMessage(); - } catch(Exception e) { + } catch (Exception e) { System.err.println(e.getMessage()); mBrokenLibraries = true; errorMsgBrokenLib = e.getMessage(); } - if (mBrokenLibraries) - { - AlertDialog.Builder dlgAlert = new AlertDialog.Builder(PythonActivity.mActivity); - dlgAlert.setMessage("An error occurred while trying to load the application libraries. Please try again and/or reinstall." - + System.getProperty("line.separator") - + System.getProperty("line.separator") - + "Error: " + errorMsgBrokenLib); + if (mBrokenLibraries) { + AlertDialog.Builder dlgAlert = new AlertDialog.Builder(PythonActivity.mActivity); + dlgAlert.setMessage( + "An error occurred while trying to load the application libraries. Please try again and/or reinstall." + + System.getProperty("line.separator") + + System.getProperty("line.separator") + + "Error: " + + errorMsgBrokenLib); dlgAlert.setTitle("Python Error"); - dlgAlert.setPositiveButton("Exit", - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog,int id) { - // if this button is clicked, close current activity - PythonActivity.mActivity.finish(); - } - }); - dlgAlert.setCancelable(false); - dlgAlert.create().show(); + dlgAlert.setPositiveButton( + "Exit", + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + // if this button is clicked, close current activity + PythonActivity.mActivity.finish(); + } + }); + dlgAlert.setCancelable(false); + dlgAlert.create().show(); - return; + return; } // Set up the webview @@ -162,26 +165,29 @@ public void onClick(DialogInterface dialog,int id) { mWebView.getSettings().setDomStorageEnabled(true); mWebView.loadUrl("file:///android_asset/_load.html"); - mWebView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); - mWebView.setWebViewClient(new WebViewClient() { - @Override - public boolean shouldOverrideUrlLoading(WebView view, String url) { - Uri u = Uri.parse(url); - if (mOpenExternalLinksInBrowser) { - if (!(u.getScheme().equals("file") || u.getHost().equals("127.0.0.1"))) { - Intent i = new Intent(Intent.ACTION_VIEW, u); - startActivity(i); - return true; + mWebView.setLayoutParams( + new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + mWebView.setWebViewClient( + new WebViewClient() { + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + Uri u = Uri.parse(url); + if (mOpenExternalLinksInBrowser) { + if (!(u.getScheme().equals("file") + || u.getHost().equals("127.0.0.1"))) { + Intent i = new Intent(Intent.ACTION_VIEW, u); + startActivity(i); + return true; + } } + return false; } - return false; - } - @Override - public void onPageFinished(WebView view, String url) { - CookieManager.getInstance().flush(); - } - }); + @Override + public void onPageFinished(WebView view, String url) { + CookieManager.getInstance().flush(); + } + }); mLayout = new AbsoluteLayout(PythonActivity.mActivity); mLayout.addView(mWebView); @@ -202,12 +208,17 @@ public void onPageFinished(WebView view, String url) { try { Log.v(TAG, "Access to our meta-data..."); - mActivity.mMetaData = mActivity.getPackageManager().getApplicationInfo( - mActivity.getPackageName(), PackageManager.GET_META_DATA).metaData; + mActivity.mMetaData = + mActivity + .getPackageManager() + .getApplicationInfo( + mActivity.getPackageName(), PackageManager.GET_META_DATA) + .metaData; PowerManager pm = (PowerManager) mActivity.getSystemService(Context.POWER_SERVICE); - if ( mActivity.mMetaData.getInt("wakelock") == 1 ) { - mActivity.mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "Screen On"); + if (mActivity.mMetaData.getInt("wakelock") == 1) { + mActivity.mWakeLock = + pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "Screen On"); mActivity.mWakeLock.acquire(); } } catch (PackageManager.NameNotFoundException e) { @@ -234,8 +245,7 @@ public void onDestroy() { public void loadLibraries() { String app_root = new String(getAppRoot()); File app_root_file = new File(app_root); - PythonUtil.loadLibraries(app_root_file, - new File(getApplicationInfo().nativeLibraryDir)); + PythonUtil.loadLibraries(app_root_file, new File(getApplicationInfo().nativeLibraryDir)); } public static void loadUrl(String url) { @@ -256,20 +266,22 @@ public void run() { } public static void enableZoom() { - mActivity.runOnUiThread(new Runnable() { - @Override - public void run() { - mWebView.getSettings().setBuiltInZoomControls(true); - mWebView.getSettings().setDisplayZoomControls(false); - } - }); + mActivity.runOnUiThread( + new Runnable() { + @Override + public void run() { + mWebView.getSettings().setBuiltInZoomControls(true); + mWebView.getSettings().setDisplayZoomControls(false); + } + }); } public static ViewGroup getLayout() { - return mLayout; + return mLayout; } long lastBackClick = 0; + @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // Check if the key event was the Back button @@ -284,7 +296,7 @@ public boolean onKeyDown(int keyCode, KeyEvent event) { // If there's no web page history, bubble up to the default // system behavior (probably exit the activity) - if (SystemClock.elapsedRealtime() - lastBackClick > 2000){ + if (SystemClock.elapsedRealtime() - lastBackClick > 2000) { lastBackClick = SystemClock.elapsedRealtime(); Toast.makeText(this, "Tap again to close the app", Toast.LENGTH_LONG).show(); return true; @@ -298,73 +310,78 @@ public boolean onKeyDown(int keyCode, KeyEvent event) { // loading screen implementation public static ImageView mImageView = null; + public void removeLoadingScreen() { - runOnUiThread(new Runnable() { - public void run() { - if (PythonActivity.mImageView != null && - PythonActivity.mImageView.getParent() != null) { - ((ViewGroup)PythonActivity.mImageView.getParent()).removeView( - PythonActivity.mImageView); - PythonActivity.mImageView = null; - } - } - }); + runOnUiThread( + new Runnable() { + public void run() { + if (PythonActivity.mImageView != null + && PythonActivity.mImageView.getParent() != null) { + ((ViewGroup) PythonActivity.mImageView.getParent()) + .removeView(PythonActivity.mImageView); + PythonActivity.mImageView = null; + } + } + }); } protected void showLoadingScreen() { - // load the bitmap - // 1. if the image is valid and we don't have layout yet, assign this bitmap - // as main view. - // 2. if we have a layout, just set it in the layout. - // 3. If we have an mImageView already, then do nothing because it will have - // already been made the content view or added to the layout. - - if (mImageView == null) { - int presplashId = this.resourceManager.getIdentifier("presplash", "drawable"); - InputStream is = this.getResources().openRawResource(presplashId); - Bitmap bitmap = null; - try { - bitmap = BitmapFactory.decodeStream(is); - } finally { - try { - is.close(); - } catch (IOException e) {}; - } + // load the bitmap + // 1. if the image is valid and we don't have layout yet, assign this bitmap + // as main view. + // 2. if we have a layout, just set it in the layout. + // 3. If we have an mImageView already, then do nothing because it will have + // already been made the content view or added to the layout. + + if (mImageView == null) { + int presplashId = this.resourceManager.getIdentifier("presplash", "drawable"); + InputStream is = this.getResources().openRawResource(presplashId); + Bitmap bitmap = null; + try { + bitmap = BitmapFactory.decodeStream(is); + } finally { + try { + is.close(); + } catch (IOException e) { + } + ; + } - mImageView = new ImageView(this); - mImageView.setImageBitmap(bitmap); - - /* - * Set the presplash loading screen background color - * https://developer.android.com/reference/android/graphics/Color.html - * Parse the color string, and return the corresponding color-int. - * If the string cannot be parsed, throws an IllegalArgumentException exception. - * Supported formats are: #RRGGBB #AARRGGBB or one of the following names: - * 'red', 'blue', 'green', 'black', 'white', 'gray', 'cyan', 'magenta', 'yellow', - * 'lightgray', 'darkgray', 'grey', 'lightgrey', 'darkgrey', 'aqua', 'fuchsia', - * 'lime', 'maroon', 'navy', 'olive', 'purple', 'silver', 'teal'. - */ - String backgroundColor = resourceManager.getString("presplash_color"); - if (backgroundColor != null) { - try { - mImageView.setBackgroundColor(Color.parseColor(backgroundColor)); - } catch (IllegalArgumentException e) {} + mImageView = new ImageView(this); + mImageView.setImageBitmap(bitmap); + + /* + * Set the presplash loading screen background color + * https://developer.android.com/reference/android/graphics/Color.html + * Parse the color string, and return the corresponding color-int. + * If the string cannot be parsed, throws an IllegalArgumentException exception. + * Supported formats are: #RRGGBB #AARRGGBB or one of the following names: + * 'red', 'blue', 'green', 'black', 'white', 'gray', 'cyan', 'magenta', 'yellow', + * 'lightgray', 'darkgray', 'grey', 'lightgrey', 'darkgrey', 'aqua', 'fuchsia', + * 'lime', 'maroon', 'navy', 'olive', 'purple', 'silver', 'teal'. + */ + String backgroundColor = resourceManager.getString("presplash_color"); + if (backgroundColor != null) { + try { + mImageView.setBackgroundColor(Color.parseColor(backgroundColor)); + } catch (IllegalArgumentException e) { + } + } + mImageView.setLayoutParams( + new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.FILL_PARENT, + ViewGroup.LayoutParams.FILL_PARENT)); + mImageView.setScaleType(ImageView.ScaleType.FIT_CENTER); } - mImageView.setLayoutParams(new ViewGroup.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, - ViewGroup.LayoutParams.FILL_PARENT)); - mImageView.setScaleType(ImageView.ScaleType.FIT_CENTER); - - } - if (mLayout == null) { - setContentView(mImageView); - } else if (PythonActivity.mImageView.getParent() == null){ - mLayout.addView(mImageView); - } + if (mLayout == null) { + setContentView(mImageView); + } else if (PythonActivity.mImageView.getParent() == null) { + mLayout.addView(mImageView); + } } - //---------------------------------------------------------------------------- + // ---------------------------------------------------------------------------- // Listener interface for onNewIntent // @@ -375,31 +392,30 @@ public interface NewIntentListener { private List newIntentListeners = null; public void registerNewIntentListener(NewIntentListener listener) { - if ( this.newIntentListeners == null ) - this.newIntentListeners = Collections.synchronizedList(new ArrayList()); + if (this.newIntentListeners == null) + this.newIntentListeners = + Collections.synchronizedList(new ArrayList()); this.newIntentListeners.add(listener); } public void unregisterNewIntentListener(NewIntentListener listener) { - if ( this.newIntentListeners == null ) - return; + if (this.newIntentListeners == null) return; this.newIntentListeners.remove(listener); } @Override protected void onNewIntent(Intent intent) { - if ( this.newIntentListeners == null ) - return; + if (this.newIntentListeners == null) return; this.onResume(); - synchronized ( this.newIntentListeners ) { + synchronized (this.newIntentListeners) { Iterator iterator = this.newIntentListeners.iterator(); - while ( iterator.hasNext() ) { + while (iterator.hasNext()) { (iterator.next()).onNewIntent(intent); } } } - //---------------------------------------------------------------------------- + // ---------------------------------------------------------------------------- // Listener interface for onActivityResult // @@ -410,55 +426,43 @@ public interface ActivityResultListener { private List activityResultListeners = null; public void registerActivityResultListener(ActivityResultListener listener) { - if ( this.activityResultListeners == null ) - this.activityResultListeners = Collections.synchronizedList(new ArrayList()); + if (this.activityResultListeners == null) + this.activityResultListeners = + Collections.synchronizedList(new ArrayList()); this.activityResultListeners.add(listener); } public void unregisterActivityResultListener(ActivityResultListener listener) { - if ( this.activityResultListeners == null ) - return; + if (this.activityResultListeners == null) return; this.activityResultListeners.remove(listener); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { - if ( this.activityResultListeners == null ) - return; + if (this.activityResultListeners == null) return; this.onResume(); - synchronized ( this.activityResultListeners ) { + synchronized (this.activityResultListeners) { Iterator iterator = this.activityResultListeners.iterator(); - while ( iterator.hasNext() ) + while (iterator.hasNext()) (iterator.next()).onActivityResult(requestCode, resultCode, intent); } } public static void start_service( - String serviceTitle, - String serviceDescription, - String pythonServiceArgument - ) { - _do_start_service( - serviceTitle, serviceDescription, pythonServiceArgument, true - ); + String serviceTitle, String serviceDescription, String pythonServiceArgument) { + _do_start_service(serviceTitle, serviceDescription, pythonServiceArgument, true); } public static void start_service_not_as_foreground( - String serviceTitle, - String serviceDescription, - String pythonServiceArgument - ) { - _do_start_service( - serviceTitle, serviceDescription, pythonServiceArgument, false - ); + String serviceTitle, String serviceDescription, String pythonServiceArgument) { + _do_start_service(serviceTitle, serviceDescription, pythonServiceArgument, false); } public static void _do_start_service( String serviceTitle, String serviceDescription, String pythonServiceArgument, - boolean showForegroundNotification - ) { + boolean showForegroundNotification) { Intent serviceIntent = new Intent(PythonActivity.mActivity, PythonService.class); String argument = PythonActivity.mActivity.getFilesDir().getAbsolutePath(); String app_root_dir = PythonActivity.mActivity.getAppRoot(); @@ -469,9 +473,8 @@ public static void _do_start_service( 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( + "serviceStartAsForeground", (showForegroundNotification ? "true" : "false")); serviceIntent.putExtra("serviceTitle", serviceTitle); serviceIntent.putExtra("serviceDescription", serviceDescription); serviceIntent.putExtra("pythonServiceArgument", pythonServiceArgument); @@ -483,15 +486,14 @@ public static void stop_service() { PythonActivity.mActivity.stopService(serviceIntent); } - public static native void nativeSetenv(String name, String value); - public static native int nativeInit(Object arguments); + public static native int nativeInit(Object arguments); /** - * Used by android.permissions p4a module to register a call back after - * requesting runtime permissions - **/ + * Used by android.permissions p4a module to register a call back after requesting runtime + * permissions + */ public interface PermissionsCallback { void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults); } @@ -506,7 +508,8 @@ public void addPermissionsCallback(PermissionsCallback callback) { } @Override - public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + public void onRequestPermissionsResult( + int requestCode, String[] permissions, int[] grantResults) { Log.v(TAG, "onRequestPermissionsResult()"); if (havePermissionsCallback) { Log.v(TAG, "onRequestPermissionsResult passed to callback"); @@ -515,39 +518,29 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in super.onRequestPermissionsResult(requestCode, permissions, grantResults); } - /** - * Used by android.permissions p4a module to check a permission - **/ + /** Used by android.permissions p4a module to check a permission */ public boolean checkCurrentPermission(String permission) { - if (android.os.Build.VERSION.SDK_INT < 23) - return true; + if (android.os.Build.VERSION.SDK_INT < 23) return true; try { java.lang.reflect.Method methodCheckPermission = - Activity.class.getMethod("checkSelfPermission", String.class); + Activity.class.getMethod("checkSelfPermission", String.class); Object resultObj = methodCheckPermission.invoke(this, permission); int result = Integer.parseInt(resultObj.toString()); - if (result == PackageManager.PERMISSION_GRANTED) - return true; - } catch (IllegalAccessException | NoSuchMethodException | - InvocationTargetException e) { + if (result == PackageManager.PERMISSION_GRANTED) return true; + } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { } return false; } - /** - * Used by android.permissions p4a module to request runtime permissions - **/ + /** Used by android.permissions p4a module to request runtime permissions */ public void requestPermissionsWithRequestCode(String[] permissions, int requestCode) { - if (android.os.Build.VERSION.SDK_INT < 23) - return; + if (android.os.Build.VERSION.SDK_INT < 23) return; try { java.lang.reflect.Method methodRequestPermission = - Activity.class.getMethod("requestPermissions", - String[].class, int.class); + Activity.class.getMethod("requestPermissions", String[].class, int.class); methodRequestPermission.invoke(this, permissions, requestCode); - } catch (IllegalAccessException | NoSuchMethodException | - InvocationTargetException e) { + } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { } } @@ -556,7 +549,6 @@ public void requestPermissions(String[] permissions) { } } - class PythonMain implements Runnable { @Override public void run() {