Android applications avec seed

Ce guide décrit comment utiliser le courant Android seed plateforme et framework. Le support mis en œuvre combine un seed bibliothèque (mobile), un Android hôte basé sur Gradle/Kotlin/CMake, et un pont JNI qui charge le natif seed bibliothèque.

État actuel : Android est la plateforme mobile active. Le cadre fournit un Surface du canevas conservée pilotée par les commandes de frame, la saisie de base, le cycle de vie, encarts, métriques d'écran et multi-ABI emballage. Ce n'est pas encore terminé boîte à outils de widgets.

Ce qui est pris en charge

Les éléments suivants ne constituent pas des revendications de support actuel : un catalogue complet de widgets, TalkBack sur appareil physique, un IME selection/composition, la mise en forme du texte, le rechargement à chaud, une large matrice de périphériques, la publication en magasin ou la préparation à la production.

Architecture

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

Le seed l'application ne remplace pas encore Activity. Le Android L'hôte reste responsable du processus, de la fenêtre, du Canvas, de JNI et de l'intégration avec le SDK. Le mobile La bibliothèque fournit les importations portables de la tranche implémentée et ne doit être utilisée qu'avec un Android cible.

Exigences

Vous devez avoir :

L'installateur officiel du projet utilise $HOME/Android/Sdk, ne nécessite pas sudo, et installe la ligne de base complète :

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

Options utiles :

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

Utiliser --api, --abi, --image-flavor, --ndk, --avd, et --device pour personnaliser l'installation. --skip-gradle laisse l'installation de Gradle à l'utilisateur. Pour utiliser un NDK autre que la ligne de base, déclarez explicitement SEED_ANDROID_NDK_REVISION et confirmer la compatibilité avec le projet.

Les diagnostics doivent montrer Android 37.0, build-tools 37.0.0, Gradle 9.5.0, platform-tools, NDK et le API 21 racines système de aarch64-linux-android et x86_64-linux-android:

./seed mobile android doctor

Tutoriel 1 : première application

Créer app.sd:

fn main() -> i64 {
    0
}

pub fn seed_mobile_entry() -> i64 {
    0
}

Créez un hôte en copiant le modèle versionné :

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

Compilez les deux ABI, préparez et générez l'APK :

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

La commande produit libseed_app.so et libseed_app.a pour arm64-v8a et x86_64, copie les artefacts dans my-android/app/src/main/jniLibs/, lie le seed objet partagé en tant que dépendance de pont JNI packagée et exécute assembleDebug; l'archive reste disponible séparément pour les consommateurs natifs. Le my-android/seed-android.properties Le fichier enregistre le nom natif et l'ID d'application utilisés par les commandes suivantes.

Tutoriel 2 : dessiner un écran

Importez la bibliothèque mobile Android dans votre code d'application. Un exemple complet se trouve dans compiler/llvm/tests/mobile/android_framework.sd. Le rappel de trame reçoit la largeur, la hauteur et la durée en nanosecondes :

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)
}

Les coordonnées et la taille de la police sont exprimées en millipixels. Les couleurs sont des entiers ARVB. L'hôte limite chaque image à 256 rectangles, 32 éléments de texte, 128 nœuds sémantiques et 256 octets UTF-8 par étiquette ou élément. Le texte est dessiné par le canevas Android ; la sélection des polices et la mise en forme avancée ne font pas encore partie du contrat.

Tutoriel 3 : Consommer le toucher, le clavier et IME

La bibliothèque gère une file d'attente limitée de 128 événements. Lisez les champs avant de supprimer un événement :

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 doit être appelé une fois par événement. Si les producteurs dépassent leur capacité, la file d'attente conserve les événements les plus récents. Les régions de sélection et de composition ne sont pas encore exposées.

Tutoriel 4 : Cycle de vie et ressources

Définissez uniquement les hooks nécessaires. Ils s'exécutent sur le thread Activity et ne doivent pas bloquer, conserver les objets JNI ou créer des tâches sans groupe structuré :

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 est protégé contre les exécutions répétées dans le même processus ; la recréation de Activity ne redémarre pas l'application. La destruction est annulée en attendant les travaux sur le pont ; la mort du processus est la limite finale du nettoyage.

Les applications dotées de capacités persistantes multi-images peuvent exporter seed_mobile_context_create, seed_mobile_context_on_event, seed_mobile_context_on_frame, et seed_mobile_context_destroy. L'hôte conserve au plus un contexte par génération de Activity, arrête de transférer les rappels lorsque cette génération est invalidée et détruit le contexte exactement une fois. Les hooks hérités restent la solution de repli.

Utilisez mobile.window_focused() pour suspendre le travail visuel en cas de perte de concentration et mobile.memory_pressure() pour vider les caches après onTrimMemory. Ne considérez pas ces signaux comme une garantie que le processus restera vivant.

Tutoriel 5 : aménagement, zone sécurisée et rangement

Les encarts sont des pixels physiques : 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() et mobile.scaled_density_milli() vous permettent d'adapter la mise en page et la typographie. mobile.app_files_* et mobile.app_cache_* renvoyer des vues délimitées des chemins privés fournis par Activity; utilisez-les pour le stockage interne et la mise en cache. Il n’y a pas d’accès automatique au stockage externe. L'autorisation réseau déclarée par le modèle couvre l'actuel net slice, mais les autorisations supplémentaires restent sous la responsabilité de l'hôte.

Créer des flux

Construction manuelle

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

Construction intégrée

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

build recherche le NDK dans ANDROID_NDK_HOME lorsque --ndk n'est pas fourni et génère des paires shared/static pour les deux ABI ; l'hôte préfère l'objet partagé packagé et conserve l'archive en tant qu'artefact distinct. stage continue d'accepter les bibliothèques partagées ELF, valide les artefacts et rejette les ID d'application non valides. Le nom du package natif ne peut pas contenir / ou ...

Si le package Seed qui contient app.sd a un assets/ dossier, la version intégrée copie également ses fichiers plats réguliers dans le dossier Android hôte. Les noms sont limités aux lettres et chiffres ASCII, ., _, et -; les sous-dossiers, les fichiers cachés et les collisions avec la sonde hôte sont rejetés. Au démarrage, l'hôte lit le généré seed-mobile-assets.list indexe et extrait exactement ces fichiers (au maximum 256 fichiers et 64 Mo) vers la racine privée en lecture seule déjà exposée à Seed. Actifs de framework ou de superposition également répertoriés par AssetManager n’entrez pas dans le package Seed. Les mêmes ressources manifeste et image, police, WAV et Ogg peuvent donc suivre le bureau et Android sans logique de copie spécifique à l'application.

Les dépendances directes sur audio-vorbis et grove-game-assets font que la version intégrée inclut les backends stb correspondants dans les deux ABI. Le pont JNI fournit le contrat audio partagé sur OpenSL ES, avec des flux limités, des poignées étiquetées par génération, une file d'attente PCM stéréo de 48 kHz, des requêtes d'octets en attente, pause/resume, un nettoyage et une fermeture exacte une fois.

Débogage, publication et exécution

./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 emballe, installe, force l'arrêt de l'instance précédente et exécute .MainActivity via adb, nécessitant Status: ok. ANDROID_SERIAL peut également sélectionner l'appareil.

Pour démarrer l'AVD installé par le programme d'installation :

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

Le nom AVD réel peut être interrogé avec avdmanager list avd.

Matrice AVD

La matrice implémentée conserve le system-images installé et crée un état AVD éphémère par exécution. Chaque ligne utilise du temporaire ANDROID_AVD_HOME, initialisation sans instantané et données propres ; Après le test, fermez et supprimez uniquement l'AVD. Les images SDK, NDK, Gradle et les caches de build restent installés. La mise en scène native et Gradle s'exécutent sur une copie temporaire de l'hôte ; la matrice ne se réécrit pas seed-android.properties, jniLibs ou les sorties dans le projet original.

Fast Smoke déclare les AVD des téléphones ARM64 dans les API 21, 29 et 37. La suite de versions utilise des versions stables. API 37 avec 16 Ko de pages pour tablette, profil pliable, mémoire limitée et huit cycles de vie. Il n'y a pas de niveau nocturne et aucune obligation d'exécuter x86_64; android-x86_64 reste couvert par compile/link contrats uniquement.

Le coureur crée l’APK une fois et le réutilise. Chaque ligne valide le démarrage, doctor --serial, install/cold lancement, accessibilité, basique touch/key/IME, insets/density/focus, lifecycle/rotation, Logcat et arrêt. La suite de versions répète le cycle de vie selon la ligne et injecte RUNNING_CRITICAL dans le scénario de mémoire limitée. Les échecs préservent la configuration, Logcat, dumpsys, gfxinfo, meminfo, arborescence d'accessibilité et capture d'écran dans 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 stratégie auto (par défaut) enregistre SKIP pour les outils ou images manquants ; required échoue ; off désactive l'exécution. --install-images, en appel direct à scripts/android_avd_matrix.sh, installe les images sélectionnées. SEED_ANDROID_ADB_TIMEOUT et SEED_ANDROID_AVD_BOOT_TIMEOUT limitent les appels adb et boot ; SEED_ANDROID_AVD_VERBOSE=true préserve la sortie détaillée de l’émulateur. Les trois scénarios de sortie et les quatre scénarios de version ARM64 sont transmis à l'Apple M4.

Le contrat Garden utilise la même infrastructure éphémère. Il valide les 64 cellules sémantiques en portrait et paysage lors de huit rotations, mouvement avec animation réduite, pause/resume, suppression de la session audio lors du démontage, du démarrage, frames/jank et la rétention du PSS. Ces mesures constituent la référence AVD ; ils ne remplacent pas Android LeakSanitizer ou mesures de performances, thermiques et de latence sur un appareil physique.

Cette matrice élargit uniquement les preuves dans l'émulateur. Motorola enregistré sous ANDROID_TARGET_BASELINE.md reste toute réclamation physique. La politique complète et l’ordre de mise en œuvre se trouvent dans roadmap-mobile.md.

Tests et validation

Validez les contrats sans SDK complet avec :

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

Pour une validation réelle, exécutez doctor, effectuez build, installez sur AVD ou un périphérique, puis exécutez run. La base de données probantes se trouve dans ANDROID_TARGET_BASELINE.md. doctor --serial <adb-serial> valide également le modèle, API, ABI, le correctif de sécurité et l'état d'autorisation du périphérique sélectionné.

Diagnostic du problème

Limites et prochaines étapes

Le pont actuel est une base opérationnelle et non une promesse de compatibilité avec l'ensemble Android SDK. Un catalogue de widgets, une mise en page conservée, une navigation, un éditeur de texte complet, TalkBack sur appareil physique, des plugins stables, un inspecteur, un profileur, un rechargement à chaud, une large matrice d'appareils, la publication en magasin et la signature de production restent sur la feuille de route. iOS est actif dans le simulateur via le compilateur, le runtime, l'hôte Swift et XCFramework ; L'exécution, le provisionnement, la signature et la publication des périphériques physiques restent ouverts.

Références