Android applicazioni con seed

Questa guida descrive come utilizzare la corrente Android seed piattaforma e quadro. Il supporto implementato combina a seed biblioteca (mobile), un Android ospite basato su Gradle/Kotlin/CMake e un bridge JNI che carica il file nativo seed biblioteca.

Stato attuale: Android è la piattaforma mobile attiva. Il quadro prevede a superficie Canvas mantenuta guidata da comandi frame, input di base, ciclo di vita, inserti, metriche dello schermo e multi-ABI imballaggio. Non è ancora completo kit di strumenti widget.

Cosa è supportato

Quanto segue non è una dichiarazione di supporto attuale: un catalogo completo di widget, TalkBack per il dispositivo fisico, completo IME selection/composition, modellazione del testo, ricarica a caldo, un'ampia matrice di dispositivi, pubblicazione in negozio o preparazione alla produzione.

Architettura

seed app (.sd)
    │  integrated build: .so + .a per ABI
    ▼
libseed_app.so ─► JNI bridge (preferred packaged dependency)
libseed_app.a  ─► separate static artifact
    │  C ABI
    ▼
JNI bridge + SeedSurfaceView
    │
    ▼
Activity Android / Canvas / adb / Gradle

Il seed l'applicazione non sostituisce ancora Activity. Il Android l'host rimane responsabile di processo, finestra, Canvas, JNI e integrazione con l'SDK. Il mobile fornisce le importazioni portatili della sezione implementata e deve essere utilizzata solo con un file Android bersaglio.

Requisiti

Devi avere:

Il programma di installazione ufficiale del progetto utilizza $HOME/Android/Sdk, non richiede sudoe installa la baseline completa:

./seed mobile android setup
./seed mobile android doctor

Opzioni utili:

./seed mobile android setup --sdk "$HOME/Android/Sdk" --start
./seed mobile android setup --skip-avd
./seed mobile android setup --dry-run

Utilizzare --api, --abi, --image-flavor, --ndk, --avd, e --device per personalizzare l'installazione. --skip-gradle lascia l'installazione di Gradle all'utente. Per utilizzare un NDK diverso dalla linea di base, dichiarare esplicitamente SEED_ANDROID_NDK_REVISION e confermare la compatibilità con il progetto.

La diagnostica dovrebbe mostrare Android 37.0, build-tools 37.0.0, Gradle 9.5.0, platform-tools, NDK e API 21 sysroot di aarch64-linux-android e x86_64-linux-android:

./seed mobile android doctor

Esercitazione 1: prima applicazione

Crea app.sd:

fn main() -> i64 {
    0
}

pub fn seed_mobile_entry() -> i64 {
    0
}

Crea un host copiando il modello con versione:

cp -R seed/compiler/llvm/mobile/android my-android

Compila entrambe le ABI, esegui lo stage e genera l'APK:

./seed mobile android build app.sd my-android \
  --package-name seed_app \
  --application-id com.example.seedapp \
  --package

Il comando produce libseed_app.so e libseed_app.a per arm64-v8a e x86_64, copia gli artefatti in my-android/app/src/main/jniLibs/, associa l'oggetto condiviso seed come dipendenza bridge JNI in pacchetto ed esegue assembleDebug; l'archivio rimane disponibile separatamente per i consumatori nativi. Il file my-android/seed-android.properties registra il nome nativo e l'ID dell'applicazione utilizzati dai comandi successivi.

Tutorial 2: disegnare uno schermo

Importa la libreria mobile Android nel codice dell'applicazione. Un esempio completo è in compiler/llvm/tests/mobile/android_framework.sd. Il callback del frame riceve larghezza, altezza e tempo in nanosecondi:

use "mobile"

pub fn seed_mobile_entry() -> i64 { 0 }

pub fn seed_mobile_on_frame(width: i32, height: i32, time_nanos: i64) {
    mobile.frame_clear()
    mobile.frame_color(4278190335 as i64) // ARGB: opaque blue
    mobile.frame_rect(1000, 1000, 2000, 2000, 4294902015 as i64)
    mobile.frame_text("Hello, Android", 1500, 4500, 2400, 4294967295 as i64)
}

Le coordinate e la dimensione del carattere sono espresse in millipixel. I colori sono numeri interi ARGB. L'host limita ciascun frame a 256 rettangoli, 32 elementi di testo, 128 nodi semantici e 256 UTF-8 byte per etichetta o elemento. Il testo è disegnato da Android tela; la selezione dei caratteri e la modellazione avanzata non fanno ancora parte del contratto.

Tutorial 3: Consumo di tocco, tastiera e IME

La libreria mantiene una coda delimitata di 128 eventi. Leggere i campi prima di rimuovere un evento:

use "mobile"

fn read_input() {
    while mobile.input_available() {
        let kind = mobile.input_kind()
        let a = mobile.input_a()
        let b = mobile.input_b()
        let c = mobile.input_c()

        // kind 1: touch; a=action, b=x in millipixels, c=y in millipixels.
        // kind 2: key; a=action, b=Android key code, c=Unicode code point.
        // kind 3: text committed by the IME.
        if kind == 3 {
            let length = mobile.input_text_length()
            // input_text_byte(index) exposes the committed text's UTF-8 bytes.
            let _ = length
        }
        mobile.input_pop()
    }
}

input_pop deve essere chiamato una volta per evento. Se i produttori superano la capacità, la coda conserva gli eventi più recenti. La regione di selezione e composizione non è ancora esposta.

Esercitazione 4: Ciclo di vita e risorse

Definire solo gli hook necessari. Vengono eseguiti sul thread Activity e non devono bloccare, conservare oggetti JNI o creare attività senza un gruppo strutturato:

pub fn seed_mobile_on_create() {}
pub fn seed_mobile_on_start() {}
pub fn seed_mobile_on_resume() {}
pub fn seed_mobile_on_pause() {}
pub fn seed_mobile_on_stop() {}
pub fn seed_mobile_on_destroy() {}

seed_mobile_entry è protetto contro l'esecuzione ripetuta nello stesso processo; la ricreazione di Activity non riavvia l'applicazione. La distruzione annulla i lavori in sospeso sul ponte; la morte del processo è il confine finale della pulizia.

Le applicazioni con funzionalità persistenti tra frame possono essere esportate seed_mobile_context_create, seed_mobile_context_on_event, seed_mobile_context_on_frame, e seed_mobile_context_destroy. L'host mantiene al massimo un contesto per generazione di Activity, interrompe l'inoltro dei callback quando questa generazione viene invalidata e distrugge il contesto esattamente una volta. Gli hook legacy rimangono il fallback.

Utilizza mobile.window_focused() per mettere in pausa il lavoro visivo durante la perdita di concentrazione e mobile.memory_pressure() per svuotare le cache dopo onTrimMemory. Non considerate questi segnali come una garanzia che il processo rimarrà vivo.

Esercitazione 5: disposizione, area sicura e stoccaggio

Gli inserti sono pixel fisici: 0=left, 1=top, 2=right, 3=bottom.

use "mobile"

fn content_top() -> i64 {
    mobile.window_inset(1)
}

fn text_size() -> i64 {
    // scaled_density_milli is the font density multiplied by 1000.
    16000 * mobile.scaled_density_milli() / 1000
}

mobile.density_dpi() e mobile.scaled_density_milli() ti consentono di adattare layout e tipografia. mobile.app_files_* e mobile.app_cache_* restituiscono viste limitate dei percorsi privati ​​forniti da Activity; usali per l'archiviazione interna e la memorizzazione nella cache. Non è previsto l'accesso automatico alla memoria esterna. L'autorizzazione di rete dichiarata dal modello copre la sezione net corrente, ma le autorizzazioni aggiuntive rimangono di responsabilità dell'host.

Costruisci flussi

Costruzione manuale

seed --emit-shared libseed_app.so \
  --target android-arm64 --runtime-profile android \
  --sysroot "$ANDROID_NDK_SYSROOT" --soname libseed_app.so app.sd

seed --emit-shared libseed_app.so \
  --target android-x86_64 --runtime-profile android \
  --sysroot "$ANDROID_NDK_SYSROOT" --soname libseed_app.so app.sd

./seed mobile android stage my-android arm64.so x86_64.so \
  seed_app com.example.seedapp
./seed mobile android package my-android

Costruzione integrata

./seed mobile android build app.sd my-android \
  --ndk "$ANDROID_NDK_HOME" \
  --package-name seed_app \
  --application-id com.example.seedapp

build cerca l'NDK in ANDROID_NDK_HOME quando --ndk non è fornito e genera coppie shared/static per i due ABI; l'host preferisce l'oggetto condiviso confezionato e mantiene l'archivio come artefatto separato. stage continua ad accettare le librerie condivise ELF, convalida gli artefatti e rifiuta gli ID applicazione non validi. Il nome del pacchetto nativo non può contenere / o ...

Se il pacchetto Seed che contiene app.sd ha un assets/ cartella, la build integrata copia anche i suoi normali file flat nella cartella Android ospite. I nomi sono limitati a lettere e cifre ASCII, ., _, e -; le sottocartelle, i file nascosti e le collisioni con la sonda host vengono rifiutati. All'avvio, l'host legge il file generato seed-mobile-assets.list indicizza ed estrae esattamente quei file - al massimo 256 file e 64 MiB - nella root privata di sola lettura già esposta a Seed. Risorse framework o overlay elencate anche per AssetManager non inserire il pacchetto Seed. Gli stessi file manifest e immagini, font, WAV e Ogg possono quindi seguire desktop e Android senza logica di copia specifica dell'applicazione.

Le dipendenze dirette su audio-vorbis e grove-game-assets fanno sì che la build integrata includa i backend stb corrispondenti in entrambi gli ABI. Il bridge JNI fornisce il contratto audio condiviso su OpenSL ES, con flussi limitati, handle con tag di generazione, una coda PCM stereo a 48 kHz, query sui byte in sospeso, pause/resume, pulizia e chiusura esattamente una volta.

Debug, rilascio ed esecuzione

./seed mobile android package my-android
./seed mobile android package my-android --release
./seed mobile android run my-android
./seed mobile android run my-android --release
./seed mobile android run my-android --serial emulator-5554
./seed mobile android doctor --serial ZF524P7D2T

run crea pacchetti, installa, forza l'arresto dell'istanza precedente ed esegue .MainActivity tramite adb, richiedendo Status: ok. ANDROID_SERIAL può anche selezionare il dispositivo.

Per avviare l'AVD installato dal setup:

emulator -avd seed-api37 -no-snapshot
adb wait-for-device
./seed mobile android run my-android

Il nome AVD effettivo può essere richiesto con avdmanager list avd.

Matrice AVD

La matrice implementata mantiene il file system-images installato e crea uno stato AVD effimero per esecuzione. Ogni riga utilizza temporaneo ANDROID_AVD_HOME, inizializzazione senza snapshot e dati puliti; Dopo il test, chiudi ed elimina solo AVD. Le immagini SDK, NDK, Gradle e le cache di build rimangono installate. La gestione temporanea nativa e Gradle vengono eseguiti su una copia temporanea dell'host; la matrice non si riscrive seed-android.properties, jniLibs o output nel progetto originale.

Fast smoke dichiara gli AVD del telefono ARM64 nelle API 21, 29 e 37. La suite di rilascio utilizza stable API 37 con pagine tablet da 16 KB, profilo pieghevole, memoria limitata e otto cicli di vita. Non esiste un livello notturno né alcun obbligo di esecuzione x86_64; android-x86_64 rimane coperto da compile/link solo contratti.

Il runner crea l'APK una volta e lo riutilizza. Ogni riga convalida l'avvio, doctor --serial, install/cold lancio, accessibilità, base touch/key/IME, insets/density/focus, lifecycle/rotation, Logcat e arresto. La suite di rilascio ripete il ciclo di vita secondo la riga e si inserisce RUNNING_CRITICAL nello scenario con memoria limitata. Gli errori preservano la configurazione, Logcat, dumpsys, gfxinfo, meminfo, albero di accessibilità e screenshot in compiler/llvm/build/android-avd-matrix/.

make -C seed/compiler/llvm android-avd-matrix-check
make -C seed/compiler/llvm android-avd-smoke
make -C seed/compiler/llvm android-avd-release
make -C seed/compiler/llvm game-seed-garden-android-avd-check
SEED_ANDROID_AVD_API=37.0 \
  SEED_ANDROID_AVD_RUNNER_POLICY=required \
  make -C seed/compiler/llvm android-avd-smoke

La policy auto (impostazione predefinita) registra SKIP per strumenti o immagini mancanti; required fallisce; off disabilita l'esecuzione. --install-images, in chiamata diretta a scripts/android_avd_matrix.sh, installa le immagini selezionate. SEED_ANDROID_ADB_TIMEOUT e SEED_ANDROID_AVD_BOOT_TIMEOUT limitano le chiamate adb e boot; SEED_ANDROID_AVD_VERBOSE=true preserva l'output dettagliato dell'emulatore. I tre fumi e i quattro scenari di rilascio ARM64 passano sull'Apple M4.

Il contratto Garden utilizza la stessa infrastruttura effimera. Convalida le 64 celle semantiche in verticale e orizzontale durante otto rotazioni, movimento con animazione ridotta, pause/resume, rimozione della sessione audio durante lo smontaggio, l'avvio, frames/jank e conservazione PSS. Queste misurazioni costituiscono la linea di base dell'AVD; non sostituiscono Android LeakSanitizer o misurazioni di prestazioni, temperatura e latenza su un dispositivo fisico.

Questa matrice espande solo le prove nell'emulatore. Motorola registrata in ANDROID_TARGET_BASELINE.md rimane tutta la pretesa fisica. La politica completa e l'ordine di implementazione si trovano in roadmap-mobile.md.

Test e validazione

Convalida i contratti senza SDK completo con:

make -C seed/compiler/llvm android-target-test
make -C seed/compiler/llvm android-host-check
make -C seed/compiler/llvm android-package-check
make -C seed/compiler/llvm android-build-check
make -C seed/compiler/llvm android-run-check
make -C seed/compiler/llvm android-doctor-check

Per una convalida reale, esegui doctor, esegui build, installa su AVD o dispositivo ed esegui run. La base delle prove è in ANDROID_TARGET_BASELINE.md. doctor --serial <adb-serial> convalida anche il modello, API, ABI, patch di sicurezza e stato di autorizzazione del dispositivo selezionato.

Diagnosi del problema

Limiti e prossimi passi

L'attuale ponte è una base operativa, non una promessa di compatibilità con l'insieme Android SDK. Un catalogo di widget, layout mantenuto, navigazione, un editor di testo completo, TalkBack per dispositivi fisici, plug-in stabili, un ispettore, un profiler, ricarica a caldo, un'ampia matrice di dispositivi, pubblicazione di negozi e firma di produzione rimangono sulla tabella di marcia. iOS è attivo nel simulatore tramite il compilatore, il runtime, l'host Swift e XCFramework; l'esecuzione, il provisioning, la firma e la pubblicazione dello store del dispositivo fisico rimangono aperti.

Riferimenti