Aller au contenu principal

Gestion des environnements et conditions physiques (OtaEnvironment)

Dans tk_ota_push, la notion d'environnement recouvre deux dimensions complémentaires :

  1. 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).
  2. La résolution d'environnement applicatif (dev, staging, prod, uat) et la bascule de canal au runtime (enableQaMode() / disableQaMode() et cascade FlutterProject.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éfaut 100) : pourcentage de batterie restant.
  • isCharging (bool, défaut false) : indique si le téléphone est branché sur secteur/USB.
  • isUnmeteredWifi (bool) : getter calculé retournant true si connectivity == OtaConnectivityType.wifi || connectivity == OtaConnectivityType.ethernet.
  • isOnline (bool) : getter calculé retournant true si connectivity != 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 :

  1. conditions.isOnline == true
  2. wifiOk : !requireWifiForSilentUpdate || conditions.isUnmeteredWifi
  3. batteryOk : 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 unique tk_ota_silent_patch_${remoteConfig.targetReleaseVersion}_${remoteConfig.latestPatchNumber}.
  • syncWithRemoteConfig retourne OtaUpdateExecutionMode.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 :

  1. Au moment du build / publication CLI :
    • Flag --server <url>
    • Clé base_url dans shorebird.yaml
    • Variable d'environnement OTA_SERVER_URL
    • Valeur par défaut : http://localhost:8080
  2. Au runtime mobile dans le moteur Rust :
    • Lit la clé base_url embarquée dans flutter_assets/shorebird.yaml.
    • Lorsqu'un téléphone interroge POST {base_url}/api/v1/patches/check, le contrôleur serveur ShorebirdUpdaterController.resolveClientReachableUrl inspecte les en-têtes X-Forwarded-Host, Host et X-Forwarded-Proto pour réécrire dynamiquement toute URL de téléchargement pointant vers localhost ou 127.0.0.1 en une URL directement joignable par le téléphone.

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 :

  1. Le paramètre explicite --env <nom> (ex: --env staging).
  2. Le paramètre --flavor <nom> (ex: --flavor dev).
  3. Les variables --dart-define contenant ENV=..., ENVIRONMENT=... ou FLAVOR=....
  4. Le fichier d'entrée --target correspondant au motif main_<env>.dart ou main-<env>.dart (ex: -t lib/main_dev.dart déduit dev).
  5. Le nom du fichier --dart-define-from-file (ex: env/dev.json ou .env.staging déduit dev ou staging).

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"