Files
unyo-core/androidcompat/README.md
Kevin Rodrigues Borges ae8bed0fda Improved core code
2026-04-23 04:30:13 +01:00

7.1 KiB

Android Compatibility Module

This module provides Android framework compatibility for running Aniyomi/Tachiyomi extensions on desktop JVM.

How It Works

This module uses a hybrid approach inspired by Suwayomi:

  1. Base Android SDK: Downloads the official Android SDK android.jar from Sable/android-platforms
  2. Custom Stubs: Provides desktop-specific implementations for classes that need different behavior
  3. Jar Patching: Removes SDK classes that have custom implementations to avoid conflicts

Architecture

androidcompat/
├── src/main/java/
│   └── android/              # Custom stub implementations
│       ├── app/              # Application, Service
│       ├── content/          # Context, SharedPreferences
│       ├── graphics/         # Bitmap, Canvas
│       ├── net/              # Uri
│       ├── os/               # Handler, Looper, Build, Environment
│       ├── webkit/           # WebView, WebSettings, WebViewClient
│       ├── widget/           # Toast
│       └── util/             # Log, Base64
├── src/main/java/
│   └── androidx/             # AndroidX compatibility
│       ├── core/             # ContextCompat
│       └── preference/       # Preference classes
├── scripts/
│   └── get-android.sh        # Downloads and patches android.jar
└── pom.xml

Custom Stubs

The following classes have custom desktop implementations:

android.app

  • Application.java - Application lifecycle and preferences
  • Service.java - Background service stub

android.content

  • Context.java - Application context with resource access
  • SharedPreferences.java - Preference storage interface
  • SharedPreferencesImpl.java - Desktop file-based preferences

android.os

  • Handler.java - Message handling (synchronous on desktop)
  • Looper.java - Message loop (simplified for desktop)
  • Build.java - Build information
  • Environment.java - Environment paths

android.webkit

  • WebView.java - WebView using JavaFX WebView
  • WebSettings.java - WebView settings
  • WebViewClient.java - WebView callbacks
  • CookieManager.java - Cookie management

android.graphics

  • Bitmap.java - Image handling

android.net

  • Uri.java - URI parsing

android.widget

  • Toast.java - Toast notifications (logs to console)

android.util

  • Log.java - Logging to stdout/stderr
  • Base64.java - Base64 encoding/decoding

Adding New Stubs

  1. Identify which Android class needs a desktop implementation
  2. Create the class in src/main/java/android/<package>/
  3. Add the class path to scripts/get-android.sh in CUSTOM_CLASSES array
  4. Run mvn clean compile to rebuild with patched JAR

How to Use

The androidcompat module is automatically included as a dependency in the core module. The build process:

  1. Downloads official android.jar from Sable/android-platforms
  2. Removes classes that have custom implementations (to avoid conflicts with our stubs)
  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):

    cd androidcompat
    ./scripts/get-android.sh
    

    Or just run a build:

    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:

mvn clean package -Dexec.skip=true

Manual Download

If automatic download fails, you can manually download:

# Download from Sable/android-platforms
curl -o androidcompat/target/android.jar \
  https://raw.githubusercontent.com/Sable/android-platforms/master/android-34/android.jar

# Then build
mvn clean package -Dexec.skip=true

Extending Android Support

When an extension requires an Android class that doesn't exist:

Create a stub that throws RuntimeException for unimplemented methods:

package android.some.package;

public class SomeClass {
    public void someMethod() {
        throw new RuntimeException("Not implemented: SomeClass.someMethod()");
    }
}

Option 2: Full Desktop Implementation

Provide a desktop-compatible implementation (e.g., using JavaFX instead of Android UI).

Option 3: Use Android SDK Class

If the class works as-is on desktop, just add it to the exclusions list in get-android.sh so it's downloaded from the SDK.

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

Class cast exceptions

  • Custom stub might conflict with SDK class
  • Ensure class is in CUSTOM_CLASSES exclusion list
  • Run mvn clean to rebuild android.jar

References