kivyforge 3.0.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kivyforge/__init__.py +9 -0
- kivyforge/artifacts/__init__.py +41 -0
- kivyforge/artifacts/cache.py +81 -0
- kivyforge/artifacts/collect.py +354 -0
- kivyforge/artifacts/download.py +125 -0
- kivyforge/artifacts/frameworks.py +240 -0
- kivyforge/artifacts/native_stage_util.py +346 -0
- kivyforge/artifacts/runtime.py +65 -0
- kivyforge/artifacts/verify.py +45 -0
- kivyforge/artifacts/wheels.py +89 -0
- kivyforge/bundle/__init__.py +1 -0
- kivyforge/bundle/pycompile.py +161 -0
- kivyforge/cli/__init__.py +52 -0
- kivyforge/cli/_common.py +62 -0
- kivyforge/cli/_platform.py +84 -0
- kivyforge/cli/build.py +111 -0
- kivyforge/cli/clean.py +135 -0
- kivyforge/cli/doctor.py +52 -0
- kivyforge/cli/init.py +612 -0
- kivyforge/cli/init_writer.py +716 -0
- kivyforge/cli/lock.py +261 -0
- kivyforge/cli/open_cmd.py +15 -0
- kivyforge/cli/package.py +134 -0
- kivyforge/cli/run.py +162 -0
- kivyforge/cli/status.py +20 -0
- kivyforge/cli/upgrade.py +314 -0
- kivyforge/config/__init__.py +46 -0
- kivyforge/config/errors.py +43 -0
- kivyforge/config/icons.py +60 -0
- kivyforge/config/loader.py +3079 -0
- kivyforge/config/model.py +817 -0
- kivyforge/doctor/__init__.py +19 -0
- kivyforge/doctor/checks_common.py +95 -0
- kivyforge/doctor/probe.py +357 -0
- kivyforge/doctor/result.py +41 -0
- kivyforge/lock/__init__.py +42 -0
- kivyforge/lock/_pip_shim.py +63 -0
- kivyforge/lock/find_links.py +182 -0
- kivyforge/lock/model.py +69 -0
- kivyforge/lock/pep751.py +111 -0
- kivyforge/lock/reader.py +30 -0
- kivyforge/lock/resolver.py +124 -0
- kivyforge/lock/wheelruntime/__init__.py +70 -0
- kivyforge/lock/wheelruntime/builder.py +280 -0
- kivyforge/lock/wheelruntime/model.py +94 -0
- kivyforge/lock/wheelruntime/native_binaries.py +127 -0
- kivyforge/lock/wheelruntime/pbs_github.py +133 -0
- kivyforge/lock/wheelruntime/profile.py +104 -0
- kivyforge/lock/wheelruntime/resolver.py +248 -0
- kivyforge/lock/wheelruntime/runtime.py +161 -0
- kivyforge/lock/wheelruntime/serialize.py +245 -0
- kivyforge/platforms/__init__.py +114 -0
- kivyforge/platforms/android/__init__.py +140 -0
- kivyforge/platforms/android/adb.py +215 -0
- kivyforge/platforms/android/bootstrap/__init__.py +7 -0
- kivyforge/platforms/android/bootstrap/contract.py +166 -0
- kivyforge/platforms/android/bootstrap/render.py +244 -0
- kivyforge/platforms/android/bootstrap/templates/androidtest/KivyforgeContractTest.java +76 -0
- kivyforge/platforms/android/bootstrap/templates/bootstrap_py/_kivy_bootstrap.py +50 -0
- kivyforge/platforms/android/bootstrap/templates/bootstrap_py/_kivyforge_bootstrap.py +54 -0
- kivyforge/platforms/android/bootstrap/templates/bootstrap_py/_kivyforge_selftest.py +97 -0
- kivyforge/platforms/android/bootstrap/templates/cpp/CMakeLists.txt +20 -0
- kivyforge/platforms/android/bootstrap/templates/cpp/main.c +150 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/jnius/NativeInvocationHandler.java +48 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/kivy/android/PythonActivity.java +75 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/kivy/android/PythonBundle.java +132 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/kivy/android/PythonService.java +189 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/renpy/android/Hardware.java +276 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/LICENSE-SDL.txt +18 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/SDL_REVISION.txt +3 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDevice.java +22 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDeviceBLESteamController.java +650 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDeviceManager.java +698 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDeviceUSB.java +309 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDL.java +90 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLActivity.java +2120 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLAudioManager.java +514 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLControllerManager.java +856 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLSurface.java +405 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/LICENSE-SDL.txt +18 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/SDL_REVISION.txt +3 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDevice.java +21 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDeviceBLESteamController.java +829 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDeviceManager.java +698 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDeviceUSB.java +354 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDL.java +90 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLActivity.java +2240 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLAudioManager.java +126 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLControllerManager.java +1010 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLDummyEdit.java +66 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLInputConnection.java +136 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLSensorManager.java +73 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLSurface.java +464 -0
- kivyforge/platforms/android/cli.py +1023 -0
- kivyforge/platforms/android/doctor.py +899 -0
- kivyforge/platforms/android/elf.py +148 -0
- kivyforge/platforms/android/generate/__init__.py +1 -0
- kivyforge/platforms/android/generate/manifest.py +261 -0
- kivyforge/platforms/android/generate/project.py +462 -0
- kivyforge/platforms/android/generate/services.py +187 -0
- kivyforge/platforms/android/gradle_wrapper/NOTICE +3 -0
- kivyforge/platforms/android/gradle_wrapper/SHA256SUMS +1 -0
- kivyforge/platforms/android/gradle_wrapper/gradle-wrapper.jar +0 -0
- kivyforge/platforms/android/gradle_wrapper/gradlew +164 -0
- kivyforge/platforms/android/gradle_wrapper/gradlew.bat +90 -0
- kivyforge/platforms/android/gradlew.py +60 -0
- kivyforge/platforms/android/icons.py +237 -0
- kivyforge/platforms/android/lock/__init__.py +1 -0
- kivyforge/platforms/android/lock/archives.py +109 -0
- kivyforge/platforms/android/lock/builder.py +387 -0
- kivyforge/platforms/android/lock/markers.py +71 -0
- kivyforge/platforms/android/lock/maven.py +252 -0
- kivyforge/platforms/android/lock/model.py +113 -0
- kivyforge/platforms/android/lock/python_meta.py +199 -0
- kivyforge/platforms/android/lock/reader.py +206 -0
- kivyforge/platforms/android/lock/resolver.py +276 -0
- kivyforge/platforms/android/lock/writer.py +121 -0
- kivyforge/platforms/android/policy.py +214 -0
- kivyforge/platforms/android/signing.py +145 -0
- kivyforge/platforms/android/smoke.py +43 -0
- kivyforge/platforms/android/splash.py +293 -0
- kivyforge/platforms/android/stage/__init__.py +1 -0
- kivyforge/platforms/android/stage/bundle.py +295 -0
- kivyforge/platforms/android/stage/jnilibs.py +186 -0
- kivyforge/platforms/android/stage/runtime.py +61 -0
- kivyforge/platforms/android/stage/wheels.py +106 -0
- kivyforge/platforms/android/toolchain.py +29 -0
- kivyforge/platforms/base.py +157 -0
- kivyforge/platforms/ios/__init__.py +129 -0
- kivyforge/platforms/ios/assets.py +193 -0
- kivyforge/platforms/ios/buildsettings.py +128 -0
- kivyforge/platforms/ios/cli.py +543 -0
- kivyforge/platforms/ios/doctor.py +410 -0
- kivyforge/platforms/ios/entitlements.py +34 -0
- kivyforge/platforms/ios/generator.py +318 -0
- kivyforge/platforms/ios/lock/__init__.py +71 -0
- kivyforge/platforms/ios/lock/builder.py +393 -0
- kivyforge/platforms/ios/lock/markers.py +69 -0
- kivyforge/platforms/ios/lock/model.py +95 -0
- kivyforge/platforms/ios/lock/python_meta.py +187 -0
- kivyforge/platforms/ios/lock/reader.py +191 -0
- kivyforge/platforms/ios/lock/resolver.py +304 -0
- kivyforge/platforms/ios/lock/spm.py +217 -0
- kivyforge/platforms/ios/lock/writer.py +114 -0
- kivyforge/platforms/ios/lock/xcframework.py +188 -0
- kivyforge/platforms/ios/materialize.py +59 -0
- kivyforge/platforms/ios/plist.py +91 -0
- kivyforge/platforms/ios/privacy.py +39 -0
- kivyforge/platforms/ios/skeleton.py +165 -0
- kivyforge/platforms/ios/sources.py +63 -0
- kivyforge/platforms/ios/staging.py +225 -0
- kivyforge/platforms/ios/swift_packages.py +324 -0
- kivyforge/platforms/ios/templates/kivyforge_bootstrap.h +34 -0
- kivyforge/platforms/ios/templates/kivyforge_bootstrap.m +146 -0
- kivyforge/platforms/ios/templates/main.m +15 -0
- kivyforge/platforms/ios/templates/main_config.h.in +12 -0
- kivyforge/platforms/ios/xcframeworks.py +194 -0
- kivyforge/platforms/ios/xcode/__init__.py +76 -0
- kivyforge/platforms/ios/xcode/commands.py +296 -0
- kivyforge/platforms/ios/xcode/runner.py +316 -0
- kivyforge/platforms/linux/__init__.py +120 -0
- kivyforge/platforms/linux/appimage.py +169 -0
- kivyforge/platforms/linux/bundle.py +235 -0
- kivyforge/platforms/linux/cli.py +232 -0
- kivyforge/platforms/linux/desktop.py +71 -0
- kivyforge/platforms/linux/doctor.py +438 -0
- kivyforge/platforms/linux/elftools.py +95 -0
- kivyforge/platforms/linux/icons.py +129 -0
- kivyforge/platforms/linux/launcher.py +107 -0
- kivyforge/platforms/linux/lock/__init__.py +126 -0
- kivyforge/platforms/linux/lock/profile.py +254 -0
- kivyforge/platforms/linux/lock/runtime.py +75 -0
- kivyforge/platforms/linux/native_stage.py +47 -0
- kivyforge/platforms/linux/runtime_stage.py +107 -0
- kivyforge/platforms/linux/wheels_stage.py +103 -0
- kivyforge/platforms/macos/__init__.py +121 -0
- kivyforge/platforms/macos/bundle.py +255 -0
- kivyforge/platforms/macos/cli.py +269 -0
- kivyforge/platforms/macos/doctor.py +480 -0
- kivyforge/platforms/macos/icns.py +75 -0
- kivyforge/platforms/macos/launcher.py +118 -0
- kivyforge/platforms/macos/lock/__init__.py +112 -0
- kivyforge/platforms/macos/lock/profile.py +119 -0
- kivyforge/platforms/macos/lock/runtime.py +58 -0
- kivyforge/platforms/macos/machotools.py +138 -0
- kivyforge/platforms/macos/native_stage.py +47 -0
- kivyforge/platforms/macos/notarize.py +143 -0
- kivyforge/platforms/macos/plist.py +37 -0
- kivyforge/platforms/macos/runtime_stage.py +110 -0
- kivyforge/platforms/macos/signing.py +78 -0
- kivyforge/platforms/macos/wheels_stage.py +108 -0
- kivyforge/platforms/windows/__init__.py +133 -0
- kivyforge/platforms/windows/assets.py +76 -0
- kivyforge/platforms/windows/bundle.py +298 -0
- kivyforge/platforms/windows/cli.py +314 -0
- kivyforge/platforms/windows/doctor.py +563 -0
- kivyforge/platforms/windows/fsswap.py +87 -0
- kivyforge/platforms/windows/icons.py +64 -0
- kivyforge/platforms/windows/launcher/__init__.py +193 -0
- kivyforge/platforms/windows/launcher/build_launcher.py +507 -0
- kivyforge/platforms/windows/launcher/launcher.c +379 -0
- kivyforge/platforms/windows/lock/__init__.py +112 -0
- kivyforge/platforms/windows/lock/profile.py +101 -0
- kivyforge/platforms/windows/lock/runtime.py +64 -0
- kivyforge/platforms/windows/naming.py +52 -0
- kivyforge/platforms/windows/native_stage.py +66 -0
- kivyforge/platforms/windows/petools.py +98 -0
- kivyforge/platforms/windows/rcedit.py +116 -0
- kivyforge/platforms/windows/runtime_stage.py +221 -0
- kivyforge/platforms/windows/signing.py +168 -0
- kivyforge/platforms/windows/vendor/LICENSE.rcedit +29 -0
- kivyforge/platforms/windows/vendor/NOTICE +17 -0
- kivyforge/platforms/windows/vendor/SHA256SUMS +4 -0
- kivyforge/platforms/windows/vendor/TOOLSET.txt +4 -0
- kivyforge/platforms/windows/vendor/__init__.py +12 -0
- kivyforge/platforms/windows/vendor/fetch_rcedit.py +97 -0
- kivyforge/platforms/windows/vendor/launcher-amd64.exe +0 -0
- kivyforge/platforms/windows/vendor/rcedit-x64.exe +0 -0
- kivyforge/platforms/windows/wheels_stage.py +139 -0
- kivyforge-3.0.0.dev0.dist-info/METADATA +609 -0
- kivyforge-3.0.0.dev0.dist-info/RECORD +225 -0
- kivyforge-3.0.0.dev0.dist-info/WHEEL +5 -0
- kivyforge-3.0.0.dev0.dist-info/entry_points.txt +3 -0
- kivyforge-3.0.0.dev0.dist-info/licenses/LICENSE +21 -0
- kivyforge-3.0.0.dev0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
package org.kivy.android;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import android.system.Os;
|
|
5
|
+
import android.util.Log;
|
|
6
|
+
|
|
7
|
+
import java.io.File;
|
|
8
|
+
import java.io.FileNotFoundException;
|
|
9
|
+
import java.io.FileOutputStream;
|
|
10
|
+
import java.io.InputStream;
|
|
11
|
+
import java.io.OutputStream;
|
|
12
|
+
import java.io.RandomAccessFile;
|
|
13
|
+
import java.nio.channels.FileChannel;
|
|
14
|
+
import java.nio.channels.FileLock;
|
|
15
|
+
import java.nio.charset.StandardCharsets;
|
|
16
|
+
import java.nio.file.Files;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The asset-bundle unpack + environment contract, shared by every process that
|
|
20
|
+
* starts a kivyforge interpreter (docs/design/platforms/android/05).
|
|
21
|
+
*
|
|
22
|
+
* PythonActivity and PythonService both need exactly this sequence, and a
|
|
23
|
+
* service runs in its own process (android:process=":service_*"), so it unpacks
|
|
24
|
+
* and configures independently rather than inheriting the activity's state.
|
|
25
|
+
* Keeping one implementation is deliberate: the environment contract is the
|
|
26
|
+
* most delicate part of the load model, and two copies would drift.
|
|
27
|
+
*/
|
|
28
|
+
public class PythonBundle {
|
|
29
|
+
private static final String TAG = "kivyforge";
|
|
30
|
+
|
|
31
|
+
/** Unpack assets/_python_bundle to filesDir, skipped when VERSION matches.
|
|
32
|
+
*
|
|
33
|
+
* Serialized across processes: a service starts in its own process and may
|
|
34
|
+
* race the activity here, and two unpacks into the same directory would
|
|
35
|
+
* leave a half-written bundle behind whichever finished first.
|
|
36
|
+
*/
|
|
37
|
+
public static File unpack(Context ctx) throws Exception {
|
|
38
|
+
File lock = new File(ctx.getFilesDir(), "_python_bundle.lock");
|
|
39
|
+
try (RandomAccessFile raf = new RandomAccessFile(lock, "rw");
|
|
40
|
+
FileChannel channel = raf.getChannel();
|
|
41
|
+
FileLock held = channel.lock()) {
|
|
42
|
+
return unpackLocked(ctx);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private static File unpackLocked(Context ctx) throws Exception {
|
|
47
|
+
File target = new File(ctx.getFilesDir(), "_python_bundle");
|
|
48
|
+
File stamp = new File(target, "VERSION");
|
|
49
|
+
String wanted = readAsset(ctx, "_python_bundle/VERSION");
|
|
50
|
+
if (stamp.exists()) {
|
|
51
|
+
String have = new String(
|
|
52
|
+
Files.readAllBytes(stamp.toPath()), StandardCharsets.UTF_8);
|
|
53
|
+
if (have.equals(wanted)) {
|
|
54
|
+
Log.i(TAG, "bundle up to date (VERSION " + have + "), skipping unpack");
|
|
55
|
+
Os.setenv("KF_UNPACK_SKIPPED", "1", true);
|
|
56
|
+
return target;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
Log.i(TAG, "unpacking bundle...");
|
|
60
|
+
long t0 = System.currentTimeMillis();
|
|
61
|
+
deleteRecursive(target);
|
|
62
|
+
extractAssetDir(ctx, "_python_bundle", ctx.getFilesDir());
|
|
63
|
+
Log.i(TAG, "bundle unpacked in " + (System.currentTimeMillis() - t0) + " ms");
|
|
64
|
+
Os.setenv("KF_UNPACK_SKIPPED", "0", true);
|
|
65
|
+
return target;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Set the environment contract the native launcher and Kivy/pyjnius read.
|
|
70
|
+
* Must run before any native code in the process.
|
|
71
|
+
*/
|
|
72
|
+
public static void setEnvironment(Context ctx, File bundleDir, String entryPoint)
|
|
73
|
+
throws Exception {
|
|
74
|
+
File appDir = new File(bundleDir, "app");
|
|
75
|
+
Os.setenv("KF_BUNDLE", bundleDir.getAbsolutePath(), true);
|
|
76
|
+
Os.setenv("KF_NATIVE_DIR", ctx.getApplicationInfo().nativeLibraryDir, true);
|
|
77
|
+
Os.setenv("KF_ENTRY_POINT", entryPoint, true);
|
|
78
|
+
// pyjnius/Kivy environment contract:
|
|
79
|
+
Os.setenv("ANDROID_ARGUMENT", appDir.getAbsolutePath(), true);
|
|
80
|
+
Os.setenv("ANDROID_APP_PATH", appDir.getAbsolutePath(), true);
|
|
81
|
+
Os.setenv("ANDROID_PRIVATE", ctx.getFilesDir().getAbsolutePath(), true);
|
|
82
|
+
Os.setenv("ANDROID_UNPACK", bundleDir.getAbsolutePath(), true);
|
|
83
|
+
Os.setenv("TMPDIR", ctx.getCacheDir().getAbsolutePath(), false);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private static String readAsset(Context ctx, String path) throws Exception {
|
|
87
|
+
try (InputStream in = ctx.getAssets().open(path)) {
|
|
88
|
+
return new String(readAll(in), StandardCharsets.UTF_8);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private static byte[] readAll(InputStream in) throws Exception {
|
|
93
|
+
java.io.ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream();
|
|
94
|
+
byte[] buf = new byte[65536];
|
|
95
|
+
int n;
|
|
96
|
+
while ((n = in.read(buf)) > 0) bos.write(buf, 0, n);
|
|
97
|
+
return bos.toByteArray();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private static void extractAssetDir(Context ctx, String path, File targetDir)
|
|
101
|
+
throws Exception {
|
|
102
|
+
String[] names = ctx.getAssets().list(path);
|
|
103
|
+
if (names == null) throw new RuntimeException("cannot list asset " + path);
|
|
104
|
+
File subdir = new File(targetDir, path);
|
|
105
|
+
if (!subdir.exists() && !subdir.mkdirs())
|
|
106
|
+
throw new RuntimeException("mkdirs failed: " + subdir);
|
|
107
|
+
for (String name : names) {
|
|
108
|
+
String subPath = path + "/" + name;
|
|
109
|
+
InputStream in;
|
|
110
|
+
try {
|
|
111
|
+
in = ctx.getAssets().open(subPath);
|
|
112
|
+
} catch (FileNotFoundException e) {
|
|
113
|
+
extractAssetDir(ctx, subPath, targetDir);
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
try (InputStream input = in;
|
|
117
|
+
OutputStream out = new FileOutputStream(new File(subdir, name))) {
|
|
118
|
+
byte[] buf = new byte[65536];
|
|
119
|
+
int n;
|
|
120
|
+
while ((n = input.read(buf)) > 0) out.write(buf, 0, n);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private static void deleteRecursive(File f) {
|
|
126
|
+
if (f.isDirectory()) {
|
|
127
|
+
File[] children = f.listFiles();
|
|
128
|
+
if (children != null) for (File c : children) deleteRecursive(c);
|
|
129
|
+
}
|
|
130
|
+
f.delete();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
package org.kivy.android;
|
|
2
|
+
|
|
3
|
+
import android.app.Notification;
|
|
4
|
+
import android.app.NotificationChannel;
|
|
5
|
+
import android.app.NotificationManager;
|
|
6
|
+
import android.app.Service;
|
|
7
|
+
import android.content.Intent;
|
|
8
|
+
import android.os.Build;
|
|
9
|
+
import android.os.IBinder;
|
|
10
|
+
import android.system.Os;
|
|
11
|
+
import android.util.Log;
|
|
12
|
+
|
|
13
|
+
import java.io.File;
|
|
14
|
+
import java.io.FileOutputStream;
|
|
15
|
+
import java.nio.charset.StandardCharsets;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Base class for the services generated from [[tool.kivy.android.services]]
|
|
19
|
+
* (docs/design/platforms/android/05 §services).
|
|
20
|
+
*
|
|
21
|
+
* Each declared service becomes a subclass that names its Python entry point
|
|
22
|
+
* and, when it is a foreground service, its notification. The manifest gives
|
|
23
|
+
* every service its own android:process, so this runs in a fresh process: it
|
|
24
|
+
* unpacks the bundle, sets the same environment contract the activity does, and
|
|
25
|
+
* starts one interpreter — on a background thread, because the interpreter does
|
|
26
|
+
* not return until the entry point does and blocking a service's main thread is
|
|
27
|
+
* an ANR.
|
|
28
|
+
*
|
|
29
|
+
* There is no SDL here. The service's Python does background work, so only
|
|
30
|
+
* libpython and libmain are loaded; nothing creates a window or a JNIEnv-owning
|
|
31
|
+
* SDL thread.
|
|
32
|
+
*/
|
|
33
|
+
public class PythonService extends Service implements Runnable {
|
|
34
|
+
private static final String TAG = "kivyforge";
|
|
35
|
+
// The libpython soname stem, substituted at render time.
|
|
36
|
+
private static final String PYTHON_LIB = "python3.14";
|
|
37
|
+
|
|
38
|
+
private static final int NOTIFICATION_ID = 1;
|
|
39
|
+
|
|
40
|
+
private boolean mStarted = false;
|
|
41
|
+
private Thread mThread = null;
|
|
42
|
+
|
|
43
|
+
// --- overridden by the generated subclass ------------------------------ #
|
|
44
|
+
|
|
45
|
+
/** The service's [[services]] name, used for logging + the ready marker. */
|
|
46
|
+
protected String getServiceName() {
|
|
47
|
+
return getClass().getSimpleName();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** The Python module this service imports (its own entry_point). */
|
|
51
|
+
protected String getEntryPoint() {
|
|
52
|
+
return "main";
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
protected boolean isForeground() {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
protected String getChannelId() {
|
|
60
|
+
return "kivyforge_service";
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
protected String getChannelName() {
|
|
64
|
+
return "Background service";
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
protected String getNotificationTitle() {
|
|
68
|
+
return getServiceName();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
protected String getNotificationText() {
|
|
72
|
+
return "";
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** A drawable resource name for the notification icon, or null for none. */
|
|
76
|
+
protected String getNotificationIcon() {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// --- service lifecycle ------------------------------------------------- #
|
|
81
|
+
|
|
82
|
+
@Override
|
|
83
|
+
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
84
|
+
if (isForeground()) {
|
|
85
|
+
// Mandatory on Android 14+: a foreground service that does not
|
|
86
|
+
// call startForeground() promptly is killed by the OS.
|
|
87
|
+
startForegroundNotification();
|
|
88
|
+
}
|
|
89
|
+
if (!mStarted) {
|
|
90
|
+
mStarted = true;
|
|
91
|
+
String argument = intent == null
|
|
92
|
+
? null : intent.getStringExtra("kivyforge_service_argument");
|
|
93
|
+
try {
|
|
94
|
+
prepare(argument);
|
|
95
|
+
} catch (Exception e) {
|
|
96
|
+
Log.e(TAG, "service " + getServiceName() + " failed to prepare", e);
|
|
97
|
+
stopSelf();
|
|
98
|
+
return START_NOT_STICKY;
|
|
99
|
+
}
|
|
100
|
+
mThread = new Thread(this, "python-service-" + getServiceName());
|
|
101
|
+
mThread.start();
|
|
102
|
+
}
|
|
103
|
+
// Deliberately not sticky: a crash-looping service that the OS keeps
|
|
104
|
+
// restarting is worse than one that stays down and is visible as down.
|
|
105
|
+
return START_NOT_STICKY;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@Override
|
|
109
|
+
public IBinder onBind(Intent intent) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Unpack + environment, then the ready-marker path the smoke test polls. */
|
|
114
|
+
private void prepare(String argument) throws Exception {
|
|
115
|
+
File bundleDir = PythonBundle.unpack(this);
|
|
116
|
+
PythonBundle.setEnvironment(this, bundleDir, getEntryPoint());
|
|
117
|
+
// p4a convention, kept so existing service code keeps working.
|
|
118
|
+
Os.setenv("PYTHON_SERVICE_ARGUMENT", argument == null ? "" : argument, true);
|
|
119
|
+
File marker = markerFile(this, getServiceName());
|
|
120
|
+
marker.delete();
|
|
121
|
+
Os.setenv("KF_SERVICE_MARKER", marker.getAbsolutePath(), true);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Where the interpreter records that it came up (android/06 --smoke). */
|
|
125
|
+
public static File markerFile(Service service, String name) {
|
|
126
|
+
return new File(service.getFilesDir(), "kivyforge_service_" + name + ".txt");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
@Override
|
|
130
|
+
public void run() {
|
|
131
|
+
Log.i(TAG, "service " + getServiceName() + ": starting " + getEntryPoint());
|
|
132
|
+
try {
|
|
133
|
+
System.loadLibrary(PYTHON_LIB);
|
|
134
|
+
System.loadLibrary("main");
|
|
135
|
+
int rc = nativeStart();
|
|
136
|
+
Log.i(TAG, "service " + getServiceName() + " returned " + rc);
|
|
137
|
+
} catch (UnsatisfiedLinkError e) {
|
|
138
|
+
Log.e(TAG, "service " + getServiceName() + ": native start failed", e);
|
|
139
|
+
recordFailure(e.toString());
|
|
140
|
+
} finally {
|
|
141
|
+
stopSelf();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private void recordFailure(String detail) {
|
|
146
|
+
File marker = markerFile(this, getServiceName());
|
|
147
|
+
try (FileOutputStream out = new FileOutputStream(marker, true)) {
|
|
148
|
+
out.write(("SERVICE_START_FAILED " + detail + "\n")
|
|
149
|
+
.getBytes(StandardCharsets.UTF_8));
|
|
150
|
+
} catch (Exception ignored) {
|
|
151
|
+
// The marker is diagnostics; losing it must not mask the real error.
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private void startForegroundNotification() {
|
|
156
|
+
NotificationManager manager = getSystemService(NotificationManager.class);
|
|
157
|
+
Notification.Builder builder;
|
|
158
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
159
|
+
NotificationChannel channel = new NotificationChannel(
|
|
160
|
+
getChannelId(), getChannelName(), NotificationManager.IMPORTANCE_LOW);
|
|
161
|
+
manager.createNotificationChannel(channel);
|
|
162
|
+
builder = new Notification.Builder(this, getChannelId());
|
|
163
|
+
} else {
|
|
164
|
+
builder = new Notification.Builder(this);
|
|
165
|
+
}
|
|
166
|
+
builder.setContentTitle(getNotificationTitle());
|
|
167
|
+
builder.setContentText(getNotificationText());
|
|
168
|
+
builder.setSmallIcon(notificationIconResource());
|
|
169
|
+
startForeground(NOTIFICATION_ID, builder.build());
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private int notificationIconResource() {
|
|
173
|
+
String icon = getNotificationIcon();
|
|
174
|
+
if (icon != null) {
|
|
175
|
+
int id = getResources().getIdentifier(icon, "drawable", getPackageName());
|
|
176
|
+
if (id == 0) {
|
|
177
|
+
id = getResources().getIdentifier(icon, "mipmap", getPackageName());
|
|
178
|
+
}
|
|
179
|
+
if (id != 0) {
|
|
180
|
+
return id;
|
|
181
|
+
}
|
|
182
|
+
Log.w(TAG, "notification icon " + icon + " not found; using the launcher");
|
|
183
|
+
}
|
|
184
|
+
return getApplicationInfo().icon;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Implemented in libmain (cpp/main.c): brings up CPython in this process. */
|
|
188
|
+
private native int nativeStart();
|
|
189
|
+
}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* org.renpy.android.Hardware — Kivy-compatibility shim.
|
|
3
|
+
*
|
|
4
|
+
* Kivy's own kivy/metrics.py calls autoclass('org.renpy.android.Hardware')
|
|
5
|
+
* for DPI/fontscale, so the kivyforge bootstrap must supply this class for
|
|
6
|
+
* unmodified Kivy-Android apps to start (android/05 §namespace preservation).
|
|
7
|
+
* Vendored verbatim from python-for-android (MIT License,
|
|
8
|
+
* https://github.com/kivy/python-for-android) — the surface Kivy was written
|
|
9
|
+
* against. Kivy's startup path (getDPI/get_fontscale) uses only the
|
|
10
|
+
* PythonActivity.mActivity reference; `context` is initialized lazily below so
|
|
11
|
+
* the sensor/network helpers work without a cross-package assignment.
|
|
12
|
+
*
|
|
13
|
+
* vibrate/getDPI/checkNetwork call APIs Android has since deprecated
|
|
14
|
+
* (Vibrator#vibrate(int), Display#getMetrics, ConnectivityManager
|
|
15
|
+
* #getActiveNetworkInfo) but not removed; their replacements need API
|
|
16
|
+
* 26/30/29 respectively, above this project's min_sdk floor of 24, so the
|
|
17
|
+
* deprecated call is kept rather than forking this surface into two paths.
|
|
18
|
+
* @SuppressWarnings("deprecation") on each is a deliberate, understood
|
|
19
|
+
* choice, not an oversight — see android/05 for the min_sdk floor.
|
|
20
|
+
*/
|
|
21
|
+
package org.renpy.android;
|
|
22
|
+
|
|
23
|
+
import android.content.BroadcastReceiver;
|
|
24
|
+
import android.content.Context;
|
|
25
|
+
import android.content.Intent;
|
|
26
|
+
import android.content.IntentFilter;
|
|
27
|
+
import android.hardware.Sensor;
|
|
28
|
+
import android.hardware.SensorEvent;
|
|
29
|
+
import android.hardware.SensorEventListener;
|
|
30
|
+
import android.hardware.SensorManager;
|
|
31
|
+
import android.net.ConnectivityManager;
|
|
32
|
+
import android.net.NetworkInfo;
|
|
33
|
+
import android.net.wifi.ScanResult;
|
|
34
|
+
import android.net.wifi.WifiManager;
|
|
35
|
+
import android.os.Vibrator;
|
|
36
|
+
import android.util.DisplayMetrics;
|
|
37
|
+
import android.view.View;
|
|
38
|
+
import android.view.inputmethod.InputMethodManager;
|
|
39
|
+
import java.util.List;
|
|
40
|
+
import org.kivy.android.PythonActivity;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Methods that are expected to be called via JNI, to access the device's non-screen hardware. (For
|
|
44
|
+
* example, the vibration and accelerometer.)
|
|
45
|
+
*/
|
|
46
|
+
public class Hardware {
|
|
47
|
+
|
|
48
|
+
// The context.
|
|
49
|
+
static Context context;
|
|
50
|
+
static View view;
|
|
51
|
+
public static final float defaultRv[] = {0f, 0f, 0f};
|
|
52
|
+
|
|
53
|
+
/** Vibrate for s seconds. */
|
|
54
|
+
@SuppressWarnings("deprecation")
|
|
55
|
+
public static void vibrate(double s) {
|
|
56
|
+
Vibrator v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
|
|
57
|
+
if (v != null) {
|
|
58
|
+
v.vibrate((int) (1000 * s));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Get an Overview of all Hardware Sensors of an Android Device */
|
|
63
|
+
public static String getHardwareSensors() {
|
|
64
|
+
SensorManager sm = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
|
|
65
|
+
List<Sensor> allSensors = sm.getSensorList(Sensor.TYPE_ALL);
|
|
66
|
+
|
|
67
|
+
if (allSensors != null) {
|
|
68
|
+
String resultString = "";
|
|
69
|
+
for (Sensor s : allSensors) {
|
|
70
|
+
resultString += String.format("Name=" + s.getName());
|
|
71
|
+
resultString += String.format(",Vendor=" + s.getVendor());
|
|
72
|
+
resultString += String.format(",Version=" + s.getVersion());
|
|
73
|
+
resultString += String.format(",MaximumRange=" + s.getMaximumRange());
|
|
74
|
+
// XXX MinDelay is not in the 2.2
|
|
75
|
+
// resultString += String.format(",MinDelay=" + s.getMinDelay());
|
|
76
|
+
resultString += String.format(",Power=" + s.getPower());
|
|
77
|
+
resultString += String.format(",Type=" + s.getType() + "\n");
|
|
78
|
+
}
|
|
79
|
+
return resultString;
|
|
80
|
+
}
|
|
81
|
+
return "";
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Get Access to 3 Axis Hardware Sensors Accelerometer, Orientation and Magnetic Field Sensors
|
|
86
|
+
*/
|
|
87
|
+
public static class generic3AxisSensor implements SensorEventListener {
|
|
88
|
+
private final SensorManager sSensorManager;
|
|
89
|
+
private final Sensor sSensor;
|
|
90
|
+
private final int sSensorType;
|
|
91
|
+
SensorEvent sSensorEvent;
|
|
92
|
+
|
|
93
|
+
public generic3AxisSensor(int sensorType) {
|
|
94
|
+
sSensorType = sensorType;
|
|
95
|
+
sSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
|
|
96
|
+
sSensor = sSensorManager.getDefaultSensor(sSensorType);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
|
|
100
|
+
|
|
101
|
+
public void onSensorChanged(SensorEvent event) {
|
|
102
|
+
sSensorEvent = event;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Enable or disable the Sensor by registering/unregistering */
|
|
106
|
+
public void changeStatus(boolean enable) {
|
|
107
|
+
if (enable) {
|
|
108
|
+
sSensorManager.registerListener(this, sSensor, SensorManager.SENSOR_DELAY_NORMAL);
|
|
109
|
+
} else {
|
|
110
|
+
sSensorManager.unregisterListener(this, sSensor);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Read the Sensor */
|
|
115
|
+
public float[] readSensor() {
|
|
116
|
+
if (sSensorEvent != null) {
|
|
117
|
+
return sSensorEvent.values;
|
|
118
|
+
} else {
|
|
119
|
+
return defaultRv;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
public static generic3AxisSensor accelerometerSensor = null;
|
|
125
|
+
public static generic3AxisSensor orientationSensor = null;
|
|
126
|
+
public static generic3AxisSensor magneticFieldSensor = null;
|
|
127
|
+
|
|
128
|
+
/** functions for backward compatibility reasons */
|
|
129
|
+
public static void accelerometerEnable(boolean enable) {
|
|
130
|
+
if (accelerometerSensor == null)
|
|
131
|
+
accelerometerSensor = new generic3AxisSensor(Sensor.TYPE_ACCELEROMETER);
|
|
132
|
+
accelerometerSensor.changeStatus(enable);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public static float[] accelerometerReading() {
|
|
136
|
+
if (accelerometerSensor == null) return defaultRv;
|
|
137
|
+
return (float[]) accelerometerSensor.readSensor();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public static void orientationSensorEnable(boolean enable) {
|
|
141
|
+
if (orientationSensor == null)
|
|
142
|
+
orientationSensor = new generic3AxisSensor(Sensor.TYPE_ORIENTATION);
|
|
143
|
+
orientationSensor.changeStatus(enable);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
public static float[] orientationSensorReading() {
|
|
147
|
+
if (orientationSensor == null) return defaultRv;
|
|
148
|
+
return (float[]) orientationSensor.readSensor();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
public static void magneticFieldSensorEnable(boolean enable) {
|
|
152
|
+
if (magneticFieldSensor == null)
|
|
153
|
+
magneticFieldSensor = new generic3AxisSensor(Sensor.TYPE_MAGNETIC_FIELD);
|
|
154
|
+
magneticFieldSensor.changeStatus(enable);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
public static float[] magneticFieldSensorReading() {
|
|
158
|
+
if (magneticFieldSensor == null) return defaultRv;
|
|
159
|
+
return (float[]) magneticFieldSensor.readSensor();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
public static DisplayMetrics metrics = new DisplayMetrics();
|
|
163
|
+
|
|
164
|
+
/** Get display DPI. */
|
|
165
|
+
@SuppressWarnings("deprecation")
|
|
166
|
+
public static int getDPI() {
|
|
167
|
+
// AND: Shouldn't have to get the metrics like this every time...
|
|
168
|
+
PythonActivity.mActivity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
|
|
169
|
+
return metrics.densityDpi;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// /**
|
|
173
|
+
// * Show the soft keyboard.
|
|
174
|
+
// */
|
|
175
|
+
// public static void showKeyboard(int input_type) {
|
|
176
|
+
// //Log.i("python", "hardware.Java show_keyword " input_type);
|
|
177
|
+
|
|
178
|
+
// InputMethodManager imm = (InputMethodManager)
|
|
179
|
+
// context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
180
|
+
|
|
181
|
+
// SDLSurfaceView vw = (SDLSurfaceView) view;
|
|
182
|
+
|
|
183
|
+
// int inputType = input_type;
|
|
184
|
+
|
|
185
|
+
// if (vw.inputType != inputType){
|
|
186
|
+
// vw.inputType = inputType;
|
|
187
|
+
// imm.restartInput(view);
|
|
188
|
+
// }
|
|
189
|
+
|
|
190
|
+
// imm.showSoftInput(view, InputMethodManager.SHOW_FORCED);
|
|
191
|
+
// }
|
|
192
|
+
|
|
193
|
+
/** Hide the soft keyboard. */
|
|
194
|
+
public static void hideKeyboard() {
|
|
195
|
+
InputMethodManager imm =
|
|
196
|
+
(InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
197
|
+
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** Scan WiFi networks */
|
|
201
|
+
static List<ScanResult> latestResult;
|
|
202
|
+
|
|
203
|
+
public static void enableWifiScanner() {
|
|
204
|
+
IntentFilter i = new IntentFilter();
|
|
205
|
+
i.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
|
|
206
|
+
|
|
207
|
+
context.registerReceiver(
|
|
208
|
+
new BroadcastReceiver() {
|
|
209
|
+
|
|
210
|
+
@Override
|
|
211
|
+
public void onReceive(Context c, Intent i) {
|
|
212
|
+
// Code to execute when SCAN_RESULTS_AVAILABLE_ACTION event occurs
|
|
213
|
+
WifiManager w = (WifiManager) c.getSystemService(Context.WIFI_SERVICE);
|
|
214
|
+
latestResult = w.getScanResults(); // Returns a <list> of scanResults
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
i);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
public static String scanWifi() {
|
|
221
|
+
|
|
222
|
+
// Now you can call this and it should execute the broadcastReceiver's
|
|
223
|
+
// onReceive()
|
|
224
|
+
if (latestResult != null) {
|
|
225
|
+
|
|
226
|
+
String latestResultString = "";
|
|
227
|
+
for (ScanResult result : latestResult) {
|
|
228
|
+
latestResultString +=
|
|
229
|
+
String.format("%s\t%s\t%d\n", result.SSID, result.BSSID, result.level);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return latestResultString;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return "";
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** network state */
|
|
239
|
+
public static boolean network_state = false;
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Check network state directly
|
|
243
|
+
*
|
|
244
|
+
* <p>(only one connection can be active at a given moment, detects all network type)
|
|
245
|
+
*/
|
|
246
|
+
@SuppressWarnings("deprecation")
|
|
247
|
+
public static boolean checkNetwork() {
|
|
248
|
+
boolean state = false;
|
|
249
|
+
final ConnectivityManager conMgr =
|
|
250
|
+
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
|
251
|
+
|
|
252
|
+
final NetworkInfo activeNetwork = conMgr.getActiveNetworkInfo();
|
|
253
|
+
if (activeNetwork != null && activeNetwork.isConnected()) {
|
|
254
|
+
state = true;
|
|
255
|
+
} else {
|
|
256
|
+
state = false;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return state;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** To receive network state changes */
|
|
263
|
+
public static void registerNetworkCheck() {
|
|
264
|
+
IntentFilter i = new IntentFilter();
|
|
265
|
+
i.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
|
266
|
+
context.registerReceiver(
|
|
267
|
+
new BroadcastReceiver() {
|
|
268
|
+
|
|
269
|
+
@Override
|
|
270
|
+
public void onReceive(Context c, Intent i) {
|
|
271
|
+
network_state = checkNetwork();
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
i);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
|
2
|
+
|
|
3
|
+
This software is provided 'as-is', without any express or implied
|
|
4
|
+
warranty. In no event will the authors be held liable for any damages
|
|
5
|
+
arising from the use of this software.
|
|
6
|
+
|
|
7
|
+
Permission is granted to anyone to use this software for any purpose,
|
|
8
|
+
including commercial applications, and to alter it and redistribute it
|
|
9
|
+
freely, subject to the following restrictions:
|
|
10
|
+
|
|
11
|
+
1. The origin of this software must not be misrepresented; you must not
|
|
12
|
+
claim that you wrote the original software. If you use this software
|
|
13
|
+
in a product, an acknowledgment in the product documentation would be
|
|
14
|
+
appreciated but is not required.
|
|
15
|
+
2. Altered source versions must be plainly marked as such, and must not be
|
|
16
|
+
misrepresented as being the original software.
|
|
17
|
+
3. This notice may not be removed or altered from any source distribution.
|
|
18
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
package org.libsdl.app;
|
|
2
|
+
|
|
3
|
+
import android.hardware.usb.UsbDevice;
|
|
4
|
+
|
|
5
|
+
interface HIDDevice
|
|
6
|
+
{
|
|
7
|
+
public int getId();
|
|
8
|
+
public int getVendorId();
|
|
9
|
+
public int getProductId();
|
|
10
|
+
public String getSerialNumber();
|
|
11
|
+
public int getVersion();
|
|
12
|
+
public String getManufacturerName();
|
|
13
|
+
public String getProductName();
|
|
14
|
+
public UsbDevice getDevice();
|
|
15
|
+
public boolean open();
|
|
16
|
+
public int sendFeatureReport(byte[] report);
|
|
17
|
+
public int sendOutputReport(byte[] report);
|
|
18
|
+
public boolean getFeatureReport(byte[] report);
|
|
19
|
+
public void setFrozen(boolean frozen);
|
|
20
|
+
public void close();
|
|
21
|
+
public void shutdown();
|
|
22
|
+
}
|