Skip to content

AjuntamentdeBarcelona/modul_comu_osam_flutter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

90 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Modul comú OSAM Flutter

License: GPL v3 License


Migrate from 6.0.0 to 8.1.0

  • Need to use minimal Dart SDK version ^3.5.0
  • Need to use minimal Flutter version 3.24.3

Migrate from 5.0.x to 6.0.0

  • Rename package from common_module_flutter to osam_common_module_flutter
    • On pubspec.yaml, change common_module_flutter to osam_common_module_flutter
    • On imports, change import 'package:common_module_flutter/common_module_flutter.dart'; to import 'package:osam_common_module_flutter/osam_common_module_flutter.dart';
  • To import, use only import 'package:osam_common_module_flutter/osam_common_module_flutter.dart'; and not src/ or other subdirectories.
  • Need to use minimal Dart SDK version 3.0.0
  • Need to use minimal Flutter version 3.10.0

Introdució

Des de la OSAM es proporcionen mòduls per realitzar un conjunt de tasques comunes a totes les apps publicades per l'Ajuntament de Barcelona. El mòdul comú (Flutter) està disponible com a repositori a Github

Useful links:

A partir de la versió 3.0.0 la llibreria es un wrapper de la desenvolupada en Kotlin Multiplatform

Com es fa servir?

  1. Afegeix aquesta dependència al pubspec:

    osam_common_module_flutter:
      git:
        url: https://github.com/AjuntamentdeBarcelona/modul_comu_osam_flutter.git
        ref: '8.1.0'

    En cas que les dependències de Firebase Analytics, Firebase Performance, Firebase Messaging i Firebase Crashlytics fallin, cal afegir aquestes aquesta configuració al pubspec:

    dependency_overrides:
    firebase_crashlytics_platform_interface: 3.1.13
    firebase_analytics_platform_interface: 3.0.5
    firebase_performance_platform_interface: ^0.1.1+18
    firebase_messaging_platform_interface: ^5.0.0
  2. Actualitzar mitjançant el comandament 'flutter packages get' les dependències.

  3. Afegir el import on sigui necessari:

    import 'package:osam_common_module_flutter/osam_common_module_flutter.dart';
  4. Per utilitzar la llibreria necessitem crear una instància de la clase OSAM, la qual es fa a través del mètode estàtic (i asíncron) init().

    Tenim un example de inicialització on example/lib/di/di.dart

    En el cas de l'app d'exemple, accedim a la instància creada a través de OsamRepository

Configuració de l'entorn

En l'exemple anterior tenim la URL del mòdul comú hardcoded a la pròpia lògica. Però aquesta URL s'ha d'externalitzar com a variable de configuració, d'aquesta manera es pot generar la versió de producció només substituint el fitxer amb els valors correctes.

Per fer-ho només cal crear el fitxer ".env" a l'arrel del projecte de Flutter i carregar aquest fitxer amb el plugin flutter_dotenv. En aquesta URL hi ha la documentació de com afegir aquest fitxer i com carregar les dades al codi

El fitxer ".env" ha de contenir la URL del mòdul comú en la variable "COMMON_MODULE_URL". Quedaria de la següent manera:

COMMON_MODULE_URL=https://dev-osam-modul-comu.dtibcn.cat/

Configuració a la part nativa

Android

Versió de Kotlin

S'ha d'utilitzar, com a mínim, la versió 1.9.0 de Kotlin.

compileSdkVersion

L'atribut compileSdkVersion del fitxer build.gradle de l'aplicació d'Android ha de tenir el valor 31 o superior.

Multidex

Si la versió mínima de Android a la que es dona suport (minSdkVersion) a l'aplicació d'Android es inferior a 21, serà necessari habilitar multidex, ja que, si no, apareixerà un error al compilar.

Estil

Si volem que els pop-ups es vegin amb l'estil correcte, haurem d'utilitzar un estil que extengui d' AppCompat. A l'aplicació de Android que crea Flutter s'hauria de modificar els fitxers styles.xml

iOS

Podfile

En el Podfile del projecte d'iOS creat por Flutter haurem d'incloure el pod del mòdul comú de Kotlin Multiplatform Mobile. Això es fa incloent la següent linea:

pod 'OSAMCommon', :git => 'https://github.com/AjuntamentdeBarcelona/modul_comu_osam.git', :tag => '2.2.3'

El Podfile quedaria de la següent manera

Implementació control de versions

Per crear el missatge d'alerta, únicament hem de cridar a la funció que descarregarà el json amb les variables ja definides i mostrarà l'alerta segons els valors rebuts. Exemple:

void _onVersionControl() async {
  final result = await DI.osamSdk.versionControl(
    language: Language.CA,
  );

  switch (result) {
    case VersionControlResponse.ACCEPTED:
      break;
    case VersionControlResponse.DISMISSED:
      break;
    case VersionControlResponse.CANCELLED:
      break;
    case VersionControlResponse.ERROR:
      break;
  }
}

No és necessari capturar la resposta si no es necessita realitzar cap acció adicional, ja que el mòdul comú s'encarregarà de mostrar el popup si es compleixen els requeriments per a que es mostri

Mostrar el control de versions cada vegada que l'app torna a primer pla

Si és necessari executar el control de versions cada vegada que l'app torna a primer pla, a l'app demo hem implementat aquesta funcionalitat en un mixin anomenat OsamVersionChecker:

class _MyHomePageState extends State<MyHomePage> with OsamVersionChecker {

Hem utilitzat el package flutter_fgbg:

mixin OsamVersionChecker<T extends StatefulWidget> on State<T> implements RouteAware {
  StreamSubscription<FGBGType> subscription;

  @override
  void initState() {
    super.initState();
    subscription = FGBGEvents.stream.listen((event) async {
      if (event.toString() == "FGBGType.foreground") {
        await DI.osamRepository.checkForUpdates(context);
      }
    });
  }
}

Implementació control de valoració

Per crear el missatge d'alerta, únicament hem de cridar a la funció que descarregarà el json amb les variables ja definides i mostrarà l'alerta segons els valors rebuts. Exemple:

void _onRating() async {
  final result = await DI.osamSdk.rating(
    language: Language.EN,
  );

  switch (result) {
    case RatingControlResponse.ACCEPTED:
      break;
    case RatingControlResponse.DISMISSED:
      break;
    case RatingControlResponse.CANCELLED:
      break;
  }
}

No és necessari capturar la resposta si no es necessita realitzar cap acció adicional, ja que el mòdul comú s'encarregarà de mostrar el popup si es compleixen els requeriments per a que es mostri

Implementació d'obtenció de informació de dispositiu i applicació

Per obtenir la informació del dispositiu i de l'aplicació Exemple:

void _onDeviceInformation(BuildContext context) async {
  final result = await DI.osamRepository.deviceInformation();
  _showToast(context, "${result.platformName}");
  _showToast(context, "${result.platformVersion}");
  _showToast(context, "${result.platformModel}");
}

void _onAppInformation(BuildContext context) async {
  final result = await DI.osamRepository.appInformation();
  _showToast(context, "${result.appName}");
  _showToast(context, "${result.appVersionName}");
  _showToast(context, "${result.appVersionCode}");
}

Implementació per enviar l'esdeveniment de canvi d'idioma a l'aplicació

Aquesta funció orquestra tota la lògica associada al canvi d'idioma de l'aplicació. En ser invocada, actualitza les preferències locals desant tant l'idioma nou com l'anterior, registra un esdeveniment language_change a Firebase Analytics amb els detalls del canvi, i actualitza la subscripció als topics de notificacions de Firebase Cloud Messaging per garantir que l'usuari rebi les comunicacions en l'idioma seleccionat.

Exemple:

void _onChangeLanguageEvent(BuildContext context) async {
  final result = await DI.osamRepository.changeLanguageEvent();
  if (context.mounted) {
    switch (result) {
      case AppLanguageResponse.SUCCESS:
        _showToast(context, AppLanguageResponse.SENT.name);
        break;
      case LanguageInformationResponse.UNCHANGED:
        _showToast(context, AppLanguageResponse.NOT_SENT.name);
        break;
      case LanguageInformationResponse.ERROR:
        _showToast(context, AppLanguageResponse.ERROR.name);
        break;
    }
  }
}

Com funciona el event del'esdeveniment d'inici o actualització de l'app

Aquesta funció, que s'ha de cridar en iniciar l'aplicació, gestiona la subscripció inicial o l'actualització dels topics de notificacions per assegurar que el dispositiu estigui subscrit al canal correcte de Firebase Cloud Messaging. El procés recupera l'últim topic registrat, construeix el nou basant-se en la versió de l'app i l'idioma del dispositiu, actualitza la subscripció a Firebase donant de baixa l'antic i registrant el nou, i finalment desa localment la informació de la nova versió per a futures execucions.

void _onFirstTimeOrUpdateEvent(BuildContext context) async {
  final result = await DI.osamRepository.firstTimeOrUpdateEvent();
  if (context.mounted) {
    switch (result) {
      case AppLanguageResponse.SUCCESS:
        _showToast(context, AppLanguageResponse.SUCCESS.name);
        break;
      case LanguageInformationResponse.UNCHANGED:
        _showToast(context, AppLanguageResponse.UNCHANGED.name);
        break;
      case LanguageInformationResponse.ERROR:
        _showToast(context, AppLanguageResponse.ERROR.name);
        break;
    }
  }
}

Com funciona el event de la subscripció a un topic personalitzat

Aquesta funció permet subscriure l'aplicació a un topic de notificacions de Firebase amb un nom específic i personalitzat.

És útil per a campanyes de màrqueting o per segmentar usuaris en grups que no depenen de la versió de l'app o de l'idioma. La funció s'encarrega de gestionar la comunicació amb Firebase per realitzar la subscripció de manera asíncrona.

void _onSubscribeToCustomTopic(BuildContext context, String topic) async {
  final result = await DI.osamRepository.subscribeToCustomTopic(topic: topic);
  if (context.mounted) {
    switch (result) {
      case AppLanguageResponse.ACCEPTED:
        _showToast(context, AppLanguageResponse.ACCEPTED.name);
        break;
      case LanguageInformationResponse.ERROR:
        _showToast(context, AppLanguageResponse.ERROR.name);
        break;
    }
  }
}

Com funciona el event de la desubscripció a un topic personalitzat

Aquesta funció permet desubscriure l'aplicació d'un topic de notificacions de Firebase amb un nom específic i personalitzat.

És l'operació inversa a subscribeToCustomTopic i és útil per aturar la recepció de notificacions d'una campanya concreta o per netejar subscripcions quan ja no són necessàries. La funció s'encarrega de gestionar la comunicació amb Firebase per realitzar la desubscripció de manera asíncrona.

void _onUnsubscribeToCustomTopic(BuildContext context, String topic) async {
  final result = await DI.osamRepository.unsubscribeToCustomTopic(topic: topic);
  if (context.mounted) {
    switch (result) {
      case AppLanguageResponse.ACCEPTED:
        _showToast(context, AppLanguageResponse.ACCEPTED.name);
        break;
      case LanguageInformationResponse.ERROR:
        _showToast(context, AppLanguageResponse.ERROR.name);
        break;
    }
  }
}

Com funciona el event per obtenir el token de Firebase

Aquesta funció permet obtenir el token de registre de Firebase Cloud Messaging (FCM) del dispositiu. Aquest token és un identificador únic que s'utilitza per enviar notificacions push directament a un dispositiu específic. L'operació es realitza de manera asíncrona.

void _onGetFCMToken(BuildContext context) async {
  final result = await DI.osamRepository.getFCMToken();
  if (context.mounted) {
    switch (result) {
      case Success(token: final token):
        _showToast(context, 'SUCCESS: $token');
      case Error(error: final error):
        _showToast(context, 'ERROR: ${error.toString()}');
    }
  }
}

Perquè aquesta funció s’executi correctament, és necessari inicialitzar la lògica del MessagingEvent. Pots veure’n un exemple a example.lib.di.di.dart, tal com es mostra a continuació:

static _onMessagingEvent(String topic, String action) async {
    switch (action) {
      case 'subscribe':
        await FirebaseMessaging.instance.subscribeToTopic(topic);
        break;
      case 'unsubscribe':
        await FirebaseMessaging.instance.unsubscribeFromTopic(topic);
        break;
      case 'getToken':
        cacheTokenForNative();
        break;
      default:
        debugPrint("MessagingEvent error: Unknown action $action");
    }
}

static Future<void> cacheTokenForNative() async {
  String? token = await FirebaseMessaging.instance.getToken();
  if (token != null) {
 await _prefs.setString('fcm_token', token);
}

Flutter app demo

Hi ha una app demo en aquest mòdul flutter amb moltes funcionalitats disponibles que poden ajudar a entendre com funciona el mòdul comú i veure quines accions es duen a terme i com.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors