Propaga actualizaciones de Remote Config en tiempo real

Puedes propagar actualizaciones de Remote Config en tiempo real con la activación de funciones en segundo plano de Remote Config que proporciona Cloud Functions para Firebase junto con FCM. En esta situación, se crea una función que se activa cuando publicas o reviertes la versión de la plantilla de Remote Config desde el panel o la API. La actualización de la plantilla activa la función para enviar un mensaje de FCM que informa a los clientes que su configuración existente está inactiva y que la siguiente solicitud de recuperación se debe realizar desde el servidor:

Diagrama en el que se muestra una actualización de Remote Config que activa alertas de FCM mediante Cloud Functions

El resto de este documento es una explicación de los pasos necesarios para propagar las actualizaciones de Remote Config en tiempo real.

Suscribe instancias de la app cliente a un tema de FCM

A fin de especificar un mensaje de FCM para un grupo grande de instancias de la app cliente, como la base de usuarios completa, la mensajería por temas es el mecanismo más eficiente. Se debe suscribir cada instancia de app que debe recibir actualizaciones en tiempo real de Remote Config a un nombre de tema, por ejemplo, PUSH_RC:

Swift

extension AppDelegate : MessagingDelegate {
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
        messaging.subscribe(toTopic: "PUSH_RC") { error in
            print("Subscribed to PUSH_RC topic")
        }
    }
}
    

Objective‑C

- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
    [[FIRMessaging messaging] subscribeToTopic:@"PUSH_RC" completion:^(NSError * _Nullable error) {
        NSLog(@"Subscribed to PUSH_RC topic");
    }];
}
    

Android

@Override
public void onNewToken(String s) {
    FirebaseMessaging.getInstance().subscribeToTopic("PUSH_RC");
}
    

Crea una función para enviar un ping de FCM sobre las actualizaciones de plantillas

Puedes activar una función en respuesta a los eventos de Remote Config, incluida la publicación de una versión de configuración nueva o la reversión a una versión anterior. Para propagar las actualizaciones de las plantillas en tiempo real, crea una función que detecte los eventos de publicación de plantillas y luego usa el SDK de Admin de FCM desde tu función para enviar un ping silencioso a las instancias de la app cliente:

exports.pushConfig = functions.remoteConfig.onUpdate(versionMetadata => {
  // Create FCM payload to send data message to PUSH_RC topic.
  const payload = {
    topic: "PUSH_RC",
    data: {
      "CONFIG_STATE": "STALE"
    }
  };
  // Use the Admin SDK to send the ping via FCM.
  return admin.messaging().send(payload).then(resp => {
    console.log(resp);
    return null;
  });
});

Esta función configura un parámetro CONFIG_STATE y luego lo envía como la carga útil de datos de un mensaje de FCM a todos los clientes que estén suscritos al tema PUSH_RC.

Configura el estado de Remote Config en el cliente

La carga útil de datos que se presentó en el paso anterior siempre configura CONFIG_STATE en STALE en las preferencias compartidas de la app. Esto indica que la plantilla de Remote Config ya almacenada en la app ahora se encuentra inactiva debido a la creación de la plantilla actualizada nueva cuya publicación activó la función. Actualiza el controlador de notificaciones para probar esta condición, como en estos ejemplos:

Swift

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                 fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

    if (userInfo.index(forKey: "CONFIG_STATE") != nil) {
        print("Config set to stale")
        UserDefaults.standard.set(true, forKey:"CONFIG_STALE")
    }

    completionHandler(UIBackgroundFetchResult.newData)
}
    

Objective‑C

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {

    if (userInfo[@"CONFIG_STATE"]) {
        NSLog(@"Config set to stale");
        [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"CONFIG_STALE"];
    }

    completionHandler(UIBackgroundFetchResultNewData);
}
    

Android

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    if (remoteMessage.getData().containsKey("CONFIG_STATE")) {
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        sharedPreferences.edit().putBoolean("CONFIG_STALE", true).apply();
    }
}
    

Solicita las actualizaciones de Remote Config cuando se inicia la app

Swift

func fetchConfig() {
  welcomeLabel.text = remoteConfig[loadingPhraseConfigKey].stringValue

  var expirationDuration = 3600
  // If your app is using developer mode, expirationDuration is set to 0, so each fetch will
  // retrieve values from the service.
  if remoteConfig.configSettings.isDeveloperModeEnabled || UserDefaults.standard.bool(forKey: "CONFIG_STALE") {
    expirationDuration = 0
  }

  remoteConfig.fetch(withExpirationDuration: TimeInterval(expirationDuration)) { (status, error) -> Void in
    if status == .success {
      print("Config fetched!")
      self.remoteConfig.activateFetched()
    } else {
      print("Config not fetched")
      print("Error: \(error?.localizedDescription ?? "No error available.")")
    }
    self.displayWelcome()
  }
}
    

Objective‑C

- (void)fetchConfig {
    self.welcomeLabel.text = self.remoteConfig[kLoadingPhraseConfigKey].stringValue;

    long expirationDuration = 3600;
    // If your app is using developer mode, expirationDuration is set to 0, so each fetch will
    // retrieve values from the Remote Config service.
    if (self.remoteConfig.configSettings.isDeveloperModeEnabled || [[NSUserDefaults standardUserDefaults] boolForKey:@"CONFIG_STALE"]) {
        expirationDuration = 0;
    }

    [self.remoteConfig fetchWithExpirationDuration:expirationDuration completionHandler:^(FIRRemoteConfigFetchStatus status, NSError *error) {
        if (status == FIRRemoteConfigFetchStatusSuccess) {
            NSLog(@"Config fetched!");
            [self.remoteConfig activateFetched];
            [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"CONFIG_STALE"];
        } else {
            NSLog(@"Config not fetched");
            NSLog(@"Error %@", error.localizedDescription);
        }
        [self displayWelcome];
    }];
}
    

Android

private void fetchWelcomeMessage() {
    mWelcomeTextView.setText(mFirebaseRemoteConfig.getString("loading_phrase"));

    long cacheExpiration = 43200; // 12 hours in seconds.
    // If your app is using developer mode or cache is stale, cacheExpiration is set to 0,
    // so each fetch will retrieve values from the service.
    if (mFirebaseRemoteConfig.getInfo().getConfigSettings().isDeveloperModeEnabled() ||
            mSharedPreferences.getBoolean("CONFIG_STALE", false)) {
        cacheExpiration = 0;
    }

    mFirebaseRemoteConfig.fetch(cacheExpiration)
            .addOnCompleteListener(this, new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    if (task.isSuccessful()) {
                        Toast.makeText(MainActivity.this, "Fetch Succeeded",
                                Toast.LENGTH_SHORT).show();

                        // After config data is successfully fetched, it must be activated before newly fetched
                        // values are returned.
                        mFirebaseRemoteConfig.activateFetched();
                    } else {
                        Toast.makeText(MainActivity.this, "Fetch Failed",
                                Toast.LENGTH_SHORT).show();
                    }
                    mWelcomeTextView.setText(mFirebaseRemoteConfig.getString("welcome_message"));
                }
            });
}
    

Finalmente, agrega lógica a tu app para forzar la solicitud de recuperación de Remote Config desde la red (sin considerar los datos almacenados de manera local) cuando el valor de CONFIG_STATE sea STALE. Si tu app recupera datos desde la red con mucha frecuencia, Firebase podría limitarla. Consulta Regulación.