Improved core code
This commit is contained in:
281
README.md
Normal file
281
README.md
Normal file
@@ -0,0 +1,281 @@
|
||||
# AniyomiBridge Core
|
||||
|
||||
A JVM runtime for running Aniyomi (anime/manga streaming) Android extensions on desktop. This project bridges the gap between Android's framework and desktop Java/Kotlin by providing a compatibility layer that lets Aniyomi extensions execute outside of the Android ecosystem.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Build the fat JAR (includes all dependencies)
|
||||
mvn clean package
|
||||
|
||||
# Output: aniyomibridge-core/target/aniyomibridge-core-1.0.0.jar
|
||||
# Main class: dev.k3vinb5.aniyomibridge.Main
|
||||
```
|
||||
|
||||
## Project Architecture
|
||||
|
||||
This is a **multi-module Maven project** with two main modules:
|
||||
|
||||
```
|
||||
aniyomibridge-core/
|
||||
├── pom.xml # Parent POM — coordinates modules
|
||||
├── androidcompat/ # Android compatibility layer
|
||||
│ ├── src/main/java/android/ # Custom Android stub implementations
|
||||
│ ├── src/main/java/androidx/ # AndroidX stub implementations
|
||||
│ ├── scripts/get-android.sh # Android SDK JAR download & patch script
|
||||
│ └── pom.xml
|
||||
├── aniyomibridge-core/ # Core bridge module
|
||||
│ ├── src/main/java/ # Java sources (bridge core)
|
||||
│ ├── src/main/kotlin/ # Kotlin sources (Tachiyomi/Aniyomi interfaces)
|
||||
│ └── pom.xml
|
||||
└── assets/ # JavaScript files for extractors
|
||||
```
|
||||
|
||||
### Module: `androidcompat`
|
||||
|
||||
Provides Android framework classes on desktop JVM using a **hybrid approach** inspired by [Suwayomi](https://github.com/Suwayomi/Suwayomi-Server):
|
||||
|
||||
1. **Base SDK**: Downloads the official Android SDK `android.jar` from [Sable/android-platforms](https://github.com/Sable/android-platforms)
|
||||
2. **Custom Stubs**: Implements desktop-specific behavior for classes that need it (e.g., `Context`, `WebView`, `SharedPreferences`)
|
||||
3. **Jar Patching**: Removes SDK classes that have custom implementations to prevent conflicts
|
||||
|
||||
**Result**: A merged Android API where ~4,000 SDK classes work as-is, and ~30+ critical classes have desktop-aware implementations.
|
||||
|
||||
### Module: `aniyomibridge-core`
|
||||
|
||||
The core bridge that loads and executes Aniyomi/Tachiyomi extensions.
|
||||
|
||||
**Key Classes**:
|
||||
- `AniyomiBridge.java` — Main API for loading/unloading extensions
|
||||
- `ExtensionLoader.java` — Loads extension classes from JAR files
|
||||
- `ApkUtils.java` — Converts Android APK → JAR using dex2jar
|
||||
|
||||
**Extension Loading Flow**:
|
||||
1. Download APK from URL
|
||||
2. `ApkUtils.dex2jar()` converts APK → JAR
|
||||
3. `ExtensionLoader.loadClassFromJar()` loads the main extension class
|
||||
4. Cast to `AnimeHttpSource` or `CatalogueSource`
|
||||
5. Store in `animeSources`/`mangaSources` maps
|
||||
|
||||
## The Build Process Explained
|
||||
|
||||
When you type `mvn clean package`, here's exactly what happens, phase by phase, across both modules.
|
||||
|
||||
### Module Build Order
|
||||
|
||||
Maven builds modules in dependency order:
|
||||
|
||||
1. **Parent POM** (coordinates children, does not produce a JAR)
|
||||
2. **`androidcompat`** (no internal dependencies)
|
||||
3. **`aniyomibridge-core`** (depends on `androidcompat`)
|
||||
|
||||
`androidcompat` **must** finish its `package` phase before `aniyomibridge-core` can even start compiling.
|
||||
|
||||
### Phase-by-Phase Breakdown
|
||||
|
||||
#### 1. `clean` phase
|
||||
**Plugin:** `maven-clean-plugin`
|
||||
|
||||
- Deletes `androidcompat/target/` and `aniyomibridge-core/target/`
|
||||
- Fresh slate. Any previously downloaded `android.jar` or compiled classes are removed.
|
||||
|
||||
#### 2. `validate` through `process-sources`
|
||||
**Plugins:** `maven-compiler-plugin`, `kotlin-maven-plugin` (configuration only)
|
||||
|
||||
- Maven validates all POMs are well-formed
|
||||
- Standard lifecycle phases proceed normally
|
||||
|
||||
#### 3. `generate-resources` phase *(androidcompat only)*
|
||||
**Plugin:** `exec-maven-plugin`
|
||||
|
||||
```xml
|
||||
<phase>generate-resources</phase>
|
||||
<goal>exec</goal>
|
||||
```
|
||||
|
||||
- Maven runs `scripts/get-android.sh`
|
||||
- The script:
|
||||
1. Downloads `android.jar` from Sable/android-platforms (if not cached)
|
||||
2. Verifies it's a valid JAR
|
||||
3. Uses `zip -d` to **delete** classes that have custom stubs (e.g., `android.content.Context`, `android.app.Application`)
|
||||
4. Saves result as `androidcompat/target/patched-android.jar`
|
||||
|
||||
> **Result:** A stripped Android SDK JAR with "holes" where custom implementations will go.
|
||||
|
||||
#### 4. `process-resources` phase *(androidcompat only)*
|
||||
**Plugin:** `maven-antrun-plugin`
|
||||
|
||||
```xml
|
||||
<phase>process-resources</phase>
|
||||
```
|
||||
|
||||
- Maven runs the Ant task that **unpacks** `patched-android.jar` into `androidcompat/target/classes/`
|
||||
- This dumps ~4,000 `.class` files (the SDK stubs) into the build output directory
|
||||
|
||||
> **Result:** `androidcompat/target/classes/` now contains all Android SDK classes you *didn't* write custom stubs for.
|
||||
|
||||
#### 5. `compile` phase
|
||||
**Plugins:** `maven-compiler-plugin` + `kotlin-maven-plugin`
|
||||
|
||||
- Compiles custom Java stubs from `androidcompat/src/main/java/` into `androidcompat/target/classes/`
|
||||
- Compiles Kotlin sources too
|
||||
- **Critical:** Compiled output goes to the **same** `target/classes/` directory, so custom stubs **overwrite** the SDK classes that were unpacked there
|
||||
|
||||
> **Result:** `target/classes/` now contains:
|
||||
> - SDK classes (the ones you don't override)
|
||||
> - Your custom stubs (overwriting the SDK versions)
|
||||
> - Your project-specific classes
|
||||
|
||||
This is the **hybrid magic** — the directory contains a merged Android API.
|
||||
|
||||
#### 6. `process-classes` through `prepare-package`
|
||||
- Nothing special in this project
|
||||
- Annotation processors or bytecode weaving would happen here if configured
|
||||
|
||||
#### 7. `package` phase
|
||||
|
||||
Two different things happen per module:
|
||||
|
||||
##### In `androidcompat`:
|
||||
**Plugin:** `maven-jar-plugin`
|
||||
- Packages `target/classes/` into `androidcompat/target/androidcompat-1.0.0.jar`
|
||||
- This JAR contains the merged Android API (SDK + custom stubs)
|
||||
|
||||
##### In `aniyomibridge-core`:
|
||||
**Plugins:** `maven-jar-plugin` → `maven-shade-plugin`
|
||||
|
||||
1. **maven-jar-plugin** creates the "thin" JAR: `aniyomibridge-core-1.0.0.jar`
|
||||
|
||||
2. **maven-shade-plugin** then runs:
|
||||
- Takes the thin JAR
|
||||
- **Unpacks** the `androidcompat` dependency JAR into it
|
||||
- **Unpacks** all other dependencies (OkHttp, Kotlin stdlib, Gson, etc.)
|
||||
- Applies filter rules:
|
||||
- `minimizeJar=true` strips unused classes from dependencies
|
||||
- A `<filter>` for `androidcompat` forces **all** its classes to be included (otherwise they'd be stripped because extensions load them dynamically, not via direct references in core code)
|
||||
- Excludes `Main.class` from the final JAR (consumed by Flutter externally)
|
||||
- Excludes signing files (`*.SF`, `*.DSA`, `*.RSA`) and `module-info.class`
|
||||
- Creates the **fat JAR**: `aniyomibridge-core/target/aniyomibridge-core-1.0.0.jar`
|
||||
|
||||
> **Result:** A single ~90MB JAR containing your core code + the entire merged Android API + all dependencies.
|
||||
|
||||
### Visual Timeline
|
||||
|
||||
```
|
||||
$ mvn clean package
|
||||
|
||||
[MODULE: parent pom]
|
||||
validate → compile → package (pom packaging, just validates)
|
||||
|
||||
[MODULE: androidcompat]
|
||||
clean → delete target/
|
||||
validate → check pom
|
||||
...
|
||||
generate-resources → exec-maven-plugin runs get-android.sh
|
||||
↳ downloads & patches android.jar
|
||||
process-resources → maven-antrun-plugin unpacks patched JAR
|
||||
↳ target/classes/ ← 4,000 SDK .class files
|
||||
compile → maven-compiler-plugin compiles custom stubs
|
||||
↳ target/classes/ ← custom stubs OVERWRITE SDK versions
|
||||
...
|
||||
package → maven-jar-plugin creates androidcompat-1.0.0.jar
|
||||
↳ contains merged Android API
|
||||
|
||||
[MODULE: aniyomibridge-core]
|
||||
validate → check pom
|
||||
...
|
||||
compile → compile core sources (can reference androidcompat classes)
|
||||
...
|
||||
package → maven-jar-plugin creates thin JAR
|
||||
→ maven-shade-plugin creates fat JAR
|
||||
↳ unpacks androidcompat + all deps
|
||||
↳ filters: include ALL androidcompat, exclude Main.class
|
||||
↳ outputs aniyomibridge-core-1.0.0.jar (~90MB)
|
||||
```
|
||||
|
||||
### Why This Order Matters
|
||||
|
||||
1. **`androidcompat` must build first** — `aniyomibridge-core` declares it as a dependency, so Maven enforces this order automatically.
|
||||
|
||||
2. **`generate-resources` must happen before `process-resources`** — You can't unpack the JAR until it exists. The download script creates it during `generate-resources`, then Ant unpacks it during `process-resources`.
|
||||
|
||||
3. **Unpacking must happen before `compile`** — The compiler needs to see the Android SDK classes to resolve imports in your custom stubs. If `maven-antrun-plugin` ran after `compile`, compilation would fail with "cannot find symbol" for Android classes.
|
||||
|
||||
4. **Custom stubs overwrite SDK classes in `target/classes/`** — This is by design. The compiler writes to the same directory that Ant unpacked into, so your `Context.java` overwrites the SDK's `Context.class`.
|
||||
|
||||
5. **`minimizeJar` + filter is critical** — Without the shade filter for `androidcompat`, Maven Shade would see that `aniyomibridge-core` never directly references `android.graphics.Bitmap` (extensions load it via reflection/ClassLoader), so it would strip it out. The filter forces inclusion of the entire merged Android API.
|
||||
|
||||
## Key Technologies
|
||||
|
||||
| Technology | Purpose |
|
||||
|-----------|---------|
|
||||
| **Android SDK JAR (patched)** | Base Android API classes |
|
||||
| **dex2jar** | Converts Android APK DEX → JAR |
|
||||
| **HtmlUnit / JavaFX WebView** | Desktop WebView implementation |
|
||||
| **OkHttp + DoH** | HTTP client for extensions |
|
||||
| **Kotlin Coroutines** | Async operations |
|
||||
| **kotlinx-serialization-json** | JSON handling |
|
||||
| **Gson** | JSON preference storage |
|
||||
| **ByteBuddy** | Runtime bytecode patching |
|
||||
| **Rhino / GraalVM JS** | JavaScript execution |
|
||||
|
||||
## Build Details
|
||||
|
||||
- **Java Version**: 17 (source and target)
|
||||
- **Kotlin Version**: 2.1.0
|
||||
- **Build Tool**: Maven (multi-module)
|
||||
- **Packaging**: Shade plugin creates minimized fat JAR
|
||||
|
||||
## Development Scripts
|
||||
|
||||
| Script | Purpose |
|
||||
|--------|---------|
|
||||
| `generate-new-core-linux.sh` | Build + copy JAR to Flutter app assets (Linux path) |
|
||||
| `generate-new-core-mac.sh` | Build + copy JAR to Flutter app assets (Mac path) |
|
||||
| `androidcompat/scripts/get-android.sh` | Download and patch Android SDK JAR |
|
||||
|
||||
Both build scripts copy the output to a sibling project `k3vinb5_aniyomi_bridge/assets/`.
|
||||
|
||||
## IntelliJ IDEA Setup
|
||||
|
||||
See [`androidcompat/README.md`](androidcompat/README.md) for detailed IntelliJ setup instructions, including how to get code navigation working for the Android SDK stubs.
|
||||
|
||||
Quick version:
|
||||
1. Run `mvn clean compile -pl androidcompat` once to download the SDK
|
||||
2. Right-click `androidcompat/pom.xml` → **Maven** → **Reload Project**
|
||||
3. Ctrl+Click on Android classes to navigate between SDK stubs and custom implementations
|
||||
|
||||
## Adding New Android Stubs
|
||||
|
||||
When an extension requires an Android class that doesn't exist or crashes:
|
||||
|
||||
1. **Identify** which class needs a desktop implementation
|
||||
2. **Create** the stub in `androidcompat/src/main/java/android/<package>/`
|
||||
3. **Add** the class path to `scripts/get-android.sh` in the `CUSTOM_CLASSES` array
|
||||
4. **Rebuild** with `mvn clean compile -pl androidcompat`
|
||||
|
||||
See [`androidcompat/README.md`](androidcompat/README.md) for more details on the three options: minimal stub, full desktop implementation, or SDK class.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### `ClassNotFoundException` for Android classes
|
||||
- Check if the class is in the downloaded `android.jar`
|
||||
- If not, create a stub in `src/main/java/android/...`
|
||||
- Add the class to `CUSTOM_CLASSES` in `get-android.sh`
|
||||
|
||||
### `MethodNotFoundError`
|
||||
- The Android SDK version might be too old
|
||||
- Update `ANDROID_SDK_VERSION` in `get-android.sh`
|
||||
- Or create a custom stub with the required method
|
||||
|
||||
### Build fails with "cannot find symbol android.***"
|
||||
- The patched `android.jar` hasn't been unpacked yet
|
||||
- Run `mvn clean compile -pl androidcompat` first
|
||||
- Check that `androidcompat/target/classes/` contains `.class` files
|
||||
|
||||
## References
|
||||
|
||||
- [Suwayomi's AndroidCompat](https://github.com/Suwayomi/Suwayomi-Server/tree/master/AndroidCompat) — Inspiration for the hybrid stub approach
|
||||
- [Sable/android-platforms](https://github.com/Sable/android-platforms) — Android SDK JAR source
|
||||
- [dex2jar](https://github.com/pxb1988/dex2jar) — APK to JAR conversion
|
||||
- [Android SDK Reference](https://developer.android.com/reference/)
|
||||
@@ -87,6 +87,55 @@ The androidcompat module is automatically included as a dependency in the core m
|
||||
3. Compiles custom stubs alongside the patched JAR
|
||||
4. Packages everything into the final JAR
|
||||
|
||||
## IntelliJ IDEA Setup (Code Navigation)
|
||||
|
||||
The stripped `android.jar` (SDK classes minus our stubs) is added as a **system dependency** in `pom.xml`. This lets IntelliJ index it so you can navigate Android SDK source code with Ctrl+Click.
|
||||
|
||||
### First-Time Setup
|
||||
|
||||
1. **Download the JAR** (one-time):
|
||||
```bash
|
||||
cd androidcompat
|
||||
./scripts/get-android.sh
|
||||
```
|
||||
Or just run a build:
|
||||
```bash
|
||||
mvn clean compile -pl androidcompat
|
||||
```
|
||||
|
||||
2. **Reload the Maven project** in IntelliJ:
|
||||
- Right-click `androidcompat/pom.xml` → **Maven** → **Reload Project**
|
||||
- Or press `Ctrl+Shift+O` (Linux/Windows) / `Cmd+Shift+O` (Mac)
|
||||
|
||||
3. **Verify it's working**:
|
||||
- Open `androidcompat/src/main/java/android/content/Context.java`
|
||||
- Press `Ctrl+B` on `ApplicationInfo` (or any SDK class not in our stubs)
|
||||
- IntelliJ should decompile and show the SDK source
|
||||
|
||||
### What You'll See
|
||||
|
||||
In the **Project Structure** (`Ctrl+Alt+Shift+S`) → **Libraries**, you should see:
|
||||
```
|
||||
Maven: com.google.android:android-sdk-stripped:34
|
||||
└── androidcompat/target/android.jar
|
||||
```
|
||||
|
||||
This JAR contains **only SDK classes we haven't stubbed** — so when you navigate to `android.app.Activity`, you see the real Android implementation, but when you navigate to `android.content.Context`, you see **our stub**.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
**"Library not found" or red text in pom.xml:**
|
||||
- The JAR hasn't been downloaded yet. Run `./scripts/get-android.sh` or `mvn clean compile`.
|
||||
|
||||
**"Cannot resolve symbol" for Android classes:**
|
||||
- Reload the Maven project: right-click `pom.xml` → **Maven** → **Reload Project**
|
||||
- Or: **File** → **Invalidate Caches** → **Invalidate and Restart**
|
||||
|
||||
**Want to see our stubs instead of SDK classes?**
|
||||
- Our stubs are regular source files in `src/main/java/android/...`
|
||||
- If IntelliJ shows the decompiled SDK version, it means that class is **not in our stubs** (which is useful info!)
|
||||
- To stub it, create the class in `src/main/java/android/<package>/` and add it to `get-android.sh`
|
||||
|
||||
### Skipping the Download
|
||||
|
||||
If you already have `android.jar` downloaded or want to skip the download:
|
||||
|
||||
@@ -68,14 +68,14 @@
|
||||
<groupId>org.graalvm.polyglot</groupId>
|
||||
<artifactId>polyglot</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.graalvm.js</groupId>
|
||||
<artifactId>js-scriptengine</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.graalvm.js</groupId>
|
||||
<artifactId>js-language</artifactId>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.graalvm.js</groupId>-->
|
||||
<!-- <artifactId>js-scriptengine</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.graalvm.js</groupId>-->
|
||||
<!-- <artifactId>js-language</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<!-- RxJava -->
|
||||
<dependency>
|
||||
@@ -88,6 +88,24 @@
|
||||
<artifactId>rxrelay</artifactId>
|
||||
<version>1.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
Android SDK JAR (stripped - only SDK classes we don't stub).
|
||||
Added as a system dependency so IntelliJ IDEA indexes it for
|
||||
code navigation and completion.
|
||||
|
||||
NOTE: The JAR is downloaded during `mvn clean compile` via the
|
||||
get-android.sh script. If IntelliJ shows it as missing, run:
|
||||
cd androidcompat && ./scripts/get-android.sh
|
||||
Then right-click pom.xml → Maven → Reload Project.
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>com.google.android</groupId>
|
||||
<artifactId>android-sdk-stripped</artifactId>
|
||||
<version>${android.sdk.version}</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.build.directory}/android.jar</systemPath>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -31,8 +31,6 @@ CUSTOM_CLASSES=(
|
||||
"android/os/Build.class"
|
||||
"android/os/Environment.class"
|
||||
"android/os/Environment\$*.class"
|
||||
"android/os/Bundle.class"
|
||||
"android/os/Bundle\$*.class"
|
||||
"android/graphics/Bitmap.class"
|
||||
"android/graphics/Bitmap\$*.class"
|
||||
"android/graphics/Canvas.class"
|
||||
@@ -52,6 +50,70 @@ CUSTOM_CLASSES=(
|
||||
"android/util/Log.class"
|
||||
"android/util/Base64.class"
|
||||
"android/annotation/SuppressLint.class"
|
||||
"android/content/pm/PackageManager.class"
|
||||
"android/content/pm/PackageManager\$*.class"
|
||||
"android/content/res/AssetManager.class"
|
||||
"android/content/res/AssetManager\$*.class"
|
||||
"android/content/res/Resources.class"
|
||||
"android/content/res/Resources\$*.class"
|
||||
"android/content/ContentResolver.class"
|
||||
"android/content/ContentResolver\$*.class"
|
||||
"android/view/Display.class"
|
||||
"android/view/Display\$*.class"
|
||||
"android/location/LocationManager.class"
|
||||
"android/location/LocationManager\$*.class"
|
||||
"android/net/ConnectivityManager.class"
|
||||
"android/net/ConnectivityManager\$*.class"
|
||||
"android/app/ActivityManager.class"
|
||||
"android/app/ActivityManager\$*.class"
|
||||
"android/app/AlarmManager.class"
|
||||
"android/app/AlarmManager\$*.class"
|
||||
"android/app/NotificationManager.class"
|
||||
"android/app/NotificationManager\$*.class"
|
||||
"android/app/SearchManager.class"
|
||||
"android/app/SearchManager\$*.class"
|
||||
"android/app/KeyguardManager.class"
|
||||
"android/app/KeyguardManager\$*.class"
|
||||
"android/app/UiModeManager.class"
|
||||
"android/app/UiModeManager\$*.class"
|
||||
"android/app/DownloadManager.class"
|
||||
"android/app/DownloadManager\$*.class"
|
||||
"android/os/PowerManager.class"
|
||||
"android/os/PowerManager\$*.class"
|
||||
"android/os/Vibrator.class"
|
||||
"android/os/BatteryManager.class"
|
||||
"android/os/BatteryManager\$*.class"
|
||||
"android/media/AudioManager.class"
|
||||
"android/media/AudioManager\$*.class"
|
||||
"android/telephony/TelephonyManager.class"
|
||||
"android/telephony/TelephonyManager\$*.class"
|
||||
"android/content/ClipboardManager.class"
|
||||
"android/view/WindowManager.class"
|
||||
"android/view/LayoutInflater.class"
|
||||
"android/view/inputmethod/InputMethodManager.class"
|
||||
"android/hardware/display/DisplayManager.class"
|
||||
"android/hardware/display/DisplayManager\$*.class"
|
||||
"android/hardware/SensorManager.class"
|
||||
"android/hardware/SensorManager\$*.class"
|
||||
"android/os/storage/StorageManager.class"
|
||||
"android/os/storage/StorageManager\$*.class"
|
||||
"android/net/wifi/WifiManager.class"
|
||||
"android/net/wifi/WifiManager\$*.class"
|
||||
"android/net/wifi/p2p/WifiP2pManager.class"
|
||||
"android/net/wifi/p2p/WifiP2pManager\$*.class"
|
||||
"android/bluetooth/BluetoothManager.class"
|
||||
"android/accounts/AccountManager.class"
|
||||
"android/accounts/AccountManager\$*.class"
|
||||
"android/appwidget/AppWidgetManager.class"
|
||||
"android/appwidget/AppWidgetManager\$*.class"
|
||||
"android/nfc/NfcManager.class"
|
||||
"android/content/pm/ShortcutManager.class"
|
||||
"android/view/accessibility/AccessibilityManager.class"
|
||||
"android/view/accessibility/AccessibilityManager\$*.class"
|
||||
"android/app/job/JobScheduler.class"
|
||||
"android/app/job/JobScheduler\$*.class"
|
||||
"android/app/admin/DevicePolicyManager.class"
|
||||
"android/app/admin/DevicePolicyManager\$*.class"
|
||||
)
|
||||
|
||||
echo "=== Android SDK Download and Patch Script ==="
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package android.accounts;
|
||||
|
||||
/**
|
||||
* Minimal AccountManager stub for desktop JVM.
|
||||
*/
|
||||
public class AccountManager {
|
||||
|
||||
public AccountManager() {
|
||||
}
|
||||
|
||||
public android.accounts.Account[] getAccounts() {
|
||||
return new android.accounts.Account[0];
|
||||
}
|
||||
|
||||
public android.accounts.Account[] getAccountsByType(String type) {
|
||||
return new android.accounts.Account[0];
|
||||
}
|
||||
|
||||
public android.accounts.Account getAccountsByTypeAndFeatures(String type, String[] features, android.accounts.AccountManagerCallback<android.accounts.Account[]> callback, android.os.Handler handler) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public java.lang.String getUserData(android.accounts.Account account, String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public java.lang.String getPassword(android.accounts.Account account) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public java.lang.String peekAuthToken(android.accounts.Account account, String authTokenType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setUserData(android.accounts.Account account, String key, String value) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void addAccountExplicitly(android.accounts.Account account, String password, android.os.Bundle userdata) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void removeAccount(android.accounts.Account account, android.accounts.AccountManagerCallback<android.os.Bundle> callback, android.os.Handler handler) {
|
||||
// No-op on desktop
|
||||
}
|
||||
}
|
||||
44
androidcompat/src/main/java/android/app/ActivityManager.java
Normal file
44
androidcompat/src/main/java/android/app/ActivityManager.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package android.app;
|
||||
|
||||
/**
|
||||
* Minimal ActivityManager stub for desktop JVM.
|
||||
*/
|
||||
public class ActivityManager {
|
||||
|
||||
public ActivityManager() {
|
||||
}
|
||||
|
||||
public static boolean isUserAMonkey() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isRunningInTestHarness() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public android.app.ActivityManager.MemoryInfo getMemoryInfo(android.app.ActivityManager.MemoryInfo outInfo) {
|
||||
if (outInfo == null) {
|
||||
outInfo = new android.app.ActivityManager.MemoryInfo();
|
||||
}
|
||||
outInfo.availMem = Runtime.getRuntime().freeMemory();
|
||||
outInfo.totalMem = Runtime.getRuntime().totalMemory();
|
||||
outInfo.threshold = 0;
|
||||
outInfo.lowMemory = false;
|
||||
return outInfo;
|
||||
}
|
||||
|
||||
public int getMemoryClass() {
|
||||
return 256;
|
||||
}
|
||||
|
||||
public int getLargeMemoryClass() {
|
||||
return 512;
|
||||
}
|
||||
|
||||
public static class MemoryInfo {
|
||||
public long availMem;
|
||||
public long totalMem;
|
||||
public long threshold;
|
||||
public boolean lowMemory;
|
||||
}
|
||||
}
|
||||
51
androidcompat/src/main/java/android/app/AlarmManager.java
Normal file
51
androidcompat/src/main/java/android/app/AlarmManager.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package android.app;
|
||||
|
||||
/**
|
||||
* Minimal AlarmManager stub for desktop JVM.
|
||||
*/
|
||||
public class AlarmManager {
|
||||
|
||||
public static final int RTC_WAKEUP = 0;
|
||||
public static final int RTC = 1;
|
||||
public static final int ELAPSED_REALTIME_WAKEUP = 2;
|
||||
public static final int ELAPSED_REALTIME = 3;
|
||||
|
||||
public AlarmManager() {
|
||||
}
|
||||
|
||||
public void set(int type, long triggerAtMillis, android.app.PendingIntent operation) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void setExact(int type, long triggerAtMillis, android.app.PendingIntent operation) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void setRepeating(int type, long triggerAtMillis, long intervalMillis, android.app.PendingIntent operation) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void setInexactRepeating(int type, long triggerAtMillis, long intervalMillis, android.app.PendingIntent operation) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void cancel(android.app.PendingIntent operation) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void cancel(android.app.AlarmManager.OnAlarmListener listener) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void setTime(long millis) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void setTimeZone(String timeZone) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public interface OnAlarmListener {
|
||||
void onAlarm();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package android.app;
|
||||
|
||||
import android.content.ApplicationContext;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferencesImpl;
|
||||
@@ -14,15 +15,20 @@ public class Application {
|
||||
|
||||
private final Map<String, SharedPreferences> prefs = new HashMap<>();
|
||||
private final Map<Long, PreferenceScreen> preferenceScreens = new HashMap<>();
|
||||
private final Context context = new Context();
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
private Application() {
|
||||
this.applicationContext = new ApplicationContext(this);
|
||||
}
|
||||
|
||||
public static Application getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public Context getApplicationContext() {
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
public SharedPreferences getSharedPreferences(String name, int mode) {
|
||||
if (prefs.containsKey(name + mode)) {
|
||||
return prefs.get(name + mode);
|
||||
@@ -36,7 +42,7 @@ public class Application {
|
||||
if (preferenceScreens.containsKey(id)) {
|
||||
return preferenceScreens.get(id);
|
||||
}
|
||||
PreferenceScreen screen = new PreferenceScreen(context, this.getSharedPreferences("source_" + id, Context.MODE_PRIVATE));
|
||||
PreferenceScreen screen = new PreferenceScreen(applicationContext, this.getSharedPreferences("source_" + id, Context.MODE_PRIVATE));
|
||||
preferenceScreens.put(id, screen);
|
||||
return screen;
|
||||
}
|
||||
|
||||
95
androidcompat/src/main/java/android/app/DownloadManager.java
Normal file
95
androidcompat/src/main/java/android/app/DownloadManager.java
Normal file
@@ -0,0 +1,95 @@
|
||||
package android.app;
|
||||
|
||||
/**
|
||||
* Minimal DownloadManager stub for desktop JVM.
|
||||
*/
|
||||
public class DownloadManager {
|
||||
|
||||
public static final String COLUMN_ID = "_id";
|
||||
public static final String COLUMN_TITLE = "title";
|
||||
public static final String COLUMN_DESCRIPTION = "description";
|
||||
public static final String COLUMN_URI = "uri";
|
||||
public static final String COLUMN_STATUS = "status";
|
||||
public static final String COLUMN_REASON = "reason";
|
||||
public static final String COLUMN_TOTAL_SIZE_BYTES = "total_size";
|
||||
public static final String COLUMN_BYTES_DOWNLOADED_SO_FAR = "bytes_so_far";
|
||||
public static final String COLUMN_LAST_MODIFIED_TIMESTAMP = "last_modified_timestamp";
|
||||
public static final String COLUMN_MEDIA_TYPE = "media_type";
|
||||
public static final String COLUMN_LOCAL_URI = "local_uri";
|
||||
|
||||
public static final int STATUS_PENDING = 1;
|
||||
public static final int STATUS_RUNNING = 2;
|
||||
public static final int STATUS_PAUSED = 4;
|
||||
public static final int STATUS_SUCCESSFUL = 8;
|
||||
public static final int STATUS_FAILED = 16;
|
||||
|
||||
public DownloadManager() {
|
||||
}
|
||||
|
||||
public long enqueue(android.app.DownloadManager.Request request) {
|
||||
System.err.println("WARNING: DownloadManager.enqueue() called on desktop - not supported");
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int remove(long... ids) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public android.database.Cursor query(android.app.DownloadManager.Query query) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public android.os.ParcelFileDescriptor openDownloadedFile(long id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public android.net.Uri getUriForDownloadedFile(long id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public java.lang.String getMimeTypeForDownloadedFile(long id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static class Request {
|
||||
public Request(android.net.Uri uri) {
|
||||
}
|
||||
|
||||
public android.app.DownloadManager.Request setDestinationUri(android.net.Uri uri) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public android.app.DownloadManager.Request setDestinationInExternalPublicDir(String dirType, String subPath) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public android.app.DownloadManager.Request setTitle(CharSequence title) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public android.app.DownloadManager.Request setDescription(CharSequence description) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public android.app.DownloadManager.Request setAllowedNetworkTypes(int flags) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public android.app.DownloadManager.Request addRequestHeader(String header, String value) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Query {
|
||||
public Query() {
|
||||
}
|
||||
|
||||
public android.app.DownloadManager.Query setFilterById(long... ids) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public android.app.DownloadManager.Query setFilterByStatus(int flags) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
54
androidcompat/src/main/java/android/app/KeyguardManager.java
Normal file
54
androidcompat/src/main/java/android/app/KeyguardManager.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package android.app;
|
||||
|
||||
/**
|
||||
* Minimal KeyguardManager stub for desktop JVM.
|
||||
*/
|
||||
public class KeyguardManager {
|
||||
|
||||
public KeyguardManager() {
|
||||
}
|
||||
|
||||
public boolean inKeyguardRestrictedInputMode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isKeyguardLocked() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isKeyguardSecure() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isDeviceLocked() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isDeviceSecure() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public KeyguardManager.KeyguardLock newKeyguardLock(String tag) {
|
||||
return new KeyguardManager.KeyguardLock();
|
||||
}
|
||||
|
||||
public void requestDismissKeyguard(android.app.Activity activity, KeyguardManager.KeyguardDismissCallback callback) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public static class KeyguardLock {
|
||||
public void disableKeyguard() {
|
||||
// No-op
|
||||
}
|
||||
|
||||
public void reenableKeyguard() {
|
||||
// No-op
|
||||
}
|
||||
}
|
||||
|
||||
public static class KeyguardDismissCallback {
|
||||
public void onDismissError() {}
|
||||
public void onDismissSucceeded() {}
|
||||
public void onDismissCancelled() {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package android.app;
|
||||
|
||||
/**
|
||||
* Minimal NotificationManager stub for desktop JVM.
|
||||
*/
|
||||
public class NotificationManager {
|
||||
|
||||
public NotificationManager() {
|
||||
}
|
||||
|
||||
public void notify(int id, android.app.Notification notification) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void notify(String tag, int id, android.app.Notification notification) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void cancel(int id) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void cancel(String tag, int id) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void cancelAll() {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void createNotificationChannel(android.app.NotificationChannel channel) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void createNotificationChannels(java.util.List<android.app.NotificationChannel> channels) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void deleteNotificationChannel(String channelId) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public java.util.List<android.app.NotificationChannel> getNotificationChannels() {
|
||||
return new java.util.ArrayList<>();
|
||||
}
|
||||
|
||||
public android.app.NotificationChannel getNotificationChannel(String channelId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean areNotificationsEnabled() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
32
androidcompat/src/main/java/android/app/SearchManager.java
Normal file
32
androidcompat/src/main/java/android/app/SearchManager.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package android.app;
|
||||
|
||||
/**
|
||||
* Minimal SearchManager stub for desktop JVM.
|
||||
*/
|
||||
public class SearchManager {
|
||||
|
||||
public static final String QUERY = "query";
|
||||
public static final String APP_DATA = "app_data";
|
||||
public static final String EXTRA_DATA_KEY = "intent_extra_data_key";
|
||||
public static final String ACTION_KEY = "action_key";
|
||||
public static final String EXTRA_SELECT_QUERY = "select_query";
|
||||
|
||||
public SearchManager() {
|
||||
}
|
||||
|
||||
public void startSearch(String initialQuery, boolean selectInitialQuery, android.content.ComponentName launchActivity, android.os.Bundle appSearchData, boolean globalSearch) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void triggerSearch(String query, android.content.ComponentName launchActivity, android.os.Bundle appSearchData) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void stopSearch() {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public android.content.Intent getSearchIntent(android.content.ComponentName launchActivity, android.os.Bundle appSearchData, boolean globalSearch) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
35
androidcompat/src/main/java/android/app/UiModeManager.java
Normal file
35
androidcompat/src/main/java/android/app/UiModeManager.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package android.app;
|
||||
|
||||
/**
|
||||
* Minimal UiModeManager stub for desktop JVM.
|
||||
*/
|
||||
public class UiModeManager {
|
||||
|
||||
public static final int MODE_NIGHT_AUTO = 0;
|
||||
public static final int MODE_NIGHT_NO = 1;
|
||||
public static final int MODE_NIGHT_YES = 2;
|
||||
public static final int MODE_NIGHT_CUSTOM = 3;
|
||||
|
||||
public UiModeManager() {
|
||||
}
|
||||
|
||||
public void enableCarMode(int flags) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void disableCarMode(int flags) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public int getCurrentModeType() {
|
||||
return 1; // UI_MODE_TYPE_NORMAL
|
||||
}
|
||||
|
||||
public void setNightMode(int mode) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public int getNightMode() {
|
||||
return MODE_NIGHT_NO;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package android.app.admin;
|
||||
|
||||
/**
|
||||
* Minimal DevicePolicyManager stub for desktop JVM.
|
||||
*/
|
||||
public class DevicePolicyManager {
|
||||
|
||||
public DevicePolicyManager() {
|
||||
}
|
||||
|
||||
public boolean isAdminActive(android.content.ComponentName admin) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public java.util.List<android.content.ComponentName> getActiveAdmins() {
|
||||
return new java.util.ArrayList<>();
|
||||
}
|
||||
|
||||
public void removeActiveAdmin(android.content.ComponentName admin) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public boolean isDeviceOwnerApp(String packageName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isProfileOwnerApp(String packageName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setCameraDisabled(android.content.ComponentName admin, boolean disabled) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public boolean getCameraDisabled(android.content.ComponentName admin) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setStorageEncryption(android.content.ComponentName admin, boolean encrypt) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public boolean getStorageEncryption(android.content.ComponentName admin) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getStorageEncryptionStatus() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package android.app.job;
|
||||
|
||||
/**
|
||||
* Minimal JobScheduler stub for desktop JVM.
|
||||
*/
|
||||
public class JobScheduler {
|
||||
|
||||
public static final int RESULT_SUCCESS = 0;
|
||||
public static final int RESULT_FAILURE = 1;
|
||||
|
||||
public JobScheduler() {
|
||||
}
|
||||
|
||||
public int schedule(android.app.job.JobInfo job) {
|
||||
System.err.println("WARNING: JobScheduler.schedule() called on desktop - not supported");
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
public void cancel(int jobId) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void cancelAll() {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public java.util.List<android.app.job.JobInfo> getAllPendingJobs() {
|
||||
return new java.util.ArrayList<>();
|
||||
}
|
||||
|
||||
public android.app.job.JobInfo getPendingJob(int jobId) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package android.appwidget;
|
||||
|
||||
/**
|
||||
* Minimal AppWidgetManager stub for desktop JVM.
|
||||
*/
|
||||
public class AppWidgetManager {
|
||||
|
||||
public AppWidgetManager() {
|
||||
}
|
||||
|
||||
public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders() {
|
||||
return new java.util.ArrayList<>();
|
||||
}
|
||||
|
||||
public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForPackage(String packageName, android.os.UserHandle profile) {
|
||||
return new java.util.ArrayList<>();
|
||||
}
|
||||
|
||||
public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void updateAppWidget(int appWidgetId, android.widget.RemoteViews views) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void updateAppWidget(int[] appWidgetIds, android.widget.RemoteViews views) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void bindAppWidgetIdIfAllowed(int appWidgetId, android.content.ComponentName provider) {
|
||||
// No-op on desktop
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package android.bluetooth;
|
||||
|
||||
/**
|
||||
* Minimal BluetoothManager stub for desktop JVM.
|
||||
*/
|
||||
public class BluetoothManager {
|
||||
|
||||
public BluetoothManager() {
|
||||
}
|
||||
|
||||
public android.bluetooth.BluetoothAdapter getAdapter() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
package android.content;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.AssetManager;
|
||||
import android.content.res.Resources;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.Looper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
/**
|
||||
* Concrete Context implementation for the AniyomiBridge application on desktop JVM.
|
||||
*/
|
||||
public class ApplicationContext extends Context {
|
||||
|
||||
private final Application application;
|
||||
private final PackageManager packageManager;
|
||||
private final AssetManager assetManager;
|
||||
private final Resources resources;
|
||||
private final ContentResolver contentResolver;
|
||||
private final File baseDir;
|
||||
private final File filesDir;
|
||||
private final File cacheDir;
|
||||
private final File externalFilesDir;
|
||||
private final File externalCacheDir;
|
||||
private final File databaseDir;
|
||||
private final File sharedPrefsDir;
|
||||
private final Looper mainLooper;
|
||||
|
||||
public ApplicationContext(Application application) {
|
||||
this.application = application;
|
||||
this.packageManager = new PackageManager();
|
||||
this.assetManager = new AssetManager();
|
||||
this.resources = new Resources();
|
||||
this.contentResolver = new ContentResolver();
|
||||
this.mainLooper = Looper.getMainLooper();
|
||||
|
||||
// Setup directories
|
||||
String basePath = System.getProperty("user.home") + File.separator + ".aniyomibridge";
|
||||
this.baseDir = ensureDir(new File(basePath));
|
||||
this.filesDir = ensureDir(new File(baseDir, "files"));
|
||||
this.cacheDir = ensureDir(new File(baseDir, "cache"));
|
||||
this.externalFilesDir = ensureDir(new File(baseDir, "external_files"));
|
||||
this.externalCacheDir = ensureDir(new File(baseDir, "external_cache"));
|
||||
this.databaseDir = ensureDir(new File(baseDir, "databases"));
|
||||
this.sharedPrefsDir = ensureDir(new File(baseDir, "shared_prefs"));
|
||||
}
|
||||
|
||||
private static File ensureDir(File dir) {
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AssetManager getAssets() {
|
||||
return assetManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resources getResources() {
|
||||
return resources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackageManager getPackageManager() {
|
||||
return packageManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentResolver getContentResolver() {
|
||||
return contentResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Looper getMainLooper() {
|
||||
return mainLooper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getApplicationContext() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTheme(int resid) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resources.Theme getTheme() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader getClassLoader() {
|
||||
return Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPackageName() {
|
||||
return "eu.kanade.tachiyomi";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplicationInfo getApplicationInfo() {
|
||||
ApplicationInfo info = new ApplicationInfo();
|
||||
info.packageName = getPackageName();
|
||||
info.targetSdkVersion = 34;
|
||||
return info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPackageResourcePath() {
|
||||
return baseDir.getAbsolutePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPackageCodePath() {
|
||||
return baseDir.getAbsolutePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SharedPreferences getSharedPreferences(String name, int mode) {
|
||||
return application.getSharedPreferences(name, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteSharedPreferences(String name) {
|
||||
File prefsFile = new File(sharedPrefsDir, name + ".xml");
|
||||
return prefsFile.delete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileInputStream openFileInput(String name) throws FileNotFoundException {
|
||||
return new FileInputStream(new File(filesDir, name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileOutputStream openFileOutput(String name, int mode) throws FileNotFoundException {
|
||||
File file = new File(filesDir, name);
|
||||
if ((mode & MODE_APPEND) == 0) {
|
||||
// Truncate mode - delete existing file
|
||||
file.delete();
|
||||
}
|
||||
return new FileOutputStream(file, (mode & MODE_APPEND) != 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteFile(String name) {
|
||||
return new File(filesDir, name).delete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getFileStreamPath(String name) {
|
||||
return new File(filesDir, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDataDir() {
|
||||
return baseDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getFilesDir() {
|
||||
return filesDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getNoBackupFilesDir() {
|
||||
return filesDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getExternalFilesDir(String type) {
|
||||
if (type != null) {
|
||||
return ensureDir(new File(externalFilesDir, type));
|
||||
}
|
||||
return externalFilesDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File[] getExternalFilesDirs(String type) {
|
||||
return new File[] { getExternalFilesDir(type) };
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getObbDir() {
|
||||
return ensureDir(new File(baseDir, "obb"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public File[] getObbDirs() {
|
||||
return new File[] { getObbDir() };
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getCacheDir() {
|
||||
return cacheDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getCodeCacheDir() {
|
||||
return cacheDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getExternalCacheDir() {
|
||||
return externalCacheDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File[] getExternalCacheDirs() {
|
||||
return new File[] { externalCacheDir };
|
||||
}
|
||||
|
||||
@Override
|
||||
public File[] getExternalMediaDirs() {
|
||||
return new File[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] fileList() {
|
||||
return filesDir.list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDir(String name, int mode) {
|
||||
return ensureDir(new File(filesDir, name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getSharedPreferencesPath(String name) {
|
||||
return new File(sharedPrefsDir, name + ".xml");
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDatabasePath(String name) {
|
||||
return new File(databaseDir, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveDatabaseFrom(Context sourceContext, String name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteDatabase(String name) {
|
||||
return new File(databaseDir, name).delete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] databaseList() {
|
||||
return databaseDir.list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSystemService(String name) {
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
return switch (name) {
|
||||
case CONNECTIVITY_SERVICE -> new ConnectivityManager();
|
||||
case WINDOW_SERVICE -> new android.view.WindowManager();
|
||||
case ACTIVITY_SERVICE -> new android.app.ActivityManager();
|
||||
case POWER_SERVICE -> new android.os.PowerManager();
|
||||
case ALARM_SERVICE -> new android.app.AlarmManager();
|
||||
case NOTIFICATION_SERVICE -> new android.app.NotificationManager();
|
||||
case LOCATION_SERVICE -> new android.location.LocationManager();
|
||||
case TELEPHONY_SERVICE -> new android.telephony.TelephonyManager();
|
||||
case AUDIO_SERVICE -> new android.media.AudioManager();
|
||||
case CLIPBOARD_SERVICE -> new ClipboardManager();
|
||||
case INPUT_METHOD_SERVICE -> new android.view.inputmethod.InputMethodManager();
|
||||
case SEARCH_SERVICE -> new android.app.SearchManager();
|
||||
case STORAGE_SERVICE -> new android.os.storage.StorageManager();
|
||||
case WIFI_SERVICE -> new android.net.wifi.WifiManager();
|
||||
case DISPLAY_SERVICE -> new android.hardware.display.DisplayManager();
|
||||
case SENSOR_SERVICE -> new android.hardware.SensorManager();
|
||||
case LAYOUT_INFLATER_SERVICE -> new android.view.LayoutInflater();
|
||||
case KEYGUARD_SERVICE -> new android.app.KeyguardManager();
|
||||
case VIBRATOR_SERVICE -> new android.os.Vibrator();
|
||||
case UI_MODE_SERVICE -> new android.app.UiModeManager();
|
||||
case DEVICE_POLICY_SERVICE -> new android.app.admin.DevicePolicyManager();
|
||||
case DOWNLOAD_SERVICE -> new android.app.DownloadManager();
|
||||
case BATTERY_SERVICE -> new android.os.BatteryManager();
|
||||
case BLUETOOTH_SERVICE -> new android.bluetooth.BluetoothManager();
|
||||
case JOB_SCHEDULER_SERVICE -> new android.app.job.JobScheduler();
|
||||
case ACCESSIBILITY_SERVICE -> new android.view.accessibility.AccessibilityManager();
|
||||
case ACCOUNT_SERVICE -> new android.accounts.AccountManager();
|
||||
case APPWIDGET_SERVICE -> new android.appwidget.AppWidgetManager();
|
||||
case NFC_SERVICE -> new android.nfc.NfcManager();
|
||||
case WIFI_P2P_SERVICE -> new android.net.wifi.p2p.WifiP2pManager();
|
||||
case SHORTCUT_SERVICE -> new android.content.pm.ShortcutManager();
|
||||
default -> {
|
||||
System.err.println("WARNING: Unimplemented system service requested: " + name);
|
||||
yield null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package android.content;
|
||||
|
||||
/**
|
||||
* Minimal ClipboardManager stub for desktop JVM.
|
||||
*/
|
||||
public class ClipboardManager {
|
||||
|
||||
public ClipboardManager() {
|
||||
}
|
||||
|
||||
public void setText(CharSequence text) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public CharSequence getText() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public boolean hasText() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setPrimaryClip(android.content.ClipData clip) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public android.content.ClipData getPrimaryClip() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public android.content.ClipDescription getPrimaryClipDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasPrimaryClip() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addPrimaryClipChangedListener(android.content.ClipboardManager.OnPrimaryClipChangedListener what) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void removePrimaryClipChangedListener(android.content.ClipboardManager.OnPrimaryClipChangedListener what) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public interface OnPrimaryClipChangedListener {
|
||||
void onPrimaryClipChanged();
|
||||
}
|
||||
}
|
||||
123
androidcompat/src/main/java/android/content/ContentResolver.java
Normal file
123
androidcompat/src/main/java/android/content/ContentResolver.java
Normal file
@@ -0,0 +1,123 @@
|
||||
package android.content;
|
||||
|
||||
/**
|
||||
* Minimal ContentResolver stub for desktop JVM.
|
||||
*/
|
||||
public class ContentResolver {
|
||||
|
||||
public static final String SYNC_EXTRAS_ACCOUNT = "account";
|
||||
public static final String SYNC_EXTRAS_EXPEDITED = "expedited";
|
||||
public static final String SYNC_EXTRAS_FORCE = "force";
|
||||
public static final String SYNC_EXTRAS_UPLOAD = "upload";
|
||||
public static final String SYNC_EXTRAS_MANUAL = "force";
|
||||
public static final String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = "deletions_override";
|
||||
public static final String SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS = "discard_deletions";
|
||||
public static final String SYNC_EXTRAS_EXPECTED_UPLOAD = "expected_upload";
|
||||
public static final String SYNC_EXTRAS_EXPECTED_DOWNLOAD = "expected_download";
|
||||
public static final String SYNC_EXTRAS_PRIORITY = "priority";
|
||||
public static final String SCHEME_CONTENT = "content";
|
||||
public static final String SCHEME_ANDROID_RESOURCE = "android.resource";
|
||||
public static final String SCHEME_FILE = "file";
|
||||
public static final int SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS = 1;
|
||||
public static final int SYNC_ERROR_AUTHENTICATION = 2;
|
||||
public static final int SYNC_ERROR_IO = 3;
|
||||
public static final int SYNC_ERROR_PARSE = 4;
|
||||
public static final int SYNC_ERROR_CONFLICT = 5;
|
||||
public static final int SYNC_ERROR_TOO_MANY_DELETIONS = 6;
|
||||
public static final int SYNC_ERROR_TOO_MANY_RETRIES = 7;
|
||||
public static final int SYNC_ERROR_INTERNAL = 8;
|
||||
public static final int SYNC_OBSERVER_TYPE_SETTINGS = 1;
|
||||
public static final int SYNC_OBSERVER_TYPE_PENDING = 2;
|
||||
public static final int SYNC_OBSERVER_TYPE_ACTIVE = 4;
|
||||
|
||||
public ContentResolver() {
|
||||
}
|
||||
|
||||
public final String getType(android.net.Uri uri) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String[] getStreamTypes(android.net.Uri uri, String mimeTypeFilter) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final android.database.Cursor query(android.net.Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final android.database.Cursor query(android.net.Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, android.os.CancellationSignal cancellationSignal) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final android.database.Cursor query(android.net.Uri uri, String[] projection, android.os.Bundle queryArgs, android.os.CancellationSignal cancellationSignal) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final android.net.Uri insert(android.net.Uri uri, android.content.ContentValues values) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final int bulkInsert(android.net.Uri uri, android.content.ContentValues[] valuesArray) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public final int delete(android.net.Uri uri, String selection, String[] selectionArgs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public final int update(android.net.Uri uri, android.content.ContentValues values, String selection, String[] selectionArgs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public final android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri uri, String mode) throws java.io.FileNotFoundException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final java.io.InputStream openInputStream(android.net.Uri uri) throws java.io.FileNotFoundException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final java.io.OutputStream openOutputStream(android.net.Uri uri) throws java.io.FileNotFoundException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final java.io.OutputStream openOutputStream(android.net.Uri uri, String mode) throws java.io.FileNotFoundException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final void registerContentObserver(android.net.Uri uri, boolean notifyForDescendants, android.database.ContentObserver observer) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public final void unregisterContentObserver(android.database.ContentObserver observer) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void notifyChange(android.net.Uri uri, android.database.ContentObserver observer) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void notifyChange(android.net.Uri uri, android.database.ContentObserver observer, boolean syncToNetwork) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void takePersistableUriPermission(android.net.Uri uri, int modeFlags) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void releasePersistableUriPermission(android.net.Uri uri, int modeFlags) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public java.util.List<android.content.UriPermission> getPersistedUriPermissions() {
|
||||
return new java.util.ArrayList<>();
|
||||
}
|
||||
|
||||
public static void requestSync(android.accounts.Account account, String authority, android.os.Bundle extras) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public static void cancelSync(android.accounts.Account account, String authority) {
|
||||
// No-op on desktop
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,479 @@
|
||||
package android.content;
|
||||
|
||||
import java.io.File;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.AssetManager;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.Display;
|
||||
|
||||
public class Context {
|
||||
public static final int MODE_PRIVATE = 0;
|
||||
public static File getCacheDir() {
|
||||
return new File(System.getProperty("java.io.tmpdir"));
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
/**
|
||||
* Abstract Context implementation for desktop JVM.
|
||||
* <p>
|
||||
* This is a stub implementation that provides sensible defaults for most methods.
|
||||
* Methods that don't make sense on desktop (like startActivity) log a warning.
|
||||
*/
|
||||
public abstract class Context {
|
||||
|
||||
// File creation modes
|
||||
public static final int MODE_PRIVATE = 0x0000;
|
||||
@Deprecated
|
||||
public static final int MODE_WORLD_READABLE = 0x0001;
|
||||
@Deprecated
|
||||
public static final int MODE_WORLD_WRITEABLE = 0x0002;
|
||||
public static final int MODE_APPEND = 0x8000;
|
||||
public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 0x0008;
|
||||
public static final int MODE_NO_LOCALIZED_COLLATORS = 0x0010;
|
||||
public static final int MODE_MULTI_PROCESS = 0x0004;
|
||||
|
||||
// Service names
|
||||
public static final String CONNECTIVITY_SERVICE = "connectivity";
|
||||
public static final String WINDOW_SERVICE = "window";
|
||||
public static final String ACTIVITY_SERVICE = "activity";
|
||||
public static final String POWER_SERVICE = "power";
|
||||
public static final String ALARM_SERVICE = "alarm";
|
||||
public static final String NOTIFICATION_SERVICE = "notification";
|
||||
public static final String LOCATION_SERVICE = "location";
|
||||
public static final String TELEPHONY_SERVICE = "phone";
|
||||
public static final String AUDIO_SERVICE = "audio";
|
||||
public static final String CLIPBOARD_SERVICE = "clipboard";
|
||||
public static final String INPUT_METHOD_SERVICE = "input_method";
|
||||
public static final String SEARCH_SERVICE = "search";
|
||||
public static final String STORAGE_SERVICE = "storage";
|
||||
public static final String WIFI_SERVICE = "wifi";
|
||||
public static final String DISPLAY_SERVICE = "display";
|
||||
public static final String SENSOR_SERVICE = "sensor";
|
||||
public static final String CAMERA_SERVICE = "camera";
|
||||
public static final String KEYGUARD_SERVICE = "keyguard";
|
||||
public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater";
|
||||
public static final String VIBRATOR_SERVICE = "vibrator";
|
||||
public static final String UI_MODE_SERVICE = "uimode";
|
||||
public static final String DEVICE_POLICY_SERVICE = "device_policy";
|
||||
public static final String DOWNLOAD_SERVICE = "download";
|
||||
public static final String BATTERY_SERVICE = "batterymanager";
|
||||
public static final String JOB_SCHEDULER_SERVICE = "jobscheduler";
|
||||
public static final String ACCESSIBILITY_SERVICE = "accessibility";
|
||||
public static final String ACCOUNT_SERVICE = "account";
|
||||
public static final String APPWIDGET_SERVICE = "appwidget";
|
||||
public static final String BLUETOOTH_SERVICE = "bluetooth";
|
||||
public static final String DROPBOX_SERVICE = "dropbox";
|
||||
public static final String MEDIA_ROUTER_SERVICE = "media_router";
|
||||
public static final String NFC_SERVICE = "nfc";
|
||||
public static final String PRINT_SERVICE = "print";
|
||||
public static final String RESTRICTIONS_SERVICE = "restrictions";
|
||||
public static final String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service";
|
||||
public static final String TELECOM_SERVICE = "telecom";
|
||||
public static final String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
|
||||
public static final String TV_INPUT_SERVICE = "tv_input";
|
||||
public static final String USAGE_STATS_SERVICE = "usagestats";
|
||||
public static final String USB_SERVICE = "usb";
|
||||
public static final String USER_SERVICE = "user";
|
||||
public static final String WALLPAPER_SERVICE = "wallpaper";
|
||||
public static final String SHORTCUT_SERVICE = "shortcut";
|
||||
public static final String COMPANION_DEVICE_SERVICE = "companiondevice";
|
||||
public static final String CROSS_PROFILE_APPS_SERVICE = "crossprofileapps";
|
||||
public static final String SLICE_SERVICE = "slice";
|
||||
public static final String TIME_ZONE_RULES_MANAGER_SERVICE = "timezone";
|
||||
public static final String APP_PREDICTION_SERVICE = "app_prediction";
|
||||
public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "content_capture";
|
||||
public static final String TRANSLATION_MANAGER_SERVICE = "translation";
|
||||
public static final String BLOB_STORE_SERVICE = "blob_store";
|
||||
public static final String FILE_INTEGRITY_SERVICE = "file_integrity";
|
||||
public static final String APP_OPS_SERVICE = "appops";
|
||||
public static final String ROLLBACK_SERVICE = "rollback";
|
||||
public static final String DYNAMIC_SYSTEM_SERVICE = "dynamic_system";
|
||||
public static final String DOMAIN_VERIFICATION_SERVICE = "domain_verification";
|
||||
public static final String GAME_SERVICE = "game";
|
||||
public static final String LOCALE_SERVICE = "locale";
|
||||
public static final String MUSIC_RECOGNITION_SERVICE = "music_recognition";
|
||||
public static final String PEOPLE_SERVICE = "people";
|
||||
public static final String PERFORMANCE_HINT_SERVICE = "performance_hint";
|
||||
public static final String SAFETY_CENTER_SERVICE = "safety_center";
|
||||
public static final String CREDENTIAL_SERVICE = "credential";
|
||||
public static final String SYSTEM_HEALTH_SERVICE = "systemhealth";
|
||||
public static final String UWB_SERVICE = "uwb";
|
||||
public static final String WIFI_AWARE_SERVICE = "wifiaware";
|
||||
public static final String WIFI_P2P_SERVICE = "wifip2p";
|
||||
public static final String WIFI_RTT_RANGING_SERVICE = "wifirtt";
|
||||
public static final String CARRIER_CONFIG_SERVICE = "carrier_config";
|
||||
public static final String EUICC_SERVICE = "euicc";
|
||||
public static final String IPSEC_SERVICE = "ipsec";
|
||||
public static final String MEDIA_SESSION_SERVICE = "media_session";
|
||||
public static final String NETWORK_STATS_SERVICE = "netstats";
|
||||
public static final String NETWORK_POLICY_SERVICE = "netpolicy";
|
||||
public static final String NETWORK_SCORE_SERVICE = "network_score";
|
||||
public static final String OEM_LOCK_SERVICE = "oem_lock";
|
||||
public static final String PERSISTENT_DATA_BLOCK_SERVICE = "persistent_data_block";
|
||||
public static final String RECOVERY_SERVICE = "recovery";
|
||||
public static final String SERVICE_DISCOVERY_SERVICE = "servicediscovery";
|
||||
public static final String SOUND_TRIGGER_SERVICE = "soundtrigger";
|
||||
public static final String STATS_MANAGER_SERVICE = "stats";
|
||||
public static final String STORAGE_STATS_SERVICE = "storagestats";
|
||||
public static final String TRUST_SERVICE = "trust";
|
||||
public static final String VIRTUALIZATION_SERVICE = "virtualization";
|
||||
|
||||
private static final String BASE_DIR = System.getProperty("user.home") + File.separator + ".aniyomibridge";
|
||||
|
||||
// ==================== ABSTRACT METHODS ====================
|
||||
|
||||
public abstract AssetManager getAssets();
|
||||
public abstract Resources getResources();
|
||||
public abstract PackageManager getPackageManager();
|
||||
public abstract ContentResolver getContentResolver();
|
||||
public abstract Looper getMainLooper();
|
||||
public abstract Context getApplicationContext();
|
||||
public abstract void setTheme(int resid);
|
||||
public abstract Resources.Theme getTheme();
|
||||
public abstract ClassLoader getClassLoader();
|
||||
public abstract String getPackageName();
|
||||
public abstract ApplicationInfo getApplicationInfo();
|
||||
public abstract String getPackageResourcePath();
|
||||
public abstract String getPackageCodePath();
|
||||
public abstract SharedPreferences getSharedPreferences(String name, int mode);
|
||||
public abstract boolean moveSharedPreferencesFrom(Context sourceContext, String name);
|
||||
public abstract boolean deleteSharedPreferences(String name);
|
||||
public abstract FileInputStream openFileInput(String name) throws FileNotFoundException;
|
||||
public abstract FileOutputStream openFileOutput(String name, int mode) throws FileNotFoundException;
|
||||
public abstract boolean deleteFile(String name);
|
||||
public abstract File getFileStreamPath(String name);
|
||||
public abstract File getDataDir();
|
||||
public abstract File getFilesDir();
|
||||
public abstract File getNoBackupFilesDir();
|
||||
public abstract File getExternalFilesDir(String type);
|
||||
public abstract File[] getExternalFilesDirs(String type);
|
||||
public abstract File getObbDir();
|
||||
public abstract File[] getObbDirs();
|
||||
public abstract File getCacheDir();
|
||||
public abstract File getCodeCacheDir();
|
||||
public abstract File getExternalCacheDir();
|
||||
public abstract File[] getExternalCacheDirs();
|
||||
public abstract File[] getExternalMediaDirs();
|
||||
public abstract String[] fileList();
|
||||
public abstract File getDir(String name, int mode);
|
||||
public abstract Object getSystemService(String name);
|
||||
|
||||
// ==================== CONCRETE METHODS WITH DEFAULTS ====================
|
||||
|
||||
public static File getCacheDirStatic() {
|
||||
return new File(BASE_DIR, "cache");
|
||||
}
|
||||
public Context() {
|
||||
|
||||
public File getSharedPreferencesPath(String name) {
|
||||
return new File(getFilesDir(), name + ".xml");
|
||||
}
|
||||
|
||||
public File getDatabasePath(String name) {
|
||||
return new File(getFilesDir(), name);
|
||||
}
|
||||
|
||||
public boolean moveDatabaseFrom(Context sourceContext, String name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean deleteDatabase(String name) {
|
||||
return new File(getFilesDir(), name).delete();
|
||||
}
|
||||
|
||||
public String[] databaseList() {
|
||||
return getFilesDir().list();
|
||||
}
|
||||
|
||||
public void registerComponentCallbacks(android.content.ComponentCallbacks callback) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void unregisterComponentCallbacks(android.content.ComponentCallbacks callback) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
// Activity/Intent methods (no-op on desktop)
|
||||
public void startActivity(android.content.Intent intent) {
|
||||
System.err.println("WARNING: Context.startActivity() called on desktop - not supported");
|
||||
}
|
||||
|
||||
public void startActivity(android.content.Intent intent, Bundle options) {
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
public void startActivities(android.content.Intent[] intents) {
|
||||
for (android.content.Intent intent : intents) {
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
public void startActivities(android.content.Intent[] intents, Bundle options) {
|
||||
startActivities(intents);
|
||||
}
|
||||
|
||||
public void sendBroadcast(android.content.Intent intent) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void sendBroadcast(android.content.Intent intent, String receiverPermission) {
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
|
||||
public void sendOrderedBroadcast(android.content.Intent intent, String receiverPermission) {
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
|
||||
public void sendStickyBroadcast(android.content.Intent intent) {
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
|
||||
public void removeStickyBroadcast(android.content.Intent intent) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
public android.content.Intent registerReceiver(android.content.BroadcastReceiver receiver, android.content.IntentFilter filter) {
|
||||
// No-op on desktop
|
||||
return null;
|
||||
}
|
||||
|
||||
public android.content.Intent registerReceiver(android.content.BroadcastReceiver receiver, android.content.IntentFilter filter, int flags) {
|
||||
return registerReceiver(receiver, filter);
|
||||
}
|
||||
|
||||
public android.content.Intent registerReceiver(android.content.BroadcastReceiver receiver, android.content.IntentFilter filter, String broadcastPermission, Handler scheduler) {
|
||||
return registerReceiver(receiver, filter);
|
||||
}
|
||||
|
||||
public android.content.Intent registerReceiver(android.content.BroadcastReceiver receiver, android.content.IntentFilter filter, String broadcastPermission, Handler scheduler, int flags) {
|
||||
return registerReceiver(receiver, filter);
|
||||
}
|
||||
|
||||
public void unregisterReceiver(android.content.BroadcastReceiver receiver) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public android.content.ComponentName startService(android.content.Intent service) {
|
||||
System.err.println("WARNING: Context.startService() called on desktop - not supported");
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean stopService(android.content.Intent name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean bindService(android.content.Intent service, android.content.ServiceConnection conn, int flags) {
|
||||
System.err.println("WARNING: Context.bindService() called on desktop - not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
public void unbindService(android.content.ServiceConnection conn) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
// Permission methods (grant everything on desktop)
|
||||
public int checkPermission(String permission, int pid, int uid) {
|
||||
return android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
public int checkCallingPermission(String permission) {
|
||||
return android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
public int checkCallingOrSelfPermission(String permission) {
|
||||
return android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
public int checkSelfPermission(String permission) {
|
||||
return android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
public void enforcePermission(String permission, int pid, int uid, String message) {
|
||||
// Always granted on desktop
|
||||
}
|
||||
|
||||
public void enforceCallingPermission(String permission, String message) {
|
||||
// Always granted on desktop
|
||||
}
|
||||
|
||||
public void enforceCallingOrSelfPermission(String permission, String message) {
|
||||
// Always granted on desktop
|
||||
}
|
||||
|
||||
// URI permission methods
|
||||
public int checkUriPermission(android.net.Uri uri, int pid, int uid, int modeFlags) {
|
||||
return android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
public int checkCallingUriPermission(android.net.Uri uri, int modeFlags) {
|
||||
return android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
public int checkCallingOrSelfUriPermission(android.net.Uri uri, int modeFlags) {
|
||||
return android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
public void enforceUriPermission(android.net.Uri uri, int pid, int uid, int modeFlags, String message) {
|
||||
// Always granted
|
||||
}
|
||||
|
||||
public void enforceCallingUriPermission(android.net.Uri uri, int modeFlags, String message) {
|
||||
// Always granted
|
||||
}
|
||||
|
||||
public void enforceCallingOrSelfUriPermission(android.net.Uri uri, int modeFlags, String message) {
|
||||
// Always granted
|
||||
}
|
||||
|
||||
public void grantUriPermission(String toPackage, android.net.Uri uri, int modeFlags) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
public void revokeUriPermission(android.net.Uri uri, int modeFlags) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
public void revokeUriPermission(String toPackage, android.net.Uri uri, int modeFlags) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
// Resource convenience methods
|
||||
public final CharSequence getText(int resId) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public final String getString(int resId) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public final String getString(int resId, Object... formatArgs) {
|
||||
return String.format(getString(resId), formatArgs);
|
||||
}
|
||||
|
||||
public final int getColor(int id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public final android.graphics.drawable.Drawable getDrawable(int id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final android.content.res.ColorStateList getColorStateList(int id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Theme methods
|
||||
public final android.content.res.TypedArray obtainStyledAttributes(int[] attrs) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final android.content.res.TypedArray obtainStyledAttributes(int resid, int[] attrs) throws android.content.res.Resources.NotFoundException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final android.content.res.TypedArray obtainStyledAttributes(android.util.AttributeSet set, int[] attrs) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final android.content.res.TypedArray obtainStyledAttributes(android.util.AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Context creation methods
|
||||
public Context createPackageContext(String packageName, int flags) throws android.content.pm.PackageManager.NameNotFoundException {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Context createConfigurationContext(android.content.res.Configuration overrideConfiguration) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Context createDisplayContext(Display display) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Context createDeviceProtectedStorageContext() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Context createCredentialProtectedStorageContext() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Context createAttributionContext(String attributionTag) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isDeviceProtectedStorage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isCredentialProtectedStorage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean canLoadUnsafeResources() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Other methods
|
||||
public String getOpPackageName() {
|
||||
return getPackageName();
|
||||
}
|
||||
|
||||
public String getAttributionTag() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public android.content.AttributionSource getAttributionSource() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isRestricted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public android.content.Context getBaseContext() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getUserId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String getSystemServiceName(Class<?> serviceClass) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getDisplayId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Display getDisplay() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void updateDisplay(int displayId) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
public void registerDeviceIdChangeListener(java.util.concurrent.Executor executor, java.util.function.IntConsumer listener) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
public void unregisterDeviceIdChangeListener(java.util.function.IntConsumer listener) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
public int getDeviceId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean isUiContext() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public android.view.WindowManager getSystemService(java.lang.Class<android.view.WindowManager> serviceClass) {
|
||||
return (android.view.WindowManager) getSystemService(WINDOW_SERVICE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,55 @@
|
||||
package android.content;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface SharedPreferences {
|
||||
boolean getBoolean(String key, boolean defaultValue);
|
||||
void putBoolean(String key, boolean value);
|
||||
|
||||
Map<String, ?> getAll();
|
||||
|
||||
String getString(String key, String defaultValue);
|
||||
|
||||
Set<String> getStringSet(String key, Set<String> defaultValue);
|
||||
void putStringSet(String key, Set<String> value);
|
||||
void putString(String key, String value);
|
||||
void remove(String key);
|
||||
String get(String key, String defaultValue);
|
||||
|
||||
int getInt(String key, int defaultValue);
|
||||
|
||||
long getLong(String key, long defaultValue);
|
||||
|
||||
float getFloat(String key, float defaultValue);
|
||||
|
||||
boolean getBoolean(String key, boolean defaultValue);
|
||||
|
||||
boolean contains(String key);
|
||||
|
||||
Editor edit();
|
||||
|
||||
void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener);
|
||||
|
||||
void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener);
|
||||
|
||||
interface Editor {
|
||||
Editor putBoolean(String key, boolean value);
|
||||
Editor putString(String key, String value);
|
||||
Editor putStringSet(String key, Set<String> value);
|
||||
|
||||
Editor putStringSet(String key, Set<String> values);
|
||||
|
||||
Editor putInt(String key, int value);
|
||||
|
||||
Editor putLong(String key, long value);
|
||||
|
||||
Editor putFloat(String key, float value);
|
||||
|
||||
Editor putBoolean(String key, boolean value);
|
||||
|
||||
Editor remove(String key);
|
||||
|
||||
Editor clear();
|
||||
|
||||
boolean commit();
|
||||
|
||||
void apply();
|
||||
}
|
||||
|
||||
interface OnSharedPreferenceChangeListener {
|
||||
void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
package android.content;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
@@ -7,19 +13,49 @@ public class SharedPreferencesImpl implements SharedPreferences {
|
||||
|
||||
private final Preferences prefs;
|
||||
private final Editor editor = new EditorImpl(this);
|
||||
private final Set<OnSharedPreferenceChangeListener> listeners = new HashSet<>();
|
||||
private final Gson gson = new Gson();
|
||||
|
||||
public SharedPreferencesImpl(String key) {
|
||||
prefs = Preferences.userRoot().node(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String key, boolean defaultValue) {
|
||||
return prefs.getBoolean(key, defaultValue);
|
||||
public Map<String, ?> getAll() {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
try {
|
||||
for (String key : prefs.keys()) {
|
||||
String value = prefs.get(key, null);
|
||||
if (value != null) {
|
||||
// Try to parse as typed values
|
||||
result.put(key, parseValue(value));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putBoolean(String key, boolean value) {
|
||||
prefs.putBoolean(key, value);
|
||||
private Object parseValue(String value) {
|
||||
// Try boolean
|
||||
if ("true".equals(value) || "false".equals(value)) {
|
||||
return Boolean.parseBoolean(value);
|
||||
}
|
||||
// Try int
|
||||
try {
|
||||
return Integer.parseInt(value);
|
||||
} catch (NumberFormatException ignored) {}
|
||||
// Try long
|
||||
try {
|
||||
return Long.parseLong(value);
|
||||
} catch (NumberFormatException ignored) {}
|
||||
// Try float
|
||||
try {
|
||||
return Float.parseFloat(value);
|
||||
} catch (NumberFormatException ignored) {}
|
||||
// Default to string
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -29,34 +65,59 @@ public class SharedPreferencesImpl implements SharedPreferences {
|
||||
|
||||
@Override
|
||||
public Set<String> getStringSet(String key, Set<String> defaultValue) {
|
||||
if (defaultValue != null) {
|
||||
return Set.of(prefs.get(key, String.join(";", defaultValue)).split(";"));
|
||||
String json = prefs.get(key, null);
|
||||
if (json == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
return gson.fromJson(json, new TypeToken<Set<String>>(){}.getType());
|
||||
} catch (Exception e) {
|
||||
// Fallback: try old semicolon-delimited format
|
||||
try {
|
||||
Set<String> result = new HashSet<>();
|
||||
for (String s : json.split(";")) {
|
||||
if (!s.isEmpty()) {
|
||||
result.add(s);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} catch (Exception e2) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(String key, int defaultValue) {
|
||||
return prefs.getInt(key, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(String key, long defaultValue) {
|
||||
return prefs.getLong(key, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(String key, float defaultValue) {
|
||||
String value = prefs.get(key, null);
|
||||
if (value != null) {
|
||||
return Set.of(value.split(";"));
|
||||
if (value == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
return Float.parseFloat(value);
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putStringSet(String key, Set<String> value) {
|
||||
prefs.put(key, String.join(";", value));
|
||||
public boolean getBoolean(String key, boolean defaultValue) {
|
||||
return prefs.getBoolean(key, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putString(String key, String value) {
|
||||
prefs.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(String key) {
|
||||
prefs.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get(String key, String defaultValue) {
|
||||
return prefs.get(key, defaultValue);
|
||||
public boolean contains(String key) {
|
||||
return prefs.get(key, null) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -64,45 +125,129 @@ public class SharedPreferencesImpl implements SharedPreferences {
|
||||
return editor;
|
||||
}
|
||||
|
||||
private static class EditorImpl implements SharedPreferences.Editor {
|
||||
@Override
|
||||
public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
void notifyListeners(String key) {
|
||||
for (OnSharedPreferenceChangeListener listener : new HashSet<>(listeners)) {
|
||||
try {
|
||||
listener.onSharedPreferenceChanged(this, key);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class EditorImpl implements Editor {
|
||||
|
||||
private final SharedPreferencesImpl prefs;
|
||||
private final Map<String, Object> pendingChanges = new HashMap<>();
|
||||
private boolean clear = false;
|
||||
|
||||
public EditorImpl(SharedPreferencesImpl prefs) {
|
||||
this.prefs = prefs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor putBoolean(String key, boolean value) {
|
||||
prefs.putBoolean(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor putString(String key, String value) {
|
||||
prefs.putString(key, value);
|
||||
pendingChanges.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor putStringSet(String key, Set<String> value) {
|
||||
prefs.putStringSet(key, value);
|
||||
public Editor putStringSet(String key, Set<String> values) {
|
||||
pendingChanges.put(key, values);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor putInt(String key, int value) {
|
||||
pendingChanges.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor putLong(String key, long value) {
|
||||
pendingChanges.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor putFloat(String key, float value) {
|
||||
pendingChanges.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor putBoolean(String key, boolean value) {
|
||||
pendingChanges.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor remove(String key) {
|
||||
prefs.remove(key);
|
||||
pendingChanges.put(key, null); // null means remove
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor clear() {
|
||||
clear = true;
|
||||
pendingChanges.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean commit() {
|
||||
apply();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() {
|
||||
if (clear) {
|
||||
try {
|
||||
for (String key : prefs.prefs.keys()) {
|
||||
prefs.prefs.remove(key);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Object> entry : pendingChanges.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
|
||||
if (value == null) {
|
||||
prefs.prefs.remove(key);
|
||||
} else if (value instanceof String) {
|
||||
prefs.prefs.put(key, (String) value);
|
||||
} else if (value instanceof Set) {
|
||||
// Store as JSON array
|
||||
prefs.prefs.put(key, prefs.gson.toJson(value));
|
||||
} else if (value instanceof Integer) {
|
||||
prefs.prefs.putInt(key, (Integer) value);
|
||||
} else if (value instanceof Long) {
|
||||
prefs.prefs.putLong(key, (Long) value);
|
||||
} else if (value instanceof Float) {
|
||||
prefs.prefs.put(key, value.toString());
|
||||
} else if (value instanceof Boolean) {
|
||||
prefs.prefs.putBoolean(key, (Boolean) value);
|
||||
}
|
||||
|
||||
prefs.notifyListeners(key);
|
||||
}
|
||||
|
||||
pendingChanges.clear();
|
||||
clear = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
package android.content.pm;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Minimal PackageManager stub for desktop JVM.
|
||||
*/
|
||||
public class PackageManager {
|
||||
|
||||
public static final int GET_ACTIVITIES = 0x00000001;
|
||||
public static final int GET_CONFIGURATIONS = 0x00004000;
|
||||
public static final int GET_GIDS = 0x00000100;
|
||||
public static final int GET_INSTRUMENTATION = 0x00000010;
|
||||
public static final int GET_INTENT_FILTERS = 0x00000020;
|
||||
public static final int GET_META_DATA = 0x00000080;
|
||||
public static final int GET_PERMISSIONS = 0x00001000;
|
||||
public static final int GET_PROVIDERS = 0x00000008;
|
||||
public static final int GET_RECEIVERS = 0x00000002;
|
||||
public static final int GET_RESOLVED_FILTER = 0x00000040;
|
||||
public static final int GET_SERVICES = 0x00000004;
|
||||
public static final int GET_SHARED_LIBRARY_FILES = 0x00000400;
|
||||
public static final int GET_SIGNATURES = 0x00000040;
|
||||
public static final int GET_SIGNING_CERTIFICATES = 0x08000000;
|
||||
public static final int GET_URI_PERMISSION_PATTERNS = 0x00000800;
|
||||
public static final int MATCH_ALL = 0x00020000;
|
||||
public static final int MATCH_DEBUG_TRIAGED_MISSING = 0x00010000;
|
||||
public static final int MATCH_DEFAULT_ONLY = 0x00010000;
|
||||
public static final int MATCH_DIRECT_BOOT_AWARE = 0x00040000;
|
||||
public static final int MATCH_DIRECT_BOOT_UNAWARE = 0x00080000;
|
||||
public static final int MATCH_DISABLED_COMPONENTS = 0x00020000;
|
||||
public static final int MATCH_DISABLED_UNTIL_USED_COMPONENTS = 0x00080000;
|
||||
public static final int MATCH_EXPLICITLY_ONLY = 0x00100000;
|
||||
public static final int MATCH_FACTORY_ONLY = 0x00200000;
|
||||
public static final int MATCH_SYSTEM_ONLY = 0x00040000;
|
||||
public static final int MATCH_UNINSTALLED_PACKAGES = 0x00002000;
|
||||
public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0;
|
||||
public static final int COMPONENT_ENABLED_STATE_ENABLED = 1;
|
||||
public static final int COMPONENT_ENABLED_STATE_DISABLED = 2;
|
||||
public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3;
|
||||
public static final int COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4;
|
||||
public static final int PERMISSION_GRANTED = 0;
|
||||
public static final int PERMISSION_DENIED = -1;
|
||||
public static final int SIGNATURE_MATCH = 0;
|
||||
public static final int SIGNATURE_NEITHER_SIGNED = 1;
|
||||
public static final int SIGNATURE_FIRST_NOT_SIGNED = -1;
|
||||
public static final int SIGNATURE_SECOND_NOT_SIGNED = -2;
|
||||
public static final int SIGNATURE_NO_MATCH = -3;
|
||||
public static final int SIGNATURE_UNKNOWN_PACKAGE = -4;
|
||||
|
||||
public PackageManager() {
|
||||
}
|
||||
|
||||
public PackageInfo getPackageInfo(String packageName, int flags) throws NameNotFoundException {
|
||||
PackageInfo info = new PackageInfo();
|
||||
info.packageName = packageName;
|
||||
return info;
|
||||
}
|
||||
|
||||
public ApplicationInfo getApplicationInfo(String packageName, int flags) throws NameNotFoundException {
|
||||
ApplicationInfo info = new ApplicationInfo();
|
||||
info.packageName = packageName;
|
||||
return info;
|
||||
}
|
||||
|
||||
public ActivityInfo getActivityInfo(android.content.ComponentName component, int flags) throws NameNotFoundException {
|
||||
ActivityInfo info = new ActivityInfo();
|
||||
info.packageName = component.getPackageName();
|
||||
info.name = component.getClassName();
|
||||
return info;
|
||||
}
|
||||
|
||||
public ServiceInfo getServiceInfo(android.content.ComponentName component, int flags) throws NameNotFoundException {
|
||||
ServiceInfo info = new ServiceInfo();
|
||||
info.packageName = component.getPackageName();
|
||||
info.name = component.getClassName();
|
||||
return info;
|
||||
}
|
||||
|
||||
public ProviderInfo getProviderInfo(android.content.ComponentName component, int flags) throws NameNotFoundException {
|
||||
ProviderInfo info = new ProviderInfo();
|
||||
info.packageName = component.getPackageName();
|
||||
info.name = component.getClassName();
|
||||
return info;
|
||||
}
|
||||
|
||||
public List<PackageInfo> getInstalledPackages(int flags) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<ApplicationInfo> getInstalledApplications(int flags) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public int checkPermission(String permName, String pkgName) {
|
||||
return PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
public boolean addPermission(PermissionInfo info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean addPermissionAsync(PermissionInfo info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void removePermission(String name) {
|
||||
}
|
||||
|
||||
public int checkSignatures(String pkg1, String pkg2) {
|
||||
return SIGNATURE_MATCH;
|
||||
}
|
||||
|
||||
public int checkSignatures(int uid1, int uid2) {
|
||||
return SIGNATURE_MATCH;
|
||||
}
|
||||
|
||||
public String[] getPackagesForUid(int uid) {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
public String getNameForUid(int uid) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<ResolveInfo> queryIntentActivityOptions(android.content.ComponentName caller, Intent[] specifics, Intent intent, int flags) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public ResolveInfo resolveService(Intent intent, int flags) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<ResolveInfo> queryIntentContentProviders(Intent intent, int flags) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public ResolveInfo resolveActivity(Intent intent, int flags) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ProviderInfo resolveContentProvider(String name, int flags) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Drawable getApplicationIcon(ApplicationInfo info) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Drawable getApplicationIcon(String packageName) throws NameNotFoundException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Drawable getActivityIcon(android.content.ComponentName activityName) throws NameNotFoundException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Drawable getActivityIcon(Intent intent) throws NameNotFoundException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Drawable getDefaultActivityIcon() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Resources getResourcesForActivity(android.content.ComponentName activityName) throws NameNotFoundException {
|
||||
return new Resources();
|
||||
}
|
||||
|
||||
public Resources getResourcesForApplication(ApplicationInfo app) throws NameNotFoundException {
|
||||
return new Resources();
|
||||
}
|
||||
|
||||
public Resources getResourcesForApplication(String appPackageName) throws NameNotFoundException {
|
||||
return new Resources();
|
||||
}
|
||||
|
||||
public CharSequence getText(String packageName, int resid, ApplicationInfo appInfo) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public CharSequence getApplicationLabel(ApplicationInfo info) {
|
||||
return info.packageName;
|
||||
}
|
||||
|
||||
public android.content.pm.PackageInstaller getPackageInstaller() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isInstantApp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isInstantApp(String packageName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getInstantAppCookieMaxBytes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public byte[] getInstantAppCookie() {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
public boolean setInstantAppCookie(byte[] cookie) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void clearInstantAppCookie() {
|
||||
}
|
||||
|
||||
public static class NameNotFoundException extends android.util.AndroidException {
|
||||
public NameNotFoundException() {
|
||||
}
|
||||
public NameNotFoundException(String name) {
|
||||
super(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package android.content.pm;
|
||||
|
||||
/**
|
||||
* Minimal ShortcutManager stub for desktop JVM.
|
||||
*/
|
||||
public class ShortcutManager {
|
||||
|
||||
public ShortcutManager() {
|
||||
}
|
||||
|
||||
public boolean setDynamicShortcuts(java.util.List<android.content.pm.ShortcutInfo> shortcutInfoList) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public java.util.List<android.content.pm.ShortcutInfo> getDynamicShortcuts() {
|
||||
return new java.util.ArrayList<>();
|
||||
}
|
||||
|
||||
public java.util.List<android.content.pm.ShortcutInfo> getManifestShortcuts() {
|
||||
return new java.util.ArrayList<>();
|
||||
}
|
||||
|
||||
public boolean addDynamicShortcuts(java.util.List<android.content.pm.ShortcutInfo> shortcutInfoList) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void removeDynamicShortcuts(java.util.List<String> shortcutIds) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void removeAllDynamicShortcuts() {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts() {
|
||||
return new java.util.ArrayList<>();
|
||||
}
|
||||
|
||||
public boolean updateShortcuts(java.util.List<android.content.pm.ShortcutInfo> shortcutInfoList) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void disableShortcuts(java.util.List<String> shortcutIds) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void enableShortcuts(java.util.List<String> shortcutIds) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public int getMaxShortcutCountPerActivity() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean isRateLimitingActive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getIconMaxWidth() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getIconMaxHeight() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void reportShortcutUsed(String shortcutId) {
|
||||
// No-op on desktop
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package android.content.res;
|
||||
|
||||
/**
|
||||
* Minimal AssetManager stub for desktop JVM.
|
||||
*/
|
||||
public class AssetManager {
|
||||
|
||||
public AssetManager() {
|
||||
}
|
||||
|
||||
public String[] list(String path) {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
public java.io.InputStream open(String fileName) throws java.io.IOException {
|
||||
return new java.io.ByteArrayInputStream(new byte[0]);
|
||||
}
|
||||
|
||||
public java.io.InputStream open(String fileName, int accessMode) throws java.io.IOException {
|
||||
return open(fileName);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
// No-op
|
||||
}
|
||||
}
|
||||
152
androidcompat/src/main/java/android/content/res/Resources.java
Normal file
152
androidcompat/src/main/java/android/content/res/Resources.java
Normal file
@@ -0,0 +1,152 @@
|
||||
package android.content.res;
|
||||
|
||||
/**
|
||||
* Minimal Resources stub for desktop JVM.
|
||||
*/
|
||||
public class Resources {
|
||||
|
||||
public Resources() {
|
||||
}
|
||||
|
||||
public Resources(AssetManager assets, android.util.DisplayMetrics metrics, android.content.res.Configuration config) {
|
||||
}
|
||||
|
||||
public CharSequence getText(int id) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getString(int id) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getString(int id, Object... formatArgs) {
|
||||
return String.format(getString(id), formatArgs);
|
||||
}
|
||||
|
||||
public String getQuantityString(int id, int quantity) {
|
||||
return getString(id);
|
||||
}
|
||||
|
||||
public String getQuantityString(int id, int quantity, Object... formatArgs) {
|
||||
return String.format(getQuantityString(id, quantity), formatArgs);
|
||||
}
|
||||
|
||||
public int getColor(int id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getColor(int id, Theme theme) {
|
||||
return getColor(id);
|
||||
}
|
||||
|
||||
public android.graphics.drawable.Drawable getDrawable(int id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public android.graphics.drawable.Drawable getDrawable(int id, Theme theme) {
|
||||
return getDrawable(id);
|
||||
}
|
||||
|
||||
public android.content.res.ColorStateList getColorStateList(int id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public android.content.res.ColorStateList getColorStateList(int id, Theme theme) {
|
||||
return getColorStateList(id);
|
||||
}
|
||||
|
||||
public float getDimension(int id) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
public int getDimensionPixelSize(int id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getDimensionPixelOffset(int id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public android.util.TypedValue getValue(int id, android.util.TypedValue outValue, boolean resolveRefs) {
|
||||
return outValue;
|
||||
}
|
||||
|
||||
public Theme newTheme() {
|
||||
return new Theme();
|
||||
}
|
||||
|
||||
public Theme getTheme() {
|
||||
return new Theme();
|
||||
}
|
||||
|
||||
public AssetManager getAssets() {
|
||||
return new AssetManager();
|
||||
}
|
||||
|
||||
public android.content.res.XmlResourceParser getXml(int id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public android.content.res.XmlResourceParser getAnimation(int id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public android.content.res.XmlResourceParser getLayout(int id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getResourceName(int resid) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getResourcePackageName(int resid) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getResourceTypeName(int resid) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getResourceEntryName(int resid) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public int getIdentifier(String name, String defType, String defPackage) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public java.io.InputStream openRawResource(int id) {
|
||||
return new java.io.ByteArrayInputStream(new byte[0]);
|
||||
}
|
||||
|
||||
public static class Theme {
|
||||
public Theme() {
|
||||
}
|
||||
|
||||
public void applyStyle(int resId, boolean force) {
|
||||
}
|
||||
|
||||
public void setTo(Theme other) {
|
||||
}
|
||||
|
||||
public android.content.res.TypedArray obtainStyledAttributes(int[] attrs) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public android.content.res.TypedArray obtainStyledAttributes(int resid, int[] attrs) throws Resources.NotFoundException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public android.content.res.TypedArray obtainStyledAttributes(android.util.AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class NotFoundException extends RuntimeException {
|
||||
public NotFoundException() {
|
||||
}
|
||||
public NotFoundException(String name) {
|
||||
super(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package android.hardware;
|
||||
|
||||
/**
|
||||
* Minimal SensorManager stub for desktop JVM.
|
||||
*/
|
||||
public class SensorManager {
|
||||
|
||||
public static final int SENSOR_DELAY_FASTEST = 0;
|
||||
public static final int SENSOR_DELAY_GAME = 1;
|
||||
public static final int SENSOR_DELAY_UI = 2;
|
||||
public static final int SENSOR_DELAY_NORMAL = 3;
|
||||
public static final int SENSOR_STATUS_NO_CONTACT = -1;
|
||||
public static final int SENSOR_STATUS_UNRELIABLE = 0;
|
||||
public static final int SENSOR_STATUS_ACCURACY_LOW = 1;
|
||||
public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2;
|
||||
public static final int SENSOR_STATUS_ACCURACY_HIGH = 3;
|
||||
|
||||
public SensorManager() {
|
||||
}
|
||||
|
||||
public java.util.List<android.hardware.Sensor> getSensorList(int type) {
|
||||
return new java.util.ArrayList<>();
|
||||
}
|
||||
|
||||
public android.hardware.Sensor getDefaultSensor(int type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public android.hardware.Sensor getDefaultSensor(int type, boolean wakeUp) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean registerListener(android.hardware.SensorEventListener listener, android.hardware.Sensor sensor, int samplingPeriodUs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean registerListener(android.hardware.SensorEventListener listener, android.hardware.Sensor sensor, int samplingPeriodUs, android.os.Handler handler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void unregisterListener(android.hardware.SensorEventListener listener) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void unregisterListener(android.hardware.SensorEventListener listener, android.hardware.Sensor sensor) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public boolean flush(android.hardware.SensorEventListener listener) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static float getAltitude(float p0, float p) {
|
||||
return 44330.0f * (1.0f - (float) Math.pow(p / p0, 1.0f / 5.255f));
|
||||
}
|
||||
|
||||
public static void getRotationMatrixFromVector(float[] R, float[] rotationVector) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public static void getQuaternionFromVector(float[] Q, float[] rv) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public static boolean getRotationMatrix(float[] R, float[] I, float[] gravity, float[] geomagnetic) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static float[] getOrientation(float[] R, float[] values) {
|
||||
if (values == null) {
|
||||
values = new float[3];
|
||||
}
|
||||
values[0] = 0;
|
||||
values[1] = 0;
|
||||
values[2] = 0;
|
||||
return values;
|
||||
}
|
||||
|
||||
public static void remapCoordinateSystem(float[] inR, int X, int Y, float[] outR) {
|
||||
// No-op on desktop
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package android.hardware.display;
|
||||
|
||||
/**
|
||||
* Minimal DisplayManager stub for desktop JVM.
|
||||
*/
|
||||
public class DisplayManager {
|
||||
|
||||
public static final String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
|
||||
|
||||
public DisplayManager() {
|
||||
}
|
||||
|
||||
public android.view.Display getDisplay(int displayId) {
|
||||
return android.view.Display.getDisplay(displayId);
|
||||
}
|
||||
|
||||
public android.view.Display[] getDisplays() {
|
||||
return new android.view.Display[] { android.view.Display.getDisplay(0) };
|
||||
}
|
||||
|
||||
public android.view.Display[] getDisplays(String category) {
|
||||
return getDisplays();
|
||||
}
|
||||
|
||||
public void registerDisplayListener(DisplayManager.DisplayListener listener, android.os.Handler handler) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void unregisterDisplayListener(DisplayManager.DisplayListener listener) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public interface DisplayListener {
|
||||
void onDisplayAdded(int displayId);
|
||||
void onDisplayRemoved(int displayId);
|
||||
void onDisplayChanged(int displayId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package android.location;
|
||||
|
||||
/**
|
||||
* Minimal LocationManager stub for desktop JVM.
|
||||
*/
|
||||
public class LocationManager {
|
||||
|
||||
public static final String NETWORK_PROVIDER = "network";
|
||||
public static final String GPS_PROVIDER = "gps";
|
||||
public static final String PASSIVE_PROVIDER = "passive";
|
||||
public static final String FUSED_PROVIDER = "fused";
|
||||
|
||||
public static final String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED";
|
||||
public static final String MODE_CHANGED_ACTION = "android.location.MODE_CHANGED";
|
||||
public static final String GPS_ENABLED_CHANGE_ACTION = "android.location.GPS_ENABLED_CHANGE";
|
||||
public static final String GPS_FIX_CHANGE_ACTION = "android.location.GPS_FIX_CHANGE";
|
||||
|
||||
public LocationManager() {
|
||||
}
|
||||
|
||||
public java.util.List<String> getAllProviders() {
|
||||
return java.util.List.of(NETWORK_PROVIDER, GPS_PROVIDER, PASSIVE_PROVIDER);
|
||||
}
|
||||
|
||||
public java.util.List<String> getProviders(boolean enabledOnly) {
|
||||
return getAllProviders();
|
||||
}
|
||||
|
||||
public android.location.LocationProvider getProvider(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public java.util.List<android.location.LocationProvider> getProviders(android.location.Criteria criteria, boolean enabledOnly) {
|
||||
return new java.util.ArrayList<>();
|
||||
}
|
||||
|
||||
public String getBestProvider(android.location.Criteria criteria, boolean enabledOnly) {
|
||||
return NETWORK_PROVIDER;
|
||||
}
|
||||
|
||||
public android.location.Location getLastKnownLocation(String provider) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void requestLocationUpdates(String provider, long minTime, float minDistance, android.location.LocationListener listener) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void requestLocationUpdates(String provider, long minTime, float minDistance, android.location.LocationListener listener, android.os.Looper looper) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void requestSingleUpdate(String provider, android.location.LocationListener listener, android.os.Looper looper) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void removeUpdates(android.location.LocationListener listener) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public boolean isProviderEnabled(String provider) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isLocationEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addGpsStatusListener(android.location.GpsStatus.Listener listener) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void removeGpsStatusListener(android.location.GpsStatus.Listener listener) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public boolean addNmeaListener(android.location.OnNmeaMessageListener listener) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean addNmeaListener(android.location.OnNmeaMessageListener listener, android.os.Handler handler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void removeNmeaListener(android.location.OnNmeaMessageListener listener) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public boolean registerGnssStatusCallback(android.location.GnssStatus.Callback callback) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean registerGnssStatusCallback(android.location.GnssStatus.Callback callback, android.os.Handler handler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void unregisterGnssStatusCallback(android.location.GnssStatus.Callback callback) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void addProximityAlert(double latitude, double longitude, float radius, long expiration, android.app.PendingIntent intent) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void removeProximityAlert(android.app.PendingIntent intent) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public boolean sendExtraCommand(String provider, String command, android.os.Bundle extras) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
114
androidcompat/src/main/java/android/media/AudioManager.java
Normal file
114
androidcompat/src/main/java/android/media/AudioManager.java
Normal file
@@ -0,0 +1,114 @@
|
||||
package android.media;
|
||||
|
||||
/**
|
||||
* Minimal AudioManager stub for desktop JVM.
|
||||
*/
|
||||
public class AudioManager {
|
||||
|
||||
public static final int STREAM_VOICE_CALL = 0;
|
||||
public static final int STREAM_SYSTEM = 1;
|
||||
public static final int STREAM_RING = 2;
|
||||
public static final int STREAM_MUSIC = 3;
|
||||
public static final int STREAM_ALARM = 4;
|
||||
public static final int STREAM_NOTIFICATION = 5;
|
||||
public static final int STREAM_DTMF = 8;
|
||||
public static final int STREAM_ACCESSIBILITY = 10;
|
||||
|
||||
public static final int MODE_NORMAL = 0;
|
||||
public static final int MODE_RINGTONE = 1;
|
||||
public static final int MODE_IN_CALL = 2;
|
||||
public static final int MODE_IN_COMMUNICATION = 3;
|
||||
|
||||
public static final int RINGER_MODE_SILENT = 0;
|
||||
public static final int RINGER_MODE_VIBRATE = 1;
|
||||
public static final int RINGER_MODE_NORMAL = 2;
|
||||
|
||||
public static final int AUDIOFOCUS_GAIN = 1;
|
||||
public static final int AUDIOFOCUS_GAIN_TRANSIENT = 2;
|
||||
public static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK = 3;
|
||||
public static final int AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE = 4;
|
||||
public static final int AUDIOFOCUS_LOSS = -1;
|
||||
public static final int AUDIOFOCUS_LOSS_TRANSIENT = -2;
|
||||
public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = -3;
|
||||
public static final int AUDIOFOCUS_REQUEST_GRANTED = 1;
|
||||
public static final int AUDIOFOCUS_REQUEST_FAILED = 0;
|
||||
|
||||
public AudioManager() {
|
||||
}
|
||||
|
||||
public int getStreamMaxVolume(int streamType) {
|
||||
return 15;
|
||||
}
|
||||
|
||||
public int getStreamVolume(int streamType) {
|
||||
return 10;
|
||||
}
|
||||
|
||||
public void setStreamVolume(int streamType, int index, int flags) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public int getRingerMode() {
|
||||
return RINGER_MODE_NORMAL;
|
||||
}
|
||||
|
||||
public void setRingerMode(int ringerMode) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public boolean isMusicActive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener l, int streamType, int durationHint) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public int requestAudioFocus(android.media.AudioFocusRequest focusRequest) {
|
||||
return AUDIOFOCUS_REQUEST_GRANTED;
|
||||
}
|
||||
|
||||
public void abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener l) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public int abandonAudioFocusRequest(android.media.AudioFocusRequest focusRequest) {
|
||||
return AUDIOFOCUS_REQUEST_GRANTED;
|
||||
}
|
||||
|
||||
public boolean isSpeakerphoneOn() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setSpeakerphoneOn(boolean on) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public boolean isBluetoothScoOn() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setBluetoothScoOn(boolean on) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void startBluetoothSco() {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void stopBluetoothSco() {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void setMode(int mode) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public int getMode() {
|
||||
return MODE_NORMAL;
|
||||
}
|
||||
|
||||
public interface OnAudioFocusChangeListener {
|
||||
void onAudioFocusChange(int focusChange);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package android.net;
|
||||
|
||||
/**
|
||||
* Minimal ConnectivityManager stub for desktop JVM.
|
||||
*/
|
||||
public class ConnectivityManager {
|
||||
|
||||
public static final int TYPE_MOBILE = 0;
|
||||
public static final int TYPE_WIFI = 1;
|
||||
public static final int TYPE_BLUETOOTH = 7;
|
||||
public static final int TYPE_ETHERNET = 9;
|
||||
public static final int TYPE_VPN = 17;
|
||||
|
||||
public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1;
|
||||
public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2;
|
||||
public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3;
|
||||
|
||||
public ConnectivityManager() {
|
||||
}
|
||||
|
||||
public android.net.NetworkInfo getActiveNetworkInfo() {
|
||||
// Always report as connected on desktop
|
||||
return new android.net.NetworkInfo(TYPE_WIFI, 0, "WIFI", "");
|
||||
}
|
||||
|
||||
public android.net.Network getActiveNetwork() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isActiveNetworkMetered() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getRestrictBackgroundStatus() {
|
||||
return RESTRICT_BACKGROUND_STATUS_DISABLED;
|
||||
}
|
||||
|
||||
public boolean getNetworkInfo(int networkType) {
|
||||
return networkType == TYPE_WIFI || networkType == TYPE_ETHERNET;
|
||||
}
|
||||
|
||||
public void registerNetworkCallback(android.net.NetworkRequest request, android.net.ConnectivityManager.NetworkCallback networkCallback) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void unregisterNetworkCallback(android.net.ConnectivityManager.NetworkCallback networkCallback) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public static abstract class NetworkCallback {
|
||||
public void onAvailable(android.net.Network network) {}
|
||||
public void onLost(android.net.Network network) {}
|
||||
public void onCapabilitiesChanged(android.net.Network network, android.net.NetworkCapabilities networkCapabilities) {}
|
||||
public void onLinkPropertiesChanged(android.net.Network network, android.net.LinkProperties linkProperties) {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package android.net.wifi;
|
||||
|
||||
/**
|
||||
* Minimal WifiManager stub for desktop JVM.
|
||||
*/
|
||||
public class WifiManager {
|
||||
|
||||
public static final int WIFI_STATE_DISABLING = 0;
|
||||
public static final int WIFI_STATE_DISABLED = 1;
|
||||
public static final int WIFI_STATE_ENABLING = 2;
|
||||
public static final int WIFI_STATE_ENABLED = 3;
|
||||
public static final int WIFI_STATE_UNKNOWN = 4;
|
||||
|
||||
public WifiManager() {
|
||||
}
|
||||
|
||||
public int getWifiState() {
|
||||
return WIFI_STATE_ENABLED;
|
||||
}
|
||||
|
||||
public boolean isWifiEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean setWifiEnabled(boolean enabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public android.net.wifi.WifiInfo getConnectionInfo() {
|
||||
return new android.net.wifi.WifiInfo();
|
||||
}
|
||||
|
||||
public java.util.List<android.net.wifi.ScanResult> getScanResults() {
|
||||
return new java.util.ArrayList<>();
|
||||
}
|
||||
|
||||
public boolean startScan() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int addNetwork(android.net.wifi.WifiConfiguration config) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public boolean disconnect() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean reconnect() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean is5GHzBandSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isP2pSupported() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package android.net.wifi.p2p;
|
||||
|
||||
/**
|
||||
* Minimal WifiP2pManager stub for desktop JVM.
|
||||
*/
|
||||
public class WifiP2pManager {
|
||||
|
||||
public static final int ERROR = 0;
|
||||
public static final int P2P_UNSUPPORTED = 1;
|
||||
public static final int BUSY = 2;
|
||||
public static final int NO_SERVICE_REQUESTS = 3;
|
||||
|
||||
public WifiP2pManager() {
|
||||
}
|
||||
|
||||
public void initialize(android.content.Context srcContext, android.os.Looper srcLooper, WifiP2pManager.ChannelListener listener) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void discoverPeers(android.net.wifi.p2p.WifiP2pManager.Channel c, android.net.wifi.p2p.WifiP2pManager.ActionListener listener) {
|
||||
if (listener != null) {
|
||||
listener.onFailure(P2P_UNSUPPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
public void stopPeerDiscovery(android.net.wifi.p2p.WifiP2pManager.Channel c, android.net.wifi.p2p.WifiP2pManager.ActionListener listener) {
|
||||
if (listener != null) {
|
||||
listener.onFailure(P2P_UNSUPPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
public interface ChannelListener {
|
||||
void onChannelDisconnected();
|
||||
}
|
||||
|
||||
public interface ActionListener {
|
||||
void onSuccess();
|
||||
void onFailure(int reason);
|
||||
}
|
||||
|
||||
public static class Channel {
|
||||
}
|
||||
}
|
||||
14
androidcompat/src/main/java/android/nfc/NfcManager.java
Normal file
14
androidcompat/src/main/java/android/nfc/NfcManager.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package android.nfc;
|
||||
|
||||
/**
|
||||
* Minimal NfcManager stub for desktop JVM.
|
||||
*/
|
||||
public class NfcManager {
|
||||
|
||||
public NfcManager() {
|
||||
}
|
||||
|
||||
public android.nfc.NfcAdapter getDefaultAdapter() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
76
androidcompat/src/main/java/android/os/BatteryManager.java
Normal file
76
androidcompat/src/main/java/android/os/BatteryManager.java
Normal file
@@ -0,0 +1,76 @@
|
||||
package android.os;
|
||||
|
||||
/**
|
||||
* Minimal BatteryManager stub for desktop JVM.
|
||||
*/
|
||||
public class BatteryManager {
|
||||
|
||||
public static final String EXTRA_HEALTH = "health";
|
||||
public static final String EXTRA_STATUS = "status";
|
||||
public static final String EXTRA_LEVEL = "level";
|
||||
public static final String EXTRA_SCALE = "scale";
|
||||
public static final String EXTRA_PLUGGED = "plugged";
|
||||
public static final String EXTRA_VOLTAGE = "voltage";
|
||||
public static final String EXTRA_TEMPERATURE = "temperature";
|
||||
public static final String EXTRA_PRESENT = "present";
|
||||
public static final String EXTRA_TECHNOLOGY = "technology";
|
||||
public static final String EXTRA_CYCLE_COUNT = "cycle_count";
|
||||
|
||||
public static final int BATTERY_STATUS_UNKNOWN = 1;
|
||||
public static final int BATTERY_STATUS_CHARGING = 2;
|
||||
public static final int BATTERY_STATUS_DISCHARGING = 3;
|
||||
public static final int BATTERY_STATUS_NOT_CHARGING = 4;
|
||||
public static final int BATTERY_STATUS_FULL = 5;
|
||||
|
||||
public static final int BATTERY_HEALTH_UNKNOWN = 1;
|
||||
public static final int BATTERY_HEALTH_GOOD = 2;
|
||||
public static final int BATTERY_HEALTH_OVERHEAT = 3;
|
||||
public static final int BATTERY_HEALTH_DEAD = 4;
|
||||
public static final int BATTERY_HEALTH_OVER_VOLTAGE = 5;
|
||||
public static final int BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6;
|
||||
public static final int BATTERY_HEALTH_COLD = 7;
|
||||
|
||||
public static final int BATTERY_PLUGGED_AC = 1;
|
||||
public static final int BATTERY_PLUGGED_USB = 2;
|
||||
public static final int BATTERY_PLUGGED_WIRELESS = 4;
|
||||
public static final int BATTERY_PLUGGED_DOCK = 8;
|
||||
|
||||
public BatteryManager() {
|
||||
}
|
||||
|
||||
public int getIntProperty(int id) {
|
||||
return switch (id) {
|
||||
case BATTERY_PROPERTY_STATUS -> BATTERY_STATUS_FULL;
|
||||
case BATTERY_PROPERTY_HEALTH -> BATTERY_HEALTH_GOOD;
|
||||
case BATTERY_PROPERTY_PRESENT -> 1;
|
||||
case BATTERY_PROPERTY_LEVEL -> 100;
|
||||
case BATTERY_PROPERTY_SCALE -> 100;
|
||||
case BATTERY_PROPERTY_VOLTAGE -> 4200;
|
||||
case BATTERY_PROPERTY_TEMPERATURE -> 250;
|
||||
case BATTERY_PROPERTY_CAPACITY -> 100;
|
||||
case BATTERY_PROPERTY_CHARGE_COUNTER -> 4000000;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
public long getLongProperty(int id) {
|
||||
return getIntProperty(id);
|
||||
}
|
||||
|
||||
public boolean isCharging() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static final int BATTERY_PROPERTY_CHARGE_COUNTER = 1;
|
||||
public static final int BATTERY_PROPERTY_CURRENT_NOW = 2;
|
||||
public static final int BATTERY_PROPERTY_CURRENT_AVERAGE = 3;
|
||||
public static final int BATTERY_PROPERTY_CAPACITY = 4;
|
||||
public static final int BATTERY_PROPERTY_ENERGY_COUNTER = 5;
|
||||
public static final int BATTERY_PROPERTY_STATUS = 6;
|
||||
public static final int BATTERY_PROPERTY_HEALTH = 7;
|
||||
public static final int BATTERY_PROPERTY_PRESENT = 8;
|
||||
public static final int BATTERY_PROPERTY_LEVEL = 9;
|
||||
public static final int BATTERY_PROPERTY_SCALE = 10;
|
||||
public static final int BATTERY_PROPERTY_VOLTAGE = 11;
|
||||
public static final int BATTERY_PROPERTY_TEMPERATURE = 12;
|
||||
}
|
||||
78
androidcompat/src/main/java/android/os/PowerManager.java
Normal file
78
androidcompat/src/main/java/android/os/PowerManager.java
Normal file
@@ -0,0 +1,78 @@
|
||||
package android.os;
|
||||
|
||||
/**
|
||||
* Minimal PowerManager stub for desktop JVM.
|
||||
*/
|
||||
public class PowerManager {
|
||||
|
||||
public static final int PARTIAL_WAKE_LOCK = 0x00000001;
|
||||
public static final int FULL_WAKE_LOCK = 0x0000001a;
|
||||
public static final int SCREEN_BRIGHT_WAKE_LOCK = 0x0000000a;
|
||||
public static final int SCREEN_DIM_WAKE_LOCK = 0x00000006;
|
||||
public static final int ACQUIRE_CAUSES_WAKEUP = 0x10000000;
|
||||
public static final int ON_AFTER_RELEASE = 0x20000000;
|
||||
|
||||
public static final int BRIGHTNESS_ON = 255;
|
||||
public static final int BRIGHTNESS_OFF = 0;
|
||||
|
||||
public PowerManager() {
|
||||
}
|
||||
|
||||
public PowerManager.WakeLock newWakeLock(int levelAndFlags, String tag) {
|
||||
return new PowerManager.WakeLock();
|
||||
}
|
||||
|
||||
public boolean isWakeLockLevelSupported(int level) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isDeviceIdleMode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isPowerSaveMode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isInteractive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isScreenOn() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void reboot(String reason) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public static class WakeLock {
|
||||
public void acquire() {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void acquire(long timeout) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void release() {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void release(int flags) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public boolean isHeld() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setReferenceCounted(boolean value) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void setWorkSource(android.os.WorkSource ws) {
|
||||
// No-op on desktop
|
||||
}
|
||||
}
|
||||
}
|
||||
34
androidcompat/src/main/java/android/os/Vibrator.java
Normal file
34
androidcompat/src/main/java/android/os/Vibrator.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package android.os;
|
||||
|
||||
/**
|
||||
* Minimal Vibrator stub for desktop JVM.
|
||||
*/
|
||||
public class Vibrator {
|
||||
|
||||
public Vibrator() {
|
||||
}
|
||||
|
||||
public boolean hasVibrator() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasAmplitudeControl() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void vibrate(long milliseconds) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void vibrate(long[] pattern, int repeat) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void vibrate(android.os.VibrationEffect vibe) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
// No-op on desktop
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package android.os.storage;
|
||||
|
||||
/**
|
||||
* Minimal StorageManager stub for desktop JVM.
|
||||
*/
|
||||
public class StorageManager {
|
||||
|
||||
public StorageManager() {
|
||||
}
|
||||
|
||||
public java.util.List<android.os.storage.StorageVolume> getStorageVolumes() {
|
||||
return new java.util.ArrayList<>();
|
||||
}
|
||||
|
||||
public android.os.storage.StorageVolume getPrimaryStorageVolume() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public long getPrimaryStorageSize() {
|
||||
return new java.io.File("/").getTotalSpace();
|
||||
}
|
||||
|
||||
public java.util.UUID getUuidForPath(java.io.File path) {
|
||||
return java.util.UUID.randomUUID();
|
||||
}
|
||||
|
||||
public boolean isEncrypted(java.io.File file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isAllocationSupported(java.io.FileDescriptor fd) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package android.telephony;
|
||||
|
||||
/**
|
||||
* Minimal TelephonyManager stub for desktop JVM.
|
||||
*/
|
||||
public class TelephonyManager {
|
||||
|
||||
public static final int NETWORK_TYPE_UNKNOWN = 0;
|
||||
public static final int NETWORK_TYPE_GPRS = 1;
|
||||
public static final int NETWORK_TYPE_EDGE = 2;
|
||||
public static final int NETWORK_TYPE_UMTS = 3;
|
||||
public static final int NETWORK_TYPE_CDMA = 4;
|
||||
public static final int NETWORK_TYPE_EVDO_0 = 5;
|
||||
public static final int NETWORK_TYPE_EVDO_A = 6;
|
||||
public static final int NETWORK_TYPE_1xRTT = 7;
|
||||
public static final int NETWORK_TYPE_HSDPA = 8;
|
||||
public static final int NETWORK_TYPE_HSUPA = 9;
|
||||
public static final int NETWORK_TYPE_HSPA = 10;
|
||||
public static final int NETWORK_TYPE_IDEN = 11;
|
||||
public static final int NETWORK_TYPE_EVDO_B = 12;
|
||||
public static final int NETWORK_TYPE_LTE = 13;
|
||||
public static final int NETWORK_TYPE_EHRPD = 14;
|
||||
public static final int NETWORK_TYPE_HSPAP = 15;
|
||||
public static final int NETWORK_TYPE_GSM = 16;
|
||||
public static final int NETWORK_TYPE_TD_SCDMA = 17;
|
||||
public static final int NETWORK_TYPE_IWLAN = 18;
|
||||
public static final int NETWORK_TYPE_NR = 20;
|
||||
|
||||
public static final int CALL_STATE_IDLE = 0;
|
||||
public static final int CALL_STATE_RINGING = 1;
|
||||
public static final int CALL_STATE_OFFHOOK = 2;
|
||||
|
||||
public static final int DATA_DISCONNECTED = 0;
|
||||
public static final int DATA_CONNECTING = 1;
|
||||
public static final int DATA_CONNECTED = 2;
|
||||
public static final int DATA_SUSPENDED = 3;
|
||||
|
||||
public static final int SIM_STATE_UNKNOWN = 0;
|
||||
public static final int SIM_STATE_ABSENT = 1;
|
||||
public static final int SIM_STATE_PIN_REQUIRED = 2;
|
||||
public static final int SIM_STATE_PUK_REQUIRED = 3;
|
||||
public static final int SIM_STATE_NETWORK_LOCKED = 4;
|
||||
public static final int SIM_STATE_READY = 5;
|
||||
|
||||
public TelephonyManager() {
|
||||
}
|
||||
|
||||
public String getDeviceId() {
|
||||
return "000000000000000";
|
||||
}
|
||||
|
||||
public String getDeviceId(int slotIndex) {
|
||||
return "000000000000000";
|
||||
}
|
||||
|
||||
public String getImei() {
|
||||
return "000000000000000";
|
||||
}
|
||||
|
||||
public String getImei(int slotIndex) {
|
||||
return "000000000000000";
|
||||
}
|
||||
|
||||
public String getMeid() {
|
||||
return "00000000000000";
|
||||
}
|
||||
|
||||
public String getMeid(int slotIndex) {
|
||||
return "00000000000000";
|
||||
}
|
||||
|
||||
public String getSubscriberId() {
|
||||
return "000000000000000";
|
||||
}
|
||||
|
||||
public String getGroupIdLevel1() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getLine1Number() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getNetworkCountryIso() {
|
||||
return "US";
|
||||
}
|
||||
|
||||
public String getSimCountryIso() {
|
||||
return "US";
|
||||
}
|
||||
|
||||
public String getNetworkOperator() {
|
||||
return "00000";
|
||||
}
|
||||
|
||||
public String getNetworkOperatorName() {
|
||||
return "Desktop";
|
||||
}
|
||||
|
||||
public String getSimOperator() {
|
||||
return "00000";
|
||||
}
|
||||
|
||||
public String getSimOperatorName() {
|
||||
return "Desktop";
|
||||
}
|
||||
|
||||
public int getCallState() {
|
||||
return CALL_STATE_IDLE;
|
||||
}
|
||||
|
||||
public int getDataState() {
|
||||
return DATA_DISCONNECTED;
|
||||
}
|
||||
|
||||
public int getDataActivity() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getNetworkType() {
|
||||
return NETWORK_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
public int getPhoneType() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getSimState() {
|
||||
return SIM_STATE_ABSENT;
|
||||
}
|
||||
|
||||
public int getSimState(int slotIndex) {
|
||||
return SIM_STATE_ABSENT;
|
||||
}
|
||||
|
||||
public boolean isNetworkRoaming() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasIccCard() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getDataNetworkType() {
|
||||
return NETWORK_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
public int getVoiceNetworkType() {
|
||||
return NETWORK_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
public boolean isSmsCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isVoiceCapable() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
87
androidcompat/src/main/java/android/view/Display.java
Normal file
87
androidcompat/src/main/java/android/view/Display.java
Normal file
@@ -0,0 +1,87 @@
|
||||
package android.view;
|
||||
|
||||
/**
|
||||
* Minimal Display stub for desktop JVM.
|
||||
*/
|
||||
public class Display {
|
||||
|
||||
public static final int DEFAULT_DISPLAY = 0;
|
||||
public static final int INVALID_DISPLAY = -1;
|
||||
public static final int STATE_UNKNOWN = 0;
|
||||
public static final int STATE_OFF = 1;
|
||||
public static final int STATE_ON = 2;
|
||||
public static final int STATE_DOZE = 3;
|
||||
public static final int STATE_DOZE_SUSPEND = 4;
|
||||
public static final int STATE_VR = 5;
|
||||
public static final int STATE_ON_SUSPEND = 6;
|
||||
|
||||
public Display() {
|
||||
}
|
||||
|
||||
public static Display getDisplay(int displayId) {
|
||||
return new Display();
|
||||
}
|
||||
|
||||
public int getDisplayId() {
|
||||
return DEFAULT_DISPLAY;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "Desktop Display";
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return 1920;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return 1080;
|
||||
}
|
||||
|
||||
public int getRotation() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getOrientation() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public float getRefreshRate() {
|
||||
return 60.0f;
|
||||
}
|
||||
|
||||
public int getState() {
|
||||
return STATE_ON;
|
||||
}
|
||||
|
||||
public void getMetrics(android.util.DisplayMetrics outMetrics) {
|
||||
if (outMetrics != null) {
|
||||
outMetrics.widthPixels = getWidth();
|
||||
outMetrics.heightPixels = getHeight();
|
||||
outMetrics.density = 1.0f;
|
||||
outMetrics.densityDpi = 160;
|
||||
outMetrics.scaledDensity = 1.0f;
|
||||
outMetrics.xdpi = 160.0f;
|
||||
outMetrics.ydpi = 160.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public void getRealMetrics(android.util.DisplayMetrics outMetrics) {
|
||||
getMetrics(outMetrics);
|
||||
}
|
||||
|
||||
public void getSize(android.graphics.Point outSize) {
|
||||
if (outSize != null) {
|
||||
outSize.x = getWidth();
|
||||
outSize.y = getHeight();
|
||||
}
|
||||
}
|
||||
|
||||
public void getRealSize(android.graphics.Point outSize) {
|
||||
getSize(outSize);
|
||||
}
|
||||
|
||||
public int getFlags() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
30
androidcompat/src/main/java/android/view/LayoutInflater.java
Normal file
30
androidcompat/src/main/java/android/view/LayoutInflater.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package android.view;
|
||||
|
||||
/**
|
||||
* Minimal LayoutInflater stub for desktop JVM.
|
||||
*/
|
||||
public class LayoutInflater {
|
||||
|
||||
public LayoutInflater() {
|
||||
}
|
||||
|
||||
public static android.view.LayoutInflater from(android.content.Context context) {
|
||||
return new android.view.LayoutInflater();
|
||||
}
|
||||
|
||||
public android.view.View inflate(int resource, android.view.ViewGroup root) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public android.view.View inflate(int resource, android.view.ViewGroup root, boolean attachToRoot) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public android.view.View inflate(org.xmlpull.v1.XmlPullParser parser, android.view.ViewGroup root) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public android.view.View inflate(org.xmlpull.v1.XmlPullParser parser, android.view.ViewGroup root, boolean attachToRoot) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
40
androidcompat/src/main/java/android/view/WindowManager.java
Normal file
40
androidcompat/src/main/java/android/view/WindowManager.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package android.view;
|
||||
|
||||
/**
|
||||
* Minimal WindowManager stub for desktop JVM.
|
||||
*/
|
||||
public class WindowManager {
|
||||
|
||||
public WindowManager() {
|
||||
}
|
||||
|
||||
public android.view.Display getDefaultDisplay() {
|
||||
return new android.view.Display();
|
||||
}
|
||||
|
||||
public void removeView(android.view.View view) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void removeViewImmediate(android.view.View view) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void addView(android.view.View view, android.view.ViewGroup.LayoutParams params) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void updateViewLayout(android.view.View view, android.view.ViewGroup.LayoutParams params) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public interface LayoutParams {
|
||||
int MATCH_PARENT = -1;
|
||||
int WRAP_CONTENT = -2;
|
||||
int TYPE_APPLICATION = 2;
|
||||
int TYPE_SYSTEM_ALERT = 2010;
|
||||
int FLAG_NOT_FOCUSABLE = 0x00000008;
|
||||
int FLAG_NOT_TOUCHABLE = 0x00000010;
|
||||
int FLAG_KEEP_SCREEN_ON = 0x00000080;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package android.view.accessibility;
|
||||
|
||||
/**
|
||||
* Minimal AccessibilityManager stub for desktop JVM.
|
||||
*/
|
||||
public class AccessibilityManager {
|
||||
|
||||
public AccessibilityManager() {
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isTouchExplorationEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void sendAccessibilityEvent(android.view.accessibility.AccessibilityEvent event) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void interrupt() {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList() {
|
||||
return new java.util.ArrayList<>();
|
||||
}
|
||||
|
||||
public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackTypeFlags) {
|
||||
return new java.util.ArrayList<>();
|
||||
}
|
||||
|
||||
public void addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener listener) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void removeAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener listener) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener listener) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void removeTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener listener) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public interface AccessibilityStateChangeListener {
|
||||
void onAccessibilityStateChanged(boolean enabled);
|
||||
}
|
||||
|
||||
public interface TouchExplorationStateChangeListener {
|
||||
void onTouchExplorationStateChanged(boolean enabled);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package android.view.inputmethod;
|
||||
|
||||
/**
|
||||
* Minimal InputMethodManager stub for desktop JVM.
|
||||
*/
|
||||
public class InputMethodManager {
|
||||
|
||||
public static final int SHOW_IMPLICIT = 0x0001;
|
||||
public static final int SHOW_FORCED = 0x0002;
|
||||
public static final int HIDE_IMPLICIT_ONLY = 0x0001;
|
||||
public static final int HIDE_NOT_ALWAYS = 0x0002;
|
||||
|
||||
public InputMethodManager() {
|
||||
}
|
||||
|
||||
public boolean showSoftInput(android.view.View view, int flags) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean showSoftInput(android.view.View view, int flags, android.os.ResultReceiver resultReceiver) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hideSoftInputFromWindow(android.os.IBinder windowToken, int flags) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hideSoftInputFromWindow(android.os.IBinder windowToken, int flags, android.os.ResultReceiver resultReceiver) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void toggleSoftInput(int showFlags, int hideFlags) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void restartInput(android.view.View view) {
|
||||
// No-op on desktop
|
||||
}
|
||||
|
||||
public void updateSelection(android.view.View view, int selStart, int selEnd, int candidatesStart, int candidatesEnd) {
|
||||
// No-op on desktop
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,6 @@ import android.content.Context
|
||||
class EditTextPreference(val context: Context?) : Preference() {
|
||||
var dialogTitle: String? = null
|
||||
var dialogMessage: String? = null
|
||||
var entries: Array<String>? = null
|
||||
var entryValues: Array<String> = emptyArray()
|
||||
var summary: String? = null
|
||||
var defaultValue: String? = null
|
||||
var setDefaultValue: ((String) -> Unit) = {defaultValue = it}
|
||||
|
||||
|
||||
@@ -3,9 +3,6 @@ package androidx.preference
|
||||
import android.content.Context
|
||||
|
||||
class ListPreference(val context: Context?) : Preference(){
|
||||
var entries: Array<String>? = null
|
||||
var entryValues: Array<String> = emptyArray()
|
||||
var summary: String? = null
|
||||
var defaultValue: String? = null
|
||||
var setDefaultValue: ((String) -> Unit) = {defaultValue = it}
|
||||
|
||||
|
||||
@@ -3,9 +3,6 @@ package androidx.preference
|
||||
import android.content.Context
|
||||
|
||||
class MultiSelectListPreference(val context: Context?) : Preference() {
|
||||
var entries: Array<String>? = null
|
||||
var entryValues: Array<String> = emptyArray()
|
||||
var summary: String? = null
|
||||
var defaultValue: Set<String>? = null
|
||||
var setDefaultValue: ((Set<String>) -> Unit) = {defaultValue = it}
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@ package androidx.preference
|
||||
open class Preference {
|
||||
var key: String? = null
|
||||
var title: String? = null
|
||||
var entries: Array<String>? = null
|
||||
var entryValues: Array<String> = emptyArray()
|
||||
var summary: String? = null
|
||||
|
||||
fun setKey(key: CharSequence?) {
|
||||
this.key = key.toString()
|
||||
|
||||
@@ -13,56 +13,64 @@ public class PreferenceScreen {
|
||||
List<Preference> listPreferences = new ArrayList<>();
|
||||
|
||||
public PreferenceScreen(Context context, SharedPreferences sharedPrefs) {
|
||||
this.context = context;
|
||||
this.sharedPrefs = sharedPrefs;
|
||||
}
|
||||
|
||||
public boolean addPreference(Preference preference) {
|
||||
listPreferences.add(preference);
|
||||
SharedPreferences.Editor editor = sharedPrefs.edit();
|
||||
if (preference instanceof SwitchPreferenceCompat switchPreference) {
|
||||
if (switchPreference.getDefaultValue() == null) {
|
||||
return false;
|
||||
}
|
||||
sharedPrefs.putBoolean(switchPreference.getKey(), switchPreference.getDefaultValue());
|
||||
editor.putBoolean(switchPreference.getKey(), switchPreference.getDefaultValue());
|
||||
} else if (preference instanceof EditTextPreference editTextPreference) {
|
||||
if (editTextPreference.getDefaultValue() == null) {
|
||||
return false;
|
||||
}
|
||||
sharedPrefs.putString(editTextPreference.getKey(), editTextPreference.getDefaultValue());
|
||||
editor.putString(editTextPreference.getKey(), editTextPreference.getDefaultValue());
|
||||
} else if (preference instanceof ListPreference listPreference) {
|
||||
if (listPreference.getDefaultValue() == null) {
|
||||
return false;
|
||||
}
|
||||
sharedPrefs.putString(listPreference.getKey(), listPreference.getDefaultValue());
|
||||
editor.putString(listPreference.getKey(), listPreference.getDefaultValue());
|
||||
} else if (preference instanceof MultiSelectListPreference multiSelectListPreference) {
|
||||
if (multiSelectListPreference.getDefaultValue() == null) {
|
||||
return false;
|
||||
}
|
||||
sharedPrefs.putStringSet(multiSelectListPreference.getKey(), multiSelectListPreference.getDefaultValue());
|
||||
editor.putStringSet(multiSelectListPreference.getKey(), multiSelectListPreference.getDefaultValue());
|
||||
}
|
||||
editor.apply();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean editPreference(String key, Object value) {
|
||||
for (Preference preference : listPreferences) {
|
||||
if (preference.getKey() != null && preference.getKey().equals(key)) {
|
||||
SharedPreferences.Editor editor = sharedPrefs.edit();
|
||||
if (preference instanceof SwitchPreferenceCompat) {
|
||||
if (value instanceof Boolean booleanValue) {
|
||||
sharedPrefs.putBoolean(key, booleanValue);
|
||||
editor.putBoolean(key, booleanValue);
|
||||
editor.apply();
|
||||
return true;
|
||||
}
|
||||
} else if (preference instanceof EditTextPreference) {
|
||||
if (value instanceof String stringValue) {
|
||||
sharedPrefs.putString(key, stringValue);
|
||||
editor.putString(key, stringValue);
|
||||
editor.apply();
|
||||
return true;
|
||||
}
|
||||
} else if (preference instanceof ListPreference) {
|
||||
if (value instanceof String stringValue) {
|
||||
sharedPrefs.putString(key, stringValue);
|
||||
editor.putString(key, stringValue);
|
||||
editor.apply();
|
||||
return true;
|
||||
}
|
||||
} else if (preference instanceof MultiSelectListPreference) {
|
||||
if (value instanceof String listValue) {
|
||||
sharedPrefs.putStringSet(key, Set.of(listValue.split(";")));
|
||||
editor.putStringSet(key, Set.of(listValue.split(";")));
|
||||
editor.apply();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,6 @@ package androidx.preference
|
||||
import android.content.Context
|
||||
|
||||
class SwitchPreferenceCompat(val context: Context?) : Preference() {
|
||||
var entries: Array<String>? = null
|
||||
var entryValues: Array<String> = emptyArray()
|
||||
var summary: String? = null
|
||||
var defaultValue: Boolean? = null
|
||||
var visible: Boolean = true
|
||||
var setDefaultValue: ((Boolean) -> Unit) = { defaultValue = it }
|
||||
|
||||
@@ -261,6 +261,24 @@
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
<!--
|
||||
Force-include all Kotlin runtime classes.
|
||||
Extensions are loaded dynamically and reference internal Kotlin
|
||||
classes (e.g. SpillingKt) that our core code never directly
|
||||
imports. Without this, maven-shade-plugin strips them.
|
||||
-->
|
||||
<filter>
|
||||
<artifact>org.jetbrains.kotlin:*</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>org.jetbrains.kotlinx:*</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.kanade.tachiyomi.network
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import eu.kanade.tachiyomi.network.interceptor.CloudflareInterceptor
|
||||
import eu.kanade.tachiyomi.network.interceptor.IgnoreGzipInterceptor
|
||||
@@ -26,7 +27,7 @@ class NetworkHelper(
|
||||
.callTimeout(2, TimeUnit.MINUTES)
|
||||
.cache(
|
||||
Cache(
|
||||
directory = File(Context.getCacheDir(), "network_cache"),
|
||||
directory = File(Application.getInstance().getApplicationContext().getCacheDir(), "network_cache"),
|
||||
maxSize = 5L * 1024 * 1024, // 5 MiB
|
||||
),
|
||||
)
|
||||
@@ -67,7 +68,7 @@ class NetworkHelper(
|
||||
|
||||
val client = clientBuilder
|
||||
.addInterceptor(
|
||||
CloudflareInterceptor(Context(), cookieJar, ::defaultUserAgentProvider),
|
||||
CloudflareInterceptor(Application.getInstance().getApplicationContext(), cookieJar, ::defaultUserAgentProvider),
|
||||
)
|
||||
.build()
|
||||
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
mvn clean package
|
||||
|
||||
# Replace the old jar with the new compiled JAR to the app directory and rename it to the expected name
|
||||
cp target/aniyomibridge-core-1.0.0.jar /home/kevin/Projects/k3vinb5_aniyomi_bridge/assets/aniyomibridge-core.jar
|
||||
cp aniyomibridge-core/target/aniyomibridge-core-1.0.0.jar /home/kevin/Projects/k3vinb5_aniyomi_bridge/assets/aniyomibridge-core.jar
|
||||
Reference in New Issue
Block a user