Gestion des environnements et conditions physiques (OtaEnvironment)
Dans tk_ota_push, la notion d'environnement recouvre deux dimensions complémentaires :
- L'inspection des conditions physiques de l'appareil au runtime (
lib/src/environment/ota_environment.dart) : type de connectivité réseau (OtaConnectivityType), niveau de batterie (OtaDeviceConditions) et planification différée en tâche de fond (OtaBackgroundScheduler). - La résolution d'environnement applicatif (
dev,staging,prod,uat) et la bascule de canal au runtime (enableQaMode()/disableQaMode()et cascadeFlutterProject.deduceEnvironmentName).
1. Conditions physiques : Réseau & Batterie (ota_environment.dart)
Lorsqu'un patch est publié en mode silencieux (forceUpdate: false), le SDK vérifie l'état physique du téléphone via OtaEnvironmentMonitor.checkConditions() avant de déclencher le téléchargement.
Types de connectivité (OtaConnectivityType)
enum OtaConnectivityType {
wifi,
ethernet,
mobile,
none,
}
État courant de l'appareil (OtaDeviceConditions)
La classe OtaDeviceConditions expose :
connectivity(OtaConnectivityType) : type de connexion active.batteryPercentage(int, défaut100) : pourcentage de batterie restant.isCharging(bool, défautfalse) : indique si le téléphone est branché sur secteur/USB.isUnmeteredWifi(bool) : getter calculé retournanttruesiconnectivity == OtaConnectivityType.wifi || connectivity == OtaConnectivityType.ethernet.isOnline(bool) : getter calculé retournanttruesiconnectivity != OtaConnectivityType.none.
Règle de décision en mode silencieux (TkOtaPush.syncWithRemoteConfig)
Dans lib/src/tk_ota_push_sdk.dart, une mise à jour silencieuse (forceUpdate: false) est autorisée immédiatement si et seulement si les trois critères suivants sont vrais :
conditions.isOnline == truewifiOk:!requireWifiForSilentUpdate || conditions.isUnmeteredWifibatteryOk:conditions.isCharging || conditions.batteryPercentage >= minBatteryPercentageForSilentUpdate
Si l'une de ces conditions n'est pas remplie (par exemple l'utilisateur est sur réseau mobile 3G/4G alors que requireWifiForSilentUpdate: true, ou sa batterie est à 15 % sans chargeur alors que minBatteryPercentageForSilentUpdate: 20) :
- Aucun appel réseau OTA n'est effectué dans l'immédiat (
networkCallPerformed: false). - Le SDK appelle
_backgroundScheduler.scheduleSilentUpdateTask(...)avec l'identifiant uniquetk_ota_silent_patch_${remoteConfig.targetReleaseVersion}_${remoteConfig.latestPatchNumber}. syncWithRemoteConfigretourneOtaUpdateExecutionMode.deferredToBackgroundTask.
Brancher connectivity_plus et battery_plus sur OtaEnvironmentMonitor
Le SDK fournit DefaultOtaEnvironmentMonitor (qui retourne par défaut wifi et 100 % de batterie pour ne nécessiter aucune dépendance native supplémentaire). Pour brancher vos plugins natifs en production, implémentez OtaEnvironmentMonitor :
import 'package:tk_ota_push/tk_ota_push.dart';
class ProductionEnvironmentMonitor implements OtaEnvironmentMonitor {
Future<OtaDeviceConditions> checkConditions() async {
// Exemple d'intégration avec vos plugins de connectivité et batterie
return const OtaDeviceConditions(
connectivity: OtaConnectivityType.wifi,
batteryPercentage: 75,
isCharging: false,
);
}
}
Brancher workmanager sur OtaBackgroundScheduler
De même, vous pouvez remplacer InMemoryOtaBackgroundScheduler par une implémentation déléguant à workmanager :
import 'package:tk_ota_push/tk_ota_push.dart';
class WorkmanagerBackgroundScheduler implements OtaBackgroundScheduler {
Future<void> scheduleSilentUpdateTask({
required String taskUniqueName,
required bool requireWifi,
required bool requireBatteryNotLow,
}) async {
// Enregistrement de la tâche différée auprès d'Android WorkManager / iOS BGTaskScheduler
}
}
2. Environnements applicatifs (dev, staging, prod) et résolution d'URL
Résolution de base_url par environnement
L'URL du serveur OTA (base_url) est résolue selon l'ordre de priorité suivant :
- Au moment du build / publication CLI :
- Flag
--server <url> - Clé
base_urldansshorebird.yaml - Variable d'environnement
OTA_SERVER_URL - Valeur par défaut :
http://localhost:8080
- Flag
- Au runtime mobile dans le moteur Rust :
- Lit la clé
base_urlembarquée dansflutter_assets/shorebird.yaml. - Lorsqu'un téléphone interroge
POST {base_url}/api/v1/patches/check, le contrôleur serveurShorebirdUpdaterController.resolveClientReachableUrlinspecte les en-têtesX-Forwarded-Host,HostetX-Forwarded-Protopour réécrire dynamiquement toute URL de téléchargement pointant verslocalhostou127.0.0.1en une URL directement joignable par le téléphone.
- Lit la clé
Déduction automatique du nom d'environnement (deduceEnvironmentName)
Lors des builds multi-environnements (dev, staging, prod, uat), FlutterProject.deduceEnvironmentName (lib/src/cli/project.dart) déduit automatiquement l'environnement actif en inspectant dans l'ordre :
- Le paramètre explicite
--env <nom>(ex:--env staging). - Le paramètre
--flavor <nom>(ex:--flavor dev). - Les variables
--dart-definecontenantENV=...,ENVIRONMENT=...ouFLAVOR=.... - Le fichier d'entrée
--targetcorrespondant au motifmain_<env>.dartoumain-<env>.dart(ex:-t lib/main_dev.dartdéduitdev). - Le nom du fichier
--dart-define-from-file(ex:env/dev.jsonou.env.stagingdéduitdevoustaging).
3. Bascule dynamique de canal au runtime (stable / staging)
Au sein d'une même version compilée, l'instance TkOtaPush écoute par défaut le canal UpdateTrack.stable. Vous pouvez basculer dynamiquement un appareil vers le canal UpdateTrack.staging (par exemple depuis un menu caché réservé aux équipes QA) sans recompiler l'application :
final ota = TkOtaPush.instance;
// Bascule sur UpdateTrack.staging
ota.enableQaMode();
print(ota.track.name); // "staging"
// Vérifie et télécharge le dernier patch publié sur le canal staging
final updated = await ota.checkAndUpdate();
// Retour sur le canal public UpdateTrack.stable
ota.disableQaMode();
print(ota.track.name); // "stable"