Changed name to unyo-lib
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# AGENTS.md
|
||||
|
||||
Flutter FFI package bridging to Aniyomi (Kotlin/Java) via JNI.
|
||||
Flutter FFI package bridging to Unyo Core JVM runtime via JNI.
|
||||
|
||||
## Project Type
|
||||
|
||||
@@ -59,7 +59,7 @@ jnigen/
|
||||
├── sanime.yaml, video.yaml, etc. # Per-class generation configs
|
||||
|
||||
assets/
|
||||
└── aniyomibridge-core.jar # Java library (source of JNI bindings)
|
||||
└── unyo-core.jar # Java library (source of JNI bindings)
|
||||
|
||||
jre/
|
||||
├── linux/customjre/ # Custom JRE for Linux builds
|
||||
@@ -70,9 +70,9 @@ jre/
|
||||
|
||||
The `lib/jmodels/j*.dart` files are **auto-generated** from Java classes via JNIGen:
|
||||
|
||||
- Source JAR: `assets/aniyomibridge-core.jar`
|
||||
- Source JAR: `assets/unyo-core.jar`
|
||||
- Configs: `jnigen/*.yaml` (one per Java class)
|
||||
- Generated classes mirror `eu.kanade.tachiyomi.*` and `dev.k3vinb5.aniyomibridge.*`
|
||||
- Generated classes mirror `eu.kanade.tachiyomi.*` and `dev.k3vinb5.unyo.core.*`
|
||||
|
||||
**Never manually edit `jmodels/j*.dart` files**—regenerate via:
|
||||
```bash
|
||||
|
||||
@@ -1,625 +0,0 @@
|
||||
# AniyomiBridge JNI Specification
|
||||
|
||||
> **Version:** 2.0 (Post-Multi-Module Refactor)
|
||||
> **Target:** Flutter JNI integration for `aniyomibridge-core-1.0.0.jar`
|
||||
> **Main Class:** `dev.k3vinb5.aniyomibridge.AniyomiBridge`
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This document specifies the public Java API exposed by `AniyomiBridge.java` for consumption via JNI from Flutter. It covers every method, its signature, the data models that cross the JNI boundary, and the behavioral changes introduced during the multi-module refactor.
|
||||
|
||||
**Key architectural fact:** `AniyomiBridge` is a **singleton-like stateful object**. It maintains internal maps of loaded anime/manga sources keyed by `packageName`. You create one instance and call methods on it. All source lookup is done internally via these maps.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Initialization](#1-initialization)
|
||||
2. [Extension Lifecycle (Anime)](#2-extension-lifecycle-anime)
|
||||
3. [Extension Lifecycle (Manga)](#3-extension-lifecycle-manga)
|
||||
4. [Querying Loaded Extensions](#4-querying-loaded-extensions)
|
||||
5. [Preferences API](#5-preferences-api)
|
||||
6. [Content Fetching (Anime)](#6-content-fetching-anime)
|
||||
7. [Content Fetching (Manga)](#7-content-fetching-manga)
|
||||
8. [Data Models](#8-data-models)
|
||||
9. [Error Handling](#9-error-handling)
|
||||
10. [Breaking Changes from v1](#10-breaking-changes-from-v1)
|
||||
11. [JNI Implementation Notes](#11-jni-implementation-notes)
|
||||
|
||||
---
|
||||
|
||||
## 1. Initialization
|
||||
|
||||
### `static void init()`
|
||||
|
||||
Must be called **once** before any other operation. Performs global JVM-level setup:
|
||||
|
||||
- Installs ByteBuddy agent for runtime bytecode patching
|
||||
- Initializes Injekt dependency injection module
|
||||
|
||||
**JNI signature:**
|
||||
```
|
||||
(env)->CallStaticVoidMethod(aniyomiBridgeClass, initMethod);
|
||||
```
|
||||
|
||||
**Thread safety:** Safe to call from any thread, but should only be called once. Not synchronized externally — caller must ensure single invocation.
|
||||
|
||||
**Throws:** Nothing directly, but ByteBuddy installation can fail if the JVM doesn't support instrumentation.
|
||||
|
||||
---
|
||||
|
||||
## 2. Extension Lifecycle (Anime)
|
||||
|
||||
### `void loadAnimeExtension(String extensionUrl, String basePath, String packageName)`
|
||||
|
||||
Downloads an APK from `extensionUrl`, converts it to JAR via dex2jar, loads the main extension class, and registers it as an `AnimeHttpSource`.
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `extensionUrl` | Full HTTPS URL to the `.apk` file |
|
||||
| `basePath` | Local directory path where the converted `.jar` will be cached |
|
||||
| `packageName` | The Android package name (e.g., `eu.kanade.tachiyomi.animeextension.en.animepahe`). Used as the **internal key** for all subsequent lookups. |
|
||||
|
||||
**Behavior:**
|
||||
- Downloads APK if not already present
|
||||
- Converts APK → JAR using dex2jar
|
||||
- Inspects JAR to find the main extension class
|
||||
- Loads class via isolated `URLClassLoader`
|
||||
- Applies ByteBuddy patches to the extension's JVM classes
|
||||
- If the source implements `ConfigurableAnimeSource`, automatically calls `setupPreferenceScreen()` with a managed `PreferenceScreen`
|
||||
- Stores the source in an internal `ConcurrentHashMap` keyed by `packageName`
|
||||
|
||||
**Throws:** `UnyoCoreException` on any failure (download, dex2jar, class loading, casting).
|
||||
|
||||
---
|
||||
|
||||
### `void unloadAnimeExtension(String packageName)`
|
||||
|
||||
Unloads an anime extension and cleans up resources.
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `packageName` | The same `packageName` passed to `loadAnimeExtension` |
|
||||
|
||||
**Behavior:**
|
||||
- Closes the extension's `URLClassLoader`
|
||||
- Deletes the cached JAR file from disk
|
||||
- Removes the source from internal maps
|
||||
|
||||
**Throws:** `UnyoCoreException` on cleanup failure.
|
||||
|
||||
---
|
||||
|
||||
## 3. Extension Lifecycle (Manga)
|
||||
|
||||
### `void loadMangaExtension(String extensionUrl, String basePath, String packageName)`
|
||||
|
||||
Identical to `loadAnimeExtension` but for manga sources implementing `CatalogueSource`.
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `extensionUrl` | Full HTTPS URL to the `.apk` file |
|
||||
| `basePath` | Local directory path where the converted `.jar` will be cached |
|
||||
| `packageName` | Android package name, used as internal key |
|
||||
|
||||
**Behavior:** Same as anime version, but casts to `CatalogueSource` and calls `ConfigurableSource.setupPreferenceScreen()` if applicable.
|
||||
|
||||
**Throws:** `UnyoCoreException`
|
||||
|
||||
---
|
||||
|
||||
### `void unloadMangaExtension(String packageName)`
|
||||
|
||||
Unloads a manga extension.
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `packageName` | The same `packageName` passed to `loadMangaExtension` |
|
||||
|
||||
**Throws:** `UnyoCoreException`
|
||||
|
||||
---
|
||||
|
||||
## 4. Querying Loaded Extensions
|
||||
|
||||
### `List<String> getAnimeLoadedExtensions()`
|
||||
|
||||
Returns a list of loaded anime extension package names.
|
||||
|
||||
**Return:** `java.util.List<java.lang.String>` — package names of all currently loaded anime sources.
|
||||
|
||||
---
|
||||
|
||||
### `List<String> getMangaLoadedExtensions()`
|
||||
|
||||
Returns a list of loaded manga extension package names.
|
||||
|
||||
**Return:** `java.util.List<java.lang.String>` — package names of all currently loaded manga sources.
|
||||
|
||||
---
|
||||
|
||||
## 5. Preferences API
|
||||
|
||||
> **New in v2.** Previously, preferences were not exposed to Flutter. Now they are fully readable and writable.
|
||||
|
||||
When a `ConfigurableAnimeSource` or `ConfigurableSource` is loaded, `AniyomiBridge` automatically calls `setupPreferenceScreen(screen)` and creates a `PreferenceScreen` backed by file-based `SharedPreferences` (stored under `~/.aniyomibridge/shared_prefs/<source-id>.xml`).
|
||||
|
||||
### `List<PreferenceItem> getAnimePreferences(String packageName)`
|
||||
|
||||
Reads all preferences registered by an anime extension.
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `packageName` | Package name of the loaded anime extension |
|
||||
|
||||
**Return:** `java.util.List<PreferenceItem>`
|
||||
|
||||
**Behavior:**
|
||||
- Returns empty list if source is not configurable
|
||||
- Iterates all `Preference` objects on the source's `PreferenceScreen`
|
||||
- Reads current value from `SharedPreferences` (or default if never set)
|
||||
- Returns typed values based on preference type
|
||||
|
||||
**Supported preference types:**
|
||||
|
||||
| Type | Java Type | Value Type |
|
||||
|------|-----------|------------|
|
||||
| `SwitchPreferenceCompat` | `Boolean` | `true` / `false` |
|
||||
| `ListPreference` | `String` | Selected entry value |
|
||||
| `EditTextPreference` | `String` | User input text |
|
||||
| `MultiSelectListPreference` | `Set<String>` | Selected values |
|
||||
| `Preference` (fallback) | `null` | No value |
|
||||
|
||||
---
|
||||
|
||||
### `void setAnimePreference(String packageName, String key, Object value)`
|
||||
|
||||
Sets a single preference value for an anime extension.
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `packageName` | Package name of the loaded anime extension |
|
||||
| `key` | Preference key (from `getAnimePreferences`) |
|
||||
| `value` | Value to set. Must match the expected type: `Boolean`, `String`, or `Set<String>` |
|
||||
|
||||
**Throws:** `UnyoCoreException` if source not configurable, key not found, or type mismatch.
|
||||
|
||||
---
|
||||
|
||||
### `void setAnimePreferences(String packageName, Map<String, Object> values)`
|
||||
|
||||
Batch-updates multiple preferences for an anime extension.
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `packageName` | Package name of the loaded anime extension |
|
||||
| `values` | `java.util.Map` of `key → value` pairs |
|
||||
|
||||
**Behavior:** Iterates the map and calls `setAnimePreference` logic for each entry. Fails fast on first error.
|
||||
|
||||
**Throws:** `UnyoCoreException`
|
||||
|
||||
> **Note:** Manga preferences API is **not yet exposed** in `AniyomiBridge.java`. If needed, the same pattern applies using `CatalogueSource` / `ConfigurableSource`.
|
||||
|
||||
---
|
||||
|
||||
## 6. Content Fetching (Anime)
|
||||
|
||||
All content-fetching methods are **synchronous blocking calls** that internally run Kotlin coroutines via `runBlocking`. Call them from background threads in Flutter.
|
||||
|
||||
### `List<SAnime> getAnimeSearchResults(String query, int page, String packageName)`
|
||||
|
||||
Searches for anime using the specified extension.
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `query` | Search query string |
|
||||
| `page` | Page number (1-based) |
|
||||
| `packageName` | Package name of the loaded anime extension |
|
||||
|
||||
**Return:** `java.util.List<SAnime>`
|
||||
|
||||
**Throws:** `UnyoCoreException` wrapping any network or parsing error.
|
||||
|
||||
---
|
||||
|
||||
### `List<SEpisode> getEpisodeList(SAnime anime, String packageName)`
|
||||
|
||||
Fetches the episode list for a given anime.
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `anime` | `SAnime` object (from search results or previous call) |
|
||||
| `packageName` | Package name of the loaded anime extension |
|
||||
|
||||
**Return:** `java.util.List<SEpisode>`
|
||||
|
||||
**Throws:** `UnyoCoreException`
|
||||
|
||||
---
|
||||
|
||||
### `List<Video> getVideoList(SEpisode episode, String packageName)`
|
||||
|
||||
Fetches video URLs/metadata for a given episode.
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `episode` | `SEpisode` object |
|
||||
| `packageName` | Package name of the loaded anime extension |
|
||||
|
||||
**Return:** `java.util.List<Video>`
|
||||
|
||||
**Throws:** `UnyoCoreException`
|
||||
|
||||
> **Important:** The `Video` class contains `okhttp3.Headers` which is **not serializable by default**. If you need to pass video data across JNI/Flutter isolates, consider using `SerializableVideo` (see Data Models).
|
||||
|
||||
---
|
||||
|
||||
## 7. Content Fetching (Manga)
|
||||
|
||||
### `List<SManga> getMangaSearchResults(String query, int page, String packageName)`
|
||||
|
||||
Searches for manga.
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `query` | Search query string |
|
||||
| `page` | Page number (1-based) |
|
||||
| `packageName` | Package name of the loaded manga extension |
|
||||
|
||||
**Return:** `java.util.List<SManga>`
|
||||
|
||||
**Throws:** `UnyoCoreException`
|
||||
|
||||
---
|
||||
|
||||
### `List<SChapter> getChapterList(SManga manga, String packageName)`
|
||||
|
||||
Fetches chapter list for a manga.
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `manga` | `SManga` object |
|
||||
| `packageName` | Package name of the loaded manga extension |
|
||||
|
||||
**Return:** `java.util.List<SChapter>`
|
||||
|
||||
**Throws:** `UnyoCoreException`
|
||||
|
||||
---
|
||||
|
||||
### `List<Page> getPageList(SChapter chapter, String packageName)`
|
||||
|
||||
Fetches image page URLs for a chapter.
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `chapter` | `SChapter` object |
|
||||
| `packageName` | Package name of the loaded manga extension |
|
||||
|
||||
**Return:** `java.util.List<Page>`
|
||||
|
||||
**Throws:** `UnyoCoreException`
|
||||
|
||||
---
|
||||
|
||||
## 8. Data Models
|
||||
|
||||
### `PreferenceItem`
|
||||
|
||||
**Package:** `dev.k3vinb5.aniyomibridge.PreferenceItem`
|
||||
|
||||
**Fields:**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `key` | `String` | Unique preference identifier |
|
||||
| `title` | `String` | Human-readable title |
|
||||
| `type` | `String` | One of: `SwitchPreferenceCompat`, `ListPreference`, `EditTextPreference`, `MultiSelectListPreference`, `Preference` |
|
||||
| `value` | `Object` | Current value (`Boolean`, `String`, or `Set<String>`) |
|
||||
| `entries` | `List<String>` | Display labels (for List/MultiSelect) |
|
||||
| `entryValues` | `List<String>` | Internal values (for List/MultiSelect) |
|
||||
| `summary` | `String` | Optional description text |
|
||||
|
||||
**JNI tip:** Access fields directly (they are `public`). No getters/setters.
|
||||
|
||||
---
|
||||
|
||||
### `SAnime`
|
||||
|
||||
**Package:** `eu.kanade.tachiyomi.animesource.model.SAnime`
|
||||
|
||||
**Interface fields (all `public`):**
|
||||
|
||||
| Field | Type | Notes |
|
||||
|-------|------|-------|
|
||||
| `url` | `String` | Relative or absolute URL to the anime page |
|
||||
| `title` | `String` | Display title |
|
||||
| `artist` | `String?` | Nullable |
|
||||
| `author` | `String?` | Nullable |
|
||||
| `description` | `String?` | Nullable |
|
||||
| `genre` | `String?` | Nullable; comma-separated genres |
|
||||
| `status` | `int` | `UNKNOWN=0`, `ONGOING=1`, `COMPLETED=2`, `LICENSED=3`, `PUBLISHING_FINISHED=4`, `CANCELLED=5`, `ON_HIATUS=6` |
|
||||
| `thumbnail_url` | `String?` | Cover image URL |
|
||||
| `update_strategy` | `AnimeUpdateStrategy` | Enum |
|
||||
| `fetch_type` | `FetchType` | Enum |
|
||||
| `season_number` | `double` | Season number |
|
||||
| `initialized` | `boolean` | Whether full metadata has been fetched |
|
||||
|
||||
**Method:** `List<String> getGenres()` — parses `genre` string into a list.
|
||||
|
||||
---
|
||||
|
||||
### `SEpisode`
|
||||
|
||||
**Package:** `eu.kanade.tachiyomi.animesource.model.SEpisode`
|
||||
|
||||
**Interface fields:**
|
||||
|
||||
| Field | Type | Notes |
|
||||
|-------|------|-------|
|
||||
| `url` | `String` | Episode page URL |
|
||||
| `name` | `String` | Episode title/number |
|
||||
| `date_upload` | `long` | Unix timestamp (ms) |
|
||||
| `episode_number` | `float` | Numeric episode number |
|
||||
| `scanlator` | `String?` | Nullable |
|
||||
|
||||
---
|
||||
|
||||
### `Video`
|
||||
|
||||
**Package:** `eu.kanade.tachiyomi.animesource.model.Video`
|
||||
|
||||
**Fields:**
|
||||
|
||||
| Field | Type | Notes |
|
||||
|-------|------|-------|
|
||||
| `videoUrl` | `String` | Direct video stream URL |
|
||||
| `videoTitle` | `String` | Quality label (e.g., "1080p") |
|
||||
| `resolution` | `Integer?` | Nullable resolution in pixels |
|
||||
| `bitrate` | `Integer?` | Nullable bitrate |
|
||||
| `headers` | `okhttp3.Headers?` | HTTP headers required for playback |
|
||||
| `preferred` | `boolean` | Whether this is the preferred quality |
|
||||
| `subtitleTracks` | `List<Track>` | Subtitle tracks |
|
||||
| `audioTracks` | `List<Track>` | Audio tracks |
|
||||
| `timestamps` | `List<TimeStamp>` | Chapter/intro markers |
|
||||
| `mpvArgs` | `List<Pair<String,String>>` | MPV player arguments |
|
||||
| `ffmpegStreamArgs` | `List<Pair<String,String>>` | FFmpeg stream arguments |
|
||||
| `ffmpegVideoArgs` | `List<Pair<String,String>>` | FFmpeg video arguments |
|
||||
| `internalData` | `String` | Opaque internal data from extractor |
|
||||
| `initialized` | `boolean` | Whether video metadata is resolved |
|
||||
|
||||
**Deprecation notice:** Old extensions may use `quality` (maps to `videoTitle`) and `url` (maps to internal `videoPageUrl`). New code should use `videoTitle` and `videoUrl`.
|
||||
|
||||
---
|
||||
|
||||
### `SManga`
|
||||
|
||||
**Package:** `eu.kanade.tachiyomi.source.model.SManga`
|
||||
|
||||
Identical structure to `SAnime` but without `fetch_type`, `season_number`, and `update_strategy` is `UpdateStrategy` instead of `AnimeUpdateStrategy`.
|
||||
|
||||
---
|
||||
|
||||
### `SChapter`
|
||||
|
||||
**Package:** `eu.kanade.tachiyomi.source.model.SChapter`
|
||||
|
||||
Identical structure to `SEpisode` but `chapter_number` instead of `episode_number`.
|
||||
|
||||
---
|
||||
|
||||
### `Page`
|
||||
|
||||
**Package:** `eu.kanade.tachiyomi.source.model.Page`
|
||||
|
||||
**Fields:**
|
||||
|
||||
| Field | Type | Notes |
|
||||
|-------|------|-------|
|
||||
| `index` | `int` | Zero-based page index |
|
||||
| `url` | `String` | Page URL (may be relative) |
|
||||
| `imageUrl` | `String?` | Resolved direct image URL |
|
||||
| `number` | `int` | Human-readable page number (`index + 1`) |
|
||||
|
||||
---
|
||||
|
||||
## 9. Error Handling
|
||||
|
||||
### `UnyoCoreException`
|
||||
|
||||
**Package:** `dev.k3vinb5.aniyomibridge.exceptions.UnyoCoreException`
|
||||
|
||||
Extends `RuntimeException`.
|
||||
|
||||
**Constructors:**
|
||||
- `UnyoCoreException(String message)`
|
||||
- `UnyoCoreException(String message, Throwable cause)`
|
||||
|
||||
**Behavior:** Every public method in `AniyomiBridge` wraps failures in `UnyoCoreException` with the full Java stack trace in the message string. When catching via JNI, you get both the user-friendly message and the developer stack trace.
|
||||
|
||||
**Recommended Flutter handling:**
|
||||
```dart
|
||||
// Pseudocode — depends on your JNI bindings
|
||||
try {
|
||||
final results = bridge.getAnimeSearchResults(query, page, packageName);
|
||||
} on JniException catch (e) {
|
||||
// e.message contains both the summary and the full Java stack trace
|
||||
log.error(e.message);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Breaking Changes from v1
|
||||
|
||||
If your Flutter code was written against the pre-refactor API (before multi-module split), these are the critical changes:
|
||||
|
||||
### 1. Extension keys changed from `extensionName` to `packageName`
|
||||
|
||||
**Before:**
|
||||
```java
|
||||
loadAnimeExtension(String extensionUrl, String basePath)
|
||||
// Key was extracted from URL: "animepahe", "torrentio", etc.
|
||||
|
||||
unloadAnimeExtension(String extensionName, String version, String basePath)
|
||||
// You passed extensionName + version, bridge constructed filename
|
||||
```
|
||||
|
||||
**After:**
|
||||
```java
|
||||
loadAnimeExtension(String extensionUrl, String basePath, String packageName)
|
||||
// You pass the full Android package name as key
|
||||
|
||||
unloadAnimeExtension(String packageName)
|
||||
// Just packageName. Bridge tracks the JAR path internally.
|
||||
```
|
||||
|
||||
**Migration:**
|
||||
- Stop extracting extension names from URLs
|
||||
- Use the Android package name (from the extension repo JSON) as the key everywhere
|
||||
- Update your Flutter model to pass `packageName` to all methods
|
||||
|
||||
### 2. `getAnimeSearchResults` / `getMangaSearchResults` signature change
|
||||
|
||||
**Before:**
|
||||
```java
|
||||
getAnimeSearchResults(String query, int page, String animeSource)
|
||||
// 'animeSource' was the extension name
|
||||
```
|
||||
|
||||
**After:**
|
||||
```java
|
||||
getAnimeSearchResults(String query, int page, String packageName)
|
||||
// 'packageName' is the full package name
|
||||
```
|
||||
|
||||
**Migration:** Pass `packageName` instead of extension name.
|
||||
|
||||
### 3. Content fetching methods signature change
|
||||
|
||||
**Before:**
|
||||
```java
|
||||
getEpisodeList(SAnime anime, String animeSource)
|
||||
getVideoList(SEpisode episode, String animeSource)
|
||||
```
|
||||
|
||||
**After:**
|
||||
```java
|
||||
getEpisodeList(SAnime anime, String packageName)
|
||||
getVideoList(SEpisode episode, String packageName)
|
||||
```
|
||||
|
||||
**Migration:** Same as above — replace `animeSource` string with `packageName`.
|
||||
|
||||
### 4. Removal of `correctedNames` map
|
||||
|
||||
**Before:** The bridge internally mapped names like `"zoro" → "hianime"` and `"aniwatch" → "aniwatchtv"`.
|
||||
|
||||
**After:** No internal name correction. You must use the exact `packageName`.
|
||||
|
||||
**Migration:** Remove any logic in Flutter that relied on these aliases. Use package names directly from the repo metadata.
|
||||
|
||||
### 5. Unload methods no longer take `version` or `basePath`
|
||||
|
||||
**Before:**
|
||||
```java
|
||||
unloadAnimeExtension(String extensionName, String version, String basePath)
|
||||
```
|
||||
|
||||
**After:**
|
||||
```java
|
||||
unloadAnimeExtension(String packageName)
|
||||
```
|
||||
|
||||
**Migration:** Simpler — just pass `packageName`.
|
||||
|
||||
### 6. Preferences API is new
|
||||
|
||||
**Before:** No way to read/write extension preferences from Flutter.
|
||||
|
||||
**After:** Full `getAnimePreferences`, `setAnimePreference`, `setAnimePreferences` API.
|
||||
|
||||
**Migration:** If your app previously couldn't handle configurable sources, now you can/should expose these preferences in your UI.
|
||||
|
||||
### 7. `MediaSourceUtils` now uses per-source filters
|
||||
|
||||
**Before:**
|
||||
```kotlin
|
||||
animeSource.getSearchAnime(page, query, filters = defaultAnimeFilterList)
|
||||
```
|
||||
|
||||
**After:**
|
||||
```kotlin
|
||||
animeSource.getSearchAnime(page, query, filters = animeSource.getFilterList())
|
||||
```
|
||||
|
||||
**Impact:** Search results may differ if an extension had custom filters. This is generally more correct but could change behavior for extensions that rely on non-default filter states.
|
||||
|
||||
---
|
||||
|
||||
## 11. JNI Implementation Notes
|
||||
|
||||
### Class Loading
|
||||
|
||||
The fat JAR (`aniyomibridge-core-1.0.0.jar`) contains everything including the Android SDK stubs, Kotlin stdlib, and all dependencies. Load it with a standard `URLClassLoader` or from the classpath.
|
||||
|
||||
**Important:** The `Main.class` (`dev.k3vinb5.aniyomibridge.Main`) is excluded from the fat JAR (consumed by external Flutter app). The class you instantiate is `dev.k3vinb5.aniyomibridge.AniyomiBridge`.
|
||||
|
||||
### Threading
|
||||
|
||||
All content-fetching methods use `kotlinx.coroutines.runBlocking` internally. They **will block the calling thread**. In Flutter, always call these methods through a background isolate or `compute()` / `Isolate.run()`.
|
||||
|
||||
The internal maps (`animeSources`, `mangaSources`, `classLoaders`) use `ConcurrentHashMap`, so `load*` and `unload*` are thread-safe. However, you should not load and unload the same extension concurrently.
|
||||
|
||||
### Object Lifetimes
|
||||
|
||||
`SAnime`, `SEpisode`, `SManga`, `SChapter` are `Serializable`. You can safely pass them across JNI boundaries and cache them in Dart if needed.
|
||||
|
||||
`Video` contains `okhttp3.Headers` which is **not serializable**. If you need to serialize video data (e.g., for Dart isolates or JSON), convert `Headers` to a `Map<String, List<String>>` or use the `SerializableVideo` Kotlin helper class.
|
||||
|
||||
### Memory
|
||||
|
||||
Each loaded extension gets its own `URLClassLoader`. When you call `unload*Extension`, the classloader is closed and the JAR file is deleted. This should release most memory, but some classes may remain in the JVM's metaspace until GC.
|
||||
|
||||
### Logging
|
||||
|
||||
The bridge uses JBoss Logging. Logs go to stdout/stderr by default. In a Flutter desktop app, you'll see them in the console. Consider redirecting `java.util.logging` or JBoss LogManager to your Dart logging system if you need structured logs.
|
||||
|
||||
---
|
||||
|
||||
## Appendix: Quick Reference — Method Signatures
|
||||
|
||||
```java
|
||||
// Initialization
|
||||
public static void init()
|
||||
|
||||
// Anime lifecycle
|
||||
public void loadAnimeExtension(String extensionUrl, String basePath, String packageName)
|
||||
public void unloadAnimeExtension(String packageName)
|
||||
|
||||
// Manga lifecycle
|
||||
public void loadMangaExtension(String extensionUrl, String basePath, String packageName)
|
||||
public void unloadMangaExtension(String packageName)
|
||||
|
||||
// Query loaded
|
||||
public List<String> getAnimeLoadedExtensions()
|
||||
public List<String> getMangaLoadedExtensions()
|
||||
|
||||
// Preferences (anime only, currently)
|
||||
public List<PreferenceItem> getAnimePreferences(String packageName)
|
||||
public void setAnimePreference(String packageName, String key, Object value)
|
||||
public void setAnimePreferences(String packageName, Map<String, Object> values)
|
||||
|
||||
// Anime content
|
||||
public List<SAnime> getAnimeSearchResults(String query, int page, String packageName)
|
||||
public List<SEpisode> getEpisodeList(SAnime anime, String packageName)
|
||||
public List<Video> getVideoList(SEpisode episode, String packageName)
|
||||
|
||||
// Manga content
|
||||
public List<SManga> getMangaSearchResults(String query, int page, String packageName)
|
||||
public List<SChapter> getChapterList(SManga manga, String packageName)
|
||||
public List<Page> getPageList(SChapter chapter, String packageName)
|
||||
```
|
||||
Binary file not shown.
@@ -4,11 +4,11 @@ import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:k3vinb5_aniyomi_bridge/aniyomi_bridge.dart';
|
||||
import 'package:k3vinb5_aniyomi_bridge/jmodels/jpreferenceitem.dart';
|
||||
import 'package:k3vinb5_aniyomi_bridge/jmodels/jsanime.dart';
|
||||
import 'package:k3vinb5_aniyomi_bridge/jmodels/jsepisode.dart';
|
||||
import 'package:k3vinb5_aniyomi_bridge/jmodels/jvideo.dart';
|
||||
import 'package:unyo_lib/aniyomi_bridge.dart';
|
||||
import 'package:unyo_lib/jmodels/jpreferenceitem.dart';
|
||||
import 'package:unyo_lib/jmodels/jsanime.dart';
|
||||
import 'package:unyo_lib/jmodels/jsepisode.dart';
|
||||
import 'package:unyo_lib/jmodels/jvideo.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const BridgeTesterApp());
|
||||
|
||||
@@ -147,13 +147,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.9.0"
|
||||
k3vinb5_aniyomi_bridge:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -375,6 +368,13 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
unyo_lib:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -36,7 +36,7 @@ dependencies:
|
||||
cupertino_icons: ^1.0.8
|
||||
http: ^1.2.0
|
||||
path: ^1.9.0
|
||||
k3vinb5_aniyomi_bridge:
|
||||
unyo_lib:
|
||||
path: ../
|
||||
|
||||
dev_dependencies:
|
||||
|
||||
@@ -13,7 +13,7 @@ PROJECT_DIR=$(pwd)
|
||||
case "$PLATFORM" in
|
||||
macos)
|
||||
# Locate Flutter macOS build output
|
||||
JRE_SRC="/Users/kevin/IdeaProjects/k3vinb5_aniyomi_bridge/jre/$PLATFORM/customjre"
|
||||
JRE_SRC="/Users/kevin/IdeaProjects/unyo-lib/jre/$PLATFORM/customjre"
|
||||
if [ ! -d "$JRE_SRC" ]; then
|
||||
echo "Error: JRE source folder not found: $JRE_SRC"
|
||||
exit 1
|
||||
@@ -27,7 +27,7 @@ case "$PLATFORM" in
|
||||
|
||||
linux)
|
||||
# Linux Flutter executable folder
|
||||
JRE_SRC="/home/kevin/Projects/k3vinb5_aniyomi_bridge/jre/$PLATFORM/customjre"
|
||||
JRE_SRC="/home/kevin/Projects/unyo-lib/jre/$PLATFORM/customjre"
|
||||
if [ ! -d "$JRE_SRC" ]; then
|
||||
echo "Error: JRE source folder not found: $JRE_SRC"
|
||||
exit 1
|
||||
|
||||
@@ -13,7 +13,7 @@ PROJECT_DIR=$(pwd)
|
||||
case "$PLATFORM" in
|
||||
macos)
|
||||
# Locate Flutter macOS build output
|
||||
JRE_SRC="/Users/kevin/IdeaProjects/k3vinb5_aniyomi_bridge/jre/$PLATFORM/customjre"
|
||||
JRE_SRC="/Users/kevin/IdeaProjects/unyo-lib/jre/$PLATFORM/customjre"
|
||||
if [ ! -d "$JRE_SRC" ]; then
|
||||
echo "Error: JRE source folder not found: $JRE_SRC"
|
||||
exit 1
|
||||
@@ -27,7 +27,7 @@ case "$PLATFORM" in
|
||||
|
||||
linux)
|
||||
# Linux Flutter executable folder
|
||||
JRE_SRC="/home/kevin/Projects/k3vinb5_aniyomi_bridge/jre/$PLATFORM/customjre"
|
||||
JRE_SRC="/home/kevin/Projects/unyo-lib/jre/$PLATFORM/customjre"
|
||||
if [ ! -d "$JRE_SRC" ]; then
|
||||
echo "Error: JRE source folder not found: $JRE_SRC"
|
||||
exit 1
|
||||
|
||||
@@ -4,6 +4,6 @@ output:
|
||||
structure: single_file
|
||||
|
||||
class_path:
|
||||
- '../assets/aniyomibridge-core.jar'
|
||||
- '../assets/unyo-core.jar'
|
||||
classes:
|
||||
- 'dev.k3vinb5.aniyomibridge.AniyomiBridge'
|
||||
- 'dev.k3vinb5.unyo.core.AniyomiBridge'
|
||||
@@ -4,6 +4,6 @@ output:
|
||||
structure: single_file
|
||||
|
||||
class_path:
|
||||
- '../assets/aniyomibridge-core.jar'
|
||||
- '../assets/unyo-core.jar'
|
||||
classes:
|
||||
- 'okhttp3.Headers'
|
||||
@@ -4,6 +4,6 @@ output:
|
||||
structure: single_file
|
||||
|
||||
class_path:
|
||||
- '../assets/aniyomibridge-core.jar'
|
||||
- '../assets/unyo-core.jar'
|
||||
classes:
|
||||
- 'eu.kanade.tachiyomi.source.model.Page'
|
||||
|
||||
@@ -4,6 +4,6 @@ output:
|
||||
structure: single_file
|
||||
|
||||
class_path:
|
||||
- '../assets/aniyomibridge-core.jar'
|
||||
- '../assets/unyo-core.jar'
|
||||
classes:
|
||||
- 'dev.k3vinb5.aniyomibridge.PreferenceItem'
|
||||
- 'dev.k3vinb5.unyo.core.PreferenceItem'
|
||||
|
||||
@@ -4,6 +4,6 @@ output:
|
||||
structure: single_file
|
||||
|
||||
class_path:
|
||||
- '../assets/aniyomibridge-core.jar'
|
||||
- '../assets/unyo-core.jar'
|
||||
classes:
|
||||
- 'eu.kanade.tachiyomi.animesource.model.SAnime'
|
||||
|
||||
@@ -4,6 +4,6 @@ output:
|
||||
structure: single_file
|
||||
|
||||
class_path:
|
||||
- '../assets/aniyomibridge-core.jar'
|
||||
- '../assets/unyo-core.jar'
|
||||
classes:
|
||||
- 'eu.kanade.tachiyomi.source.model.SChapter'
|
||||
|
||||
@@ -4,6 +4,6 @@ output:
|
||||
structure: single_file
|
||||
|
||||
class_path:
|
||||
- '../assets/aniyomibridge-core.jar'
|
||||
- '../assets/unyo-core.jar'
|
||||
classes:
|
||||
- 'eu.kanade.tachiyomi.animesource.model.SEpisode'
|
||||
|
||||
@@ -4,6 +4,6 @@ output:
|
||||
structure: single_file
|
||||
|
||||
class_path:
|
||||
- '../assets/aniyomibridge-core.jar'
|
||||
- '../assets/unyo-core.jar'
|
||||
classes:
|
||||
- 'eu.kanade.tachiyomi.source.model.SManga'
|
||||
|
||||
@@ -4,6 +4,6 @@ output:
|
||||
structure: single_file
|
||||
|
||||
class_path:
|
||||
- '../assets/aniyomibridge-core.jar'
|
||||
- '../assets/unyo-core.jar'
|
||||
classes:
|
||||
- 'eu.kanade.tachiyomi.animesource.model.Track'
|
||||
@@ -4,6 +4,6 @@ output:
|
||||
structure: single_file
|
||||
|
||||
class_path:
|
||||
- '../assets/aniyomibridge-core.jar'
|
||||
- '../assets/unyo-core.jar'
|
||||
classes:
|
||||
- 'eu.kanade.tachiyomi.animesource.model.Video'
|
||||
|
||||
@@ -4,29 +4,29 @@ import 'dart:isolate';
|
||||
import 'dart:math';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:jni/jni.dart';
|
||||
import 'package:k3vinb5_aniyomi_bridge/jni_isolate.dart';
|
||||
import 'package:k3vinb5_aniyomi_bridge/jni_isolate_message.dart';
|
||||
import 'package:k3vinb5_aniyomi_bridge/models/extension.dart';
|
||||
import 'package:unyo_lib/jni_isolate.dart';
|
||||
import 'package:unyo_lib/jni_isolate_message.dart';
|
||||
import 'package:unyo_lib/models/extension.dart';
|
||||
import 'package:logger/logger.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:k3vinb5_aniyomi_bridge/jmodels/jvideo.dart';
|
||||
import 'package:k3vinb5_aniyomi_bridge/jmodels/jsanime.dart';
|
||||
import 'package:k3vinb5_aniyomi_bridge/jmodels/jsepisode.dart';
|
||||
import 'package:k3vinb5_aniyomi_bridge/jmodels/jsmanga.dart';
|
||||
import 'package:k3vinb5_aniyomi_bridge/jmodels/jschapter.dart';
|
||||
import 'package:k3vinb5_aniyomi_bridge/jmodels/jpage.dart';
|
||||
import 'package:k3vinb5_aniyomi_bridge/jmodels/jpreferenceitem.dart';
|
||||
import 'package:unyo_lib/jmodels/jvideo.dart';
|
||||
import 'package:unyo_lib/jmodels/jsanime.dart';
|
||||
import 'package:unyo_lib/jmodels/jsepisode.dart';
|
||||
import 'package:unyo_lib/jmodels/jsmanga.dart';
|
||||
import 'package:unyo_lib/jmodels/jschapter.dart';
|
||||
import 'package:unyo_lib/jmodels/jpage.dart';
|
||||
import 'package:unyo_lib/jmodels/jpreferenceitem.dart';
|
||||
|
||||
class AniyomiBridge {
|
||||
// static consts
|
||||
static const String _aniyomiBridgeAnimeExtensionsDir = "animeExtensions";
|
||||
static const String _aniyomiBridgeMangaExtensionsDir = "mangaExtensions";
|
||||
static const String _aniyomiBridgeDir = "aniyomibridge";
|
||||
static const String _aniyomiBridgeJarName = "aniyomibridge-core.jar";
|
||||
static const String _aniyomiBridgeJarName = "unyo-core.jar";
|
||||
static const String _packageAssetsDir =
|
||||
"packages/k3vinb5_aniyomi_bridge/assets";
|
||||
"packages/unyo_lib/assets";
|
||||
static const Duration _cacheTtl = Duration(minutes: 20);
|
||||
|
||||
// static variables
|
||||
|
||||
@@ -36,7 +36,7 @@ import 'dart:core' as core$_;
|
||||
import 'package:jni/_internal.dart' as jni$_;
|
||||
import 'package:jni/jni.dart' as jni$_;
|
||||
|
||||
/// from: `dev.k3vinb5.aniyomibridge.AniyomiBridge`
|
||||
/// from: `dev.k3vinb5.unyo.core.AniyomiBridge`
|
||||
class JAniyomiBridge extends jni$_.JObject {
|
||||
@jni$_.internal
|
||||
@core$_.override
|
||||
@@ -48,12 +48,12 @@ class JAniyomiBridge extends jni$_.JObject {
|
||||
super.fromReference(reference);
|
||||
|
||||
static final _class = jni$_.JClass.forName(
|
||||
r'dev/k3vinb5/aniyomibridge/AniyomiBridge',
|
||||
r'dev/k3vinb5/unyo/core/AniyomiBridge',
|
||||
);
|
||||
|
||||
/// The type which includes information such as the signature of this class.
|
||||
static const nullableType = $JAniyomiBridge$NullableType();
|
||||
static const type = $JAniyomiBridge$Type();
|
||||
static const nullableType = $AniyomiBridge$NullableType();
|
||||
static const type = $AniyomiBridge$Type();
|
||||
static final _id_classLoaders = _class.staticFieldId(
|
||||
r'classLoaders',
|
||||
r'Ljava/util/Map;',
|
||||
@@ -444,7 +444,7 @@ class JAniyomiBridge extends jni$_.JObject {
|
||||
)
|
||||
>();
|
||||
|
||||
/// from: `public java.util.List<dev.k3vinb5.aniyomibridge.PreferenceItem> getAnimePreferences(java.lang.String string)`
|
||||
/// from: `public java.util.List<dev.k3vinb5.unyo.core.PreferenceItem> getAnimePreferences(java.lang.String string)`
|
||||
/// The returned object must be released after use, by calling the [release] method.
|
||||
jni$_.JList<jni$_.JObject?>? getAnimePreferences(jni$_.JString? string) {
|
||||
final _$string = string?.reference ?? jni$_.jNullReference;
|
||||
@@ -840,13 +840,13 @@ class JAniyomiBridge extends jni$_.JObject {
|
||||
}
|
||||
}
|
||||
|
||||
final class $JAniyomiBridge$NullableType extends jni$_.JObjType<JAniyomiBridge?> {
|
||||
final class $AniyomiBridge$NullableType extends jni$_.JObjType<JAniyomiBridge?> {
|
||||
@jni$_.internal
|
||||
const $JAniyomiBridge$NullableType();
|
||||
const $AniyomiBridge$NullableType();
|
||||
|
||||
@jni$_.internal
|
||||
@core$_.override
|
||||
String get signature => r'Ldev/k3vinb5/aniyomibridge/AniyomiBridge;';
|
||||
String get signature => r'Ldev/k3vinb5/unyo/core/AniyomiBridge;';
|
||||
|
||||
@jni$_.internal
|
||||
@core$_.override
|
||||
@@ -865,22 +865,22 @@ final class $JAniyomiBridge$NullableType extends jni$_.JObjType<JAniyomiBridge?>
|
||||
final superCount = 1;
|
||||
|
||||
@core$_.override
|
||||
int get hashCode => ($JAniyomiBridge$NullableType).hashCode;
|
||||
int get hashCode => ($AniyomiBridge$NullableType).hashCode;
|
||||
|
||||
@core$_.override
|
||||
bool operator ==(Object other) {
|
||||
return other.runtimeType == ($JAniyomiBridge$NullableType) &&
|
||||
other is $JAniyomiBridge$NullableType;
|
||||
return other.runtimeType == ($AniyomiBridge$NullableType) &&
|
||||
other is $AniyomiBridge$NullableType;
|
||||
}
|
||||
}
|
||||
|
||||
final class $JAniyomiBridge$Type extends jni$_.JObjType<JAniyomiBridge> {
|
||||
final class $AniyomiBridge$Type extends jni$_.JObjType<JAniyomiBridge> {
|
||||
@jni$_.internal
|
||||
const $JAniyomiBridge$Type();
|
||||
const $AniyomiBridge$Type();
|
||||
|
||||
@jni$_.internal
|
||||
@core$_.override
|
||||
String get signature => r'Ldev/k3vinb5/aniyomibridge/AniyomiBridge;';
|
||||
String get signature => r'Ldev/k3vinb5/unyo/core/AniyomiBridge;';
|
||||
|
||||
@jni$_.internal
|
||||
@core$_.override
|
||||
@@ -893,18 +893,18 @@ final class $JAniyomiBridge$Type extends jni$_.JObjType<JAniyomiBridge> {
|
||||
@jni$_.internal
|
||||
@core$_.override
|
||||
jni$_.JObjType<JAniyomiBridge?> get nullableType =>
|
||||
const $JAniyomiBridge$NullableType();
|
||||
const $AniyomiBridge$NullableType();
|
||||
|
||||
@jni$_.internal
|
||||
@core$_.override
|
||||
final superCount = 1;
|
||||
|
||||
@core$_.override
|
||||
int get hashCode => ($JAniyomiBridge$Type).hashCode;
|
||||
int get hashCode => ($AniyomiBridge$Type).hashCode;
|
||||
|
||||
@core$_.override
|
||||
bool operator ==(Object other) {
|
||||
return other.runtimeType == ($JAniyomiBridge$Type) &&
|
||||
other is $JAniyomiBridge$Type;
|
||||
return other.runtimeType == ($AniyomiBridge$Type) &&
|
||||
other is $AniyomiBridge$Type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -816,6 +816,39 @@ class JHeaders extends jni$_.JObject {
|
||||
static Headers$Companion get Companion =>
|
||||
_id_Companion.get(_class, const $Headers$Companion$Type());
|
||||
|
||||
static final _id_new$ = _class.constructorId(r'([Ljava/lang/String;)V');
|
||||
|
||||
static final _new$ =
|
||||
jni$_.ProtectedJniExtensions.lookup<
|
||||
jni$_.NativeFunction<
|
||||
jni$_.JniResult Function(
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.JMethodIDPtr,
|
||||
jni$_.VarArgs<(jni$_.Pointer<jni$_.Void>,)>,
|
||||
)
|
||||
>
|
||||
>('globalEnv_NewObject')
|
||||
.asFunction<
|
||||
jni$_.JniResult Function(
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.JMethodIDPtr,
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
)
|
||||
>();
|
||||
|
||||
/// from: `public void <init>(java.lang.String[] strings)`
|
||||
/// The returned object must be released after use, by calling the [release] method.
|
||||
factory JHeaders(jni$_.JArray<jni$_.JString> strings) {
|
||||
final _$strings = strings.reference;
|
||||
return JHeaders.fromReference(
|
||||
_new$(
|
||||
_class.reference.pointer,
|
||||
_id_new$ as jni$_.JMethodIDPtr,
|
||||
_$strings.pointer,
|
||||
).reference,
|
||||
);
|
||||
}
|
||||
|
||||
static final _id_get = _class.instanceMethodId(
|
||||
r'get',
|
||||
r'(Ljava/lang/String;)Ljava/lang/String;',
|
||||
@@ -1355,50 +1388,6 @@ class JHeaders extends jni$_.JObject {
|
||||
).object<JHeaders>(const $Headers$Type());
|
||||
}
|
||||
|
||||
static final _id_new$ = _class.constructorId(
|
||||
r'([Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V',
|
||||
);
|
||||
|
||||
static final _new$ =
|
||||
jni$_.ProtectedJniExtensions.lookup<
|
||||
jni$_.NativeFunction<
|
||||
jni$_.JniResult Function(
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.JMethodIDPtr,
|
||||
jni$_.VarArgs<
|
||||
(jni$_.Pointer<jni$_.Void>, jni$_.Pointer<jni$_.Void>)
|
||||
>,
|
||||
)
|
||||
>
|
||||
>('globalEnv_NewObject')
|
||||
.asFunction<
|
||||
jni$_.JniResult Function(
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.JMethodIDPtr,
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
)
|
||||
>();
|
||||
|
||||
/// from: `synthetic public void <init>(java.lang.String[] strings, kotlin.jvm.internal.DefaultConstructorMarker defaultConstructorMarker)`
|
||||
/// The returned object must be released after use, by calling the [release] method.
|
||||
factory JHeaders(
|
||||
jni$_.JArray<jni$_.JString?>? strings,
|
||||
jni$_.JObject? defaultConstructorMarker,
|
||||
) {
|
||||
final _$strings = strings?.reference ?? jni$_.jNullReference;
|
||||
final _$defaultConstructorMarker =
|
||||
defaultConstructorMarker?.reference ?? jni$_.jNullReference;
|
||||
return JHeaders.fromReference(
|
||||
_new$(
|
||||
_class.reference.pointer,
|
||||
_id_new$ as jni$_.JMethodIDPtr,
|
||||
_$strings.pointer,
|
||||
_$defaultConstructorMarker.pointer,
|
||||
).reference,
|
||||
);
|
||||
}
|
||||
|
||||
jni$_.JString? operator [](jni$_.JString string) {
|
||||
return get(string);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ import 'dart:core' as core$_;
|
||||
import 'package:jni/_internal.dart' as jni$_;
|
||||
import 'package:jni/jni.dart' as jni$_;
|
||||
|
||||
/// from: `dev.k3vinb5.aniyomibridge.JPreferenceItem`
|
||||
/// from: `dev.k3vinb5.unyo.core.PreferenceItem`
|
||||
class JPreferenceItem extends jni$_.JObject {
|
||||
@jni$_.internal
|
||||
@core$_.override
|
||||
@@ -48,12 +48,12 @@ class JPreferenceItem extends jni$_.JObject {
|
||||
super.fromReference(reference);
|
||||
|
||||
static final _class = jni$_.JClass.forName(
|
||||
r'dev/k3vinb5/aniyomibridge/JPreferenceItem',
|
||||
r'dev/k3vinb5/unyo/core/PreferenceItem',
|
||||
);
|
||||
|
||||
/// The type which includes information such as the signature of this class.
|
||||
static const nullableType = $JPreferenceItem$NullableType();
|
||||
static const type = $JPreferenceItem$Type();
|
||||
static const nullableType = $PreferenceItem$NullableType();
|
||||
static const type = $PreferenceItem$Type();
|
||||
static final _id_key = _class.instanceFieldId(r'key', r'Ljava/lang/String;');
|
||||
|
||||
/// from: `public java.lang.String key`
|
||||
@@ -238,14 +238,14 @@ class JPreferenceItem extends jni$_.JObject {
|
||||
}
|
||||
}
|
||||
|
||||
final class $JPreferenceItem$NullableType
|
||||
final class $PreferenceItem$NullableType
|
||||
extends jni$_.JObjType<JPreferenceItem?> {
|
||||
@jni$_.internal
|
||||
const $JPreferenceItem$NullableType();
|
||||
const $PreferenceItem$NullableType();
|
||||
|
||||
@jni$_.internal
|
||||
@core$_.override
|
||||
String get signature => r'Ldev/k3vinb5/aniyomibridge/JPreferenceItem;';
|
||||
String get signature => r'Ldev/k3vinb5/unyo/core/PreferenceItem;';
|
||||
|
||||
@jni$_.internal
|
||||
@core$_.override
|
||||
@@ -264,22 +264,22 @@ final class $JPreferenceItem$NullableType
|
||||
final superCount = 1;
|
||||
|
||||
@core$_.override
|
||||
int get hashCode => ($JPreferenceItem$NullableType).hashCode;
|
||||
int get hashCode => ($PreferenceItem$NullableType).hashCode;
|
||||
|
||||
@core$_.override
|
||||
bool operator ==(Object other) {
|
||||
return other.runtimeType == ($JPreferenceItem$NullableType) &&
|
||||
other is $JPreferenceItem$NullableType;
|
||||
return other.runtimeType == ($PreferenceItem$NullableType) &&
|
||||
other is $PreferenceItem$NullableType;
|
||||
}
|
||||
}
|
||||
|
||||
final class $JPreferenceItem$Type extends jni$_.JObjType<JPreferenceItem> {
|
||||
final class $PreferenceItem$Type extends jni$_.JObjType<JPreferenceItem> {
|
||||
@jni$_.internal
|
||||
const $JPreferenceItem$Type();
|
||||
const $PreferenceItem$Type();
|
||||
|
||||
@jni$_.internal
|
||||
@core$_.override
|
||||
String get signature => r'Ldev/k3vinb5/aniyomibridge/JPreferenceItem;';
|
||||
String get signature => r'Ldev/k3vinb5/unyo/core/PreferenceItem;';
|
||||
|
||||
@jni$_.internal
|
||||
@core$_.override
|
||||
@@ -292,18 +292,18 @@ final class $JPreferenceItem$Type extends jni$_.JObjType<JPreferenceItem> {
|
||||
@jni$_.internal
|
||||
@core$_.override
|
||||
jni$_.JObjType<JPreferenceItem?> get nullableType =>
|
||||
const $JPreferenceItem$NullableType();
|
||||
const $PreferenceItem$NullableType();
|
||||
|
||||
@jni$_.internal
|
||||
@core$_.override
|
||||
final superCount = 1;
|
||||
|
||||
@core$_.override
|
||||
int get hashCode => ($JPreferenceItem$Type).hashCode;
|
||||
int get hashCode => ($PreferenceItem$Type).hashCode;
|
||||
|
||||
@core$_.override
|
||||
bool operator ==(Object other) {
|
||||
return other.runtimeType == ($JPreferenceItem$Type) &&
|
||||
other is $JPreferenceItem$Type;
|
||||
return other.runtimeType == ($PreferenceItem$Type) &&
|
||||
other is $PreferenceItem$Type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'dart:isolate';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:jni/jni.dart';
|
||||
import 'package:k3vinb5_aniyomi_bridge/jni_isolate_message.dart';
|
||||
import 'package:unyo_lib/jni_isolate_message.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import 'jmodels/janiyomibridge.dart';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: k3vinb5_aniyomi_bridge
|
||||
description: "A new Flutter package project."
|
||||
name: unyo_lib
|
||||
description: "Flutter bridge for Unyo Core JVM runtime"
|
||||
version: 0.0.1
|
||||
|
||||
environment:
|
||||
@@ -32,7 +32,7 @@ flutter:
|
||||
|
||||
# To add assets to your package, add an assets section, like this:
|
||||
assets:
|
||||
- assets/aniyomibridge-core.jar
|
||||
- assets/unyo-core.jar
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user