Gerenciar instalações do Firebase

O serviço de instalações do Firebase (FIS, na sigla em inglês) fornece um ID de instalação do Firebase (FID, na sigla em inglês) para cada instância de um app. Esse ID é usado internamente pelos seguintes serviços:

Serviço do Firebase Funcionalidade de instalações do Firebase
Firebase Cloud Messaging

O Firebase Cloud Messaging usa IDs de instalação do Firebase para segmentar os dispositivos que vão receber mensagens.

Firebase Crashlytics

O Firebase Crashlytics rotaciona o UUID da instalação do Crashlytics com base nas alterações feitas no ID de instalação do Firebase da instância do app. No futuro, o ID de instalação poderá ser usado para ativar recursos que melhoram os relatórios de falhas e os serviços de gerenciamento de falhas.

Mensagens no app do Firebase

O recurso Mensagens no app do Firebase usa IDs de instalação do Firebase para segmentar dispositivos que receberão mensagens.

Monitoramento de desempenho do Firebase

O monitoramento de desempenho usa IDs de instalação do Firebase para calcular o número de instalações únicas do Firebase que acessam recursos de rede, com o objetivo de garantir que os padrões de acesso sejam suficientemente anônimos. O monitoramento também usa os IDs de instalação do Firebase com a Configuração remota para gerenciar a taxa de relatórios dos eventos de desempenho.

Configuração remota do Firebase

A Configuração remota usa IDs de instalação do Firebase para selecionar valores de configuração que serão retornados aos dispositivos dos usuários finais.

Firebase ML

As credenciais chamadas tokens de autenticação de instalação são usadas pelo Firebase ML para autenticação de dispositivos que interagem com instâncias de apps, por exemplo, para distribuir modelos de desenvolvedores para instâncias de apps.

Armazenamento da segmentação de usuários do Firebase

Com esse serviço, o Firebase armazena IDs de instalação, bem como atributos e segmentos relacionados, para fornecer informações de segmentação a outros serviços do Firebase que as utilizam.

Normalmente, os serviços do Firebase usam o serviço de instalações dessa plataforma sem exigir que os desenvolvedores interajam diretamente com a API FIS. No entanto, há casos em que pode ser útil para os desenvolvedores de apps chamar diretamente a API FIS, como os mostrados a seguir:

  • Excluir uma instalação do Firebase e os dados vinculados a ela.
  • Recuperar identificadores (IDs de instalação do Firebase) para segmentar instalações de aplicativos específicos.
  • Recuperar tokens de autenticação de instalação para autenticar as instalações do Firebase.

Para começar a chamar diretamente a API FIS, adicione o SDK ao seu app.

Adicionar o SDK de instalação do Firebase ao seu app

iOS+

  1. Adicione a dependência das instalações do Firebase ao seu Podfile:
    pod 'FirebaseInstallations'
  2. Execute pod install e abra o arquivo .xcworkspace criado.
  3. Importe o módulo FirebaseCore no UIApplicationDelegate, assim como qualquer outro módulo do Firebase usado pelo delegado do app. Por exemplo, para usar o Cloud Firestore e o Authentication:

    SwiftUI

    import SwiftUI
    import FirebaseCore
    import FirebaseFirestore
    import FirebaseAuth
    // ...
          

    Swift

    import FirebaseCore
    import FirebaseFirestore
    import FirebaseAuth
    // ...
          

    Objective-C

    @import FirebaseCore;
    @import FirebaseFirestore;
    @import FirebaseAuth;
    // ...
          
  4. Configure uma instância compartilhada do FirebaseApp no método application(_:didFinishLaunchingWithOptions:) do delegado do app:

    SwiftUI

    // Use Firebase library to configure APIs
    FirebaseApp.configure()

    Swift

    // Use Firebase library to configure APIs
    FirebaseApp.configure()

    Objective-C

    // Use Firebase library to configure APIs
    [FIRApp configure];
  5. Se você estiver usando a SwiftUI, crie um delegado do aplicativo e o anexe ao struct App via UIApplicationDelegateAdaptor ou NSApplicationDelegateAdaptor. Também é necessário desativar o swizzling do delegado do app. Para mais informações, consulte as instruções da SwiftUI.

    SwiftUI

    @main
    struct YourApp: App {
      // register app delegate for Firebase setup
      @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
    
      var body: some Scene {
        WindowGroup {
          NavigationView {
            ContentView()
          }
        }
      }
    }
          

Android

Adicione a dependência do SDK para Android das instalações do Firebase ao arquivo Gradle (geralmente app/build.gradle) do seu módulo no app:

implementation 'com.google.firebase:firebase-installations:17.1.4'

JavaScript

Dependendo de como seu aplicativo da Web é hospedado, sua configuração pode ser gerenciada automaticamente ou pode ser necessário atualizar seu objeto de configuração do Firebase.

Por exemplo, se as dependências são adicionadas em index.html, acrescente a dependência no elemento <head>:

<script src="/__/firebase/10.4.0/firebase-installations.js"></script>

Flutter

  1. No diretório raiz do projeto do Flutter, execute o seguinte comando para instalar o plug-in de instalações do Firebase:

    flutter pub add firebase_app_installations
    
  2. Recrie seu projeto:

    flutter run
    
  3. Importe o plug-in de instalações do Firebase:

    import 'package:firebase_app_installations/firebase_app_installations.dart';
    

Excluir uma instalação do Firebase

Geralmente, os dados vinculados a uma instalação do Firebase não são de identificação pessoal. Ainda assim, pode ser útil oferecer aos usuários a opção de gerenciar e excluir esses dados.

Os IDs de instalação do Firebase diferem para cada instalação de cada app. Aplicativos diferentes no mesmo dispositivo têm IDs distintos. Esses IDs identificam instalações de apps e dados vinculados a essas instalações.

Quando você exclui um ID de instalação, os dados vinculados a ele são removidos dos sistemas ativos e de backup de todos os serviços do Firebase que usam esses IDs para identificar instalações em até 180 dias. Esse processo é descrito na declaração do Google sobre exclusão e retenção.

A menos que você desative todos os serviços de geração de FID no seu aplicativo, o FIS criará um novo ID em alguns dias. O Firebase considera o ID recém-criado como uma nova instalação e não o associa ao ID ou aos dados anteriores.

Excluir um FID com uma chamada de API do cliente

Para excluir os FIDs gerados pelos serviços do Firebase, chame o método apropriado no SDK de instalações do Firebase:

Swift

Installations.installations().delete { error in
  if let error = error {
    print("Error deleting installation: \(error)")
    return
  }
  print("Installation deleted");
}

Objective-C

[[FIRInstallations installations] deleteWithCompletion:^(NSError *error) {
   if (error != nil) {
     NSLog(@"Error deleting Installation %@", error);
     return;
   }
   NSLog(@"Installation deleted");
}];

Java

FirebaseInstallations.getInstance().delete()
        .addOnCompleteListener(new OnCompleteListener<Void>() {
    @Override
    public void onComplete(@NonNull Task<Void> task) {
        if (task.isSuccessful()) {
            Log.d("Installations", "Installation deleted");
        } else {
            Log.e("Installations", "Unable to delete Installation");
        }
    }
});

Kotlin+KTX

FirebaseInstallations.getInstance().delete().addOnCompleteListener { task ->
    if (task.isComplete) {
        Log.d("Installations", "Installation deleted")
    } else {
        Log.e("Installations", "Unable to delete Installation")
    }
}

JavaScript

await firebase.installations().delete();

Dart

await FirebaseInstallations.instance.delete();

Excluir um FID com uma chamada de API do servidor

Para excluir um FID com uma chamada de API do servidor, adicione o SDK Admin do Firebase ao seu servidor, caso ainda não tenha feito isso.

Depois que o SDK for adicionado, exclua os FIDs usando uma chamada para a função de exclusão na linguagem de sua preferência. Observação: esses métodos refletem a nomeação do ID da instância, exceto para Node.js. No entanto, todas elas excluem o FID quando chamadas com qualquer SDK atual do Firebase.

Node.js

// An FIDsent from a client service SDK
const idToDelete = 'eyJhbGciOiJFUzI1N_iIs5';

admin.installations().deleteInstallation(idToDelete);

Java

// An FID sent from a client service SDK
String idToDelete = "eyJhbGciOiJFUzI1N_iIs5";

FirebaseInstanceId.getInstance().deleteInstanceIdAsync(idToDelete).get();

Python

  from firebase_admin import instance_id

  # An FID sent from a client service SDK
  id_to_delete = 'eyJhbGciOiJFUzI1N_iIs5'

  instance_id.delete_instance_id(id_to_delete)

Go

client, err := app.InstanceId(ctx)
if err != nil {
  log.Fatalln("error initializing client", err)
}

iidToDelete := "eyJhbGciOiJFUzI1N_iIs5"
if err := client.DeleteInstanceId(ctx, iidToDelete); err != nil {
  log.Fatalln("error deleting FID", err)
}

Quando você exclui um ID de instalação do Firebase com uma chamada de API do servidor, os serviços do Firebase iniciam o processo de exclusão dos dados vinculados a esse ID e param de aceitar novos dados em até dois dias. Depois desse período, os serviços notificam o app cliente sobre a exclusão. Até que o Firebase notifique o app cliente, é possível que alguns dos serviços do app ainda sejam direcionados ao ID. Por exemplo, uma instalação do Firebase pode continuar recebendo notificações do FCM por algumas horas.

Se você quiser excluir o ID de instalação atual do Firebase e usar imediatamente os serviços do Firebase com um novo ID não relacionado, faça a exclusão usando a API cliente.

Recuperar identificadores de clientes

Se você precisa identificar instalações específicas do seu app, é possível fazer isso recuperando o ID de instalação do Firebase. Por exemplo, para criar segmentos de instalações de apps para importação do BigQuery ou realizar testes durante o desenvolvimento do recurso "Mensagens no app" do Firebase, identifique e segmente os dispositivos corretos usando os IDs de instalação do Firebase correspondentes.

Para recuperar um ID de instalação do Firebase:

Swift

Installations.installations().installationID { (id, error) in
  if let error = error {
    print("Error fetching id: \(error)")
    return
  }
  guard let id = id else { return }
  print("Installation ID: \(id)")
}

Objective-C

[[FIRInstallations installations] installationIDWithCompletion:^(NSString *identifier, NSError *error) {
  if (error != nil) {
    NSLog(@"Error fetching Installation ID %@", error);
    return;
  }
  NSLog(@"Installation ID: %@", identifier);
}];

Java

FirebaseInstallations.getInstance().getId()
        .addOnCompleteListener(new OnCompleteListener<String>() {
    @Override
    public void onComplete(@NonNull Task<String> task) {
        if (task.isSuccessful()) {
            Log.d("Installations", "Installation ID: " + task.getResult());
        } else {
            Log.e("Installations", "Unable to get Installation ID");
        }
    }
});

Kotlin+KTX

FirebaseInstallations.getInstance().id.addOnCompleteListener { task ->
    if (task.isSuccessful) {
        Log.d("Installations", "Installation ID: " + task.result)
    } else {
        Log.e("Installations", "Unable to get Installation ID")
    }
}

JavaScript

const installationId = await firebase.installations().getId();
console.log(installationId);

Dart

String id = await FirebaseInstallations.instance.getId();

Recuperar tokens de autorização de instalação

Os serviços do Firebase podem autenticar as instalações do Firebase com tokens de autenticação recuperados do FIS. Por exemplo, ao projetar testes A/B para a Configuração remota, é possível autenticar um dispositivo de teste segmentado usando um token de autenticação da instalação.

Um token de autenticação de instalação é um token do portador de curta duração no formato JSON Web token (JWT) contendo as seguintes informações para uma instalação:

  • O ID de instalação do Firebase
  • O projeto associado (projectNumber)
  • O ID do aplicativo do Firebase associado (appId)
  • A data de validade do token

Um token de autenticação de instalação não pode ser revogado e permanece válido até a data de expiração. A vida útil padrão do token é de uma semana.

Para recuperar um token de autenticação de instalação:

Swift

Installations.installations().authTokenForcingRefresh(true, completion: { (result, error) in
  if let error = error {
    print("Error fetching token: \(error)")
    return
  }
  guard let result = result else { return }
  print("Installation auth token: \(result.authToken)")
})

Objective-C

[[FIRInstallations installations] authTokenForcingRefresh:true
                                               completion:^(FIRInstallationsAuthTokenResult *result, NSError *error) {
  if (error != nil) {
    NSLog(@"Error fetching Installation token %@", error);
    return;
  }
  NSLog(@"Installation auth token: %@", [result authToken]);
}];

Java

FirebaseInstallations.getInstance().getToken(/* forceRefresh */true)
        .addOnCompleteListener(new OnCompleteListener<InstallationTokenResult>() {
    @Override
    public void onComplete(@NonNull Task<InstallationTokenResult> task) {
        if (task.isSuccessful() && task.getResult() != null) {
            Log.d("Installations", "Installation auth token: " + task.getResult().getToken());
        } else {
            Log.e("Installations", "Unable to get Installation auth token");
        }
    }
});

Kotlin+KTX

val forceRefresh = true
FirebaseInstallations.getInstance().getToken(forceRefresh)
    .addOnCompleteListener { task ->
        if (task.isSuccessful) {
            Log.d("Installations", "Installation auth token: " + task.result?.token)
        } else {
            Log.e("Installations", "Unable to get Installation auth token")
        }
    }

JavaScript

const installationToken = await firebase.installations()
    .getToken(/* forceRefresh */ true);
console.log(installationToken);

Dart

String token = await FirebaseInstallations.instance.getToken();

Monitorar o ciclo de vida do ID de instalação do Firebase

Durante a operação normal de um app, os IDs de instalação do Firebase (FIDs) não exigem monitoramento especial. No entanto, os apps que recuperam e usam FIDs explicitamente precisam adicionar lógica para monitorar uma possível exclusão ou rotação do FID. Veja alguns casos em que isso pode acontecer:

  • Durante a desinstalação ou reinstalação do app, por exemplo, quando um usuário final faz a instalação em um novo dispositivo.
  • Quando o usuário final limpa o cache do app ou do dispositivo.
  • Quando a exclusão de FID é acionada no back-end devido à inatividade do app. Atualmente, o período limite de inatividade é de 270 dias.

Quando um FID é excluído ou rotacionado de um app. Nesses casos, eles recebem um novo FID. Além disso, em situações em que o token de autenticação de instalação associado a um FID excluído é removido, independentemente da integridade dele, um novo token de instalação é colocado no lugar.

Os apps podem monitorar essas mudanças e responder de acordo com elas.

Siga estas instruções para monitorar a rotação de FID:

Swift

installationIDObserver = NotificationCenter.default.addObserver(
        forName: .InstallationIDDidChange,
        object: nil,
        queue: nil
) { (notification) in
  // Fetch new Installation ID
  self.fetchInstallationToken()
}

Objective-C

__weak __auto_type weakSelf = self;
self.installationIDObserver = [[NSNotificationCenter defaultCenter]
        addObserverForName: FIRInstallationIDDidChangeNotification
                    object:nil
                     queue:nil
                usingBlock:^(NSNotification * _Nonnull notification) {
    // Fetch new Installation ID
    [weakSelf fetchInstallationsID];
}];

Uma NSNotification chamada NSNotificationName.InstallationIDDidChange é postada no NSNotificationCenter padrão sempre que um novo FID é atribuído.

Android

Os clientes do Kotlin e do Java precisam adicionar a lógica de repetição para responder chamadas com falha para recuperar o novo FID.

JavaScript

Os apps da Web podem se inscrever no gancho onIdChange.

Sempre que um novo FID é criado, o retorno de chamada inscrito é acionado:

await firebase.installations().onIdChange((newId) => {
  console.log(newId);
  // TODO: Handle new installation ID.
});

Dart

FirebaseInstallations.instance.onIdChange.listen((token) {
  print('FID token: $token');
});

Migrar do ID da instância para instalações do Firebase

Antes do lançamento das instalações do Firebase, a plataforma dependia do SDK do ID da instância para identificadores de instalação de apps. As instalações do Firebase oferecem vantagens significativas em relação ao ID da instância em termos de confiabilidade, desempenho e segurança. Os apps do Firebase que dependem do SDK do ID da instância precisam migrar para as instalações do Firebase.

O processo de migração varia de acordo com seu app:

  • Os apps que não chamam diretamente as APIs de ID da instância podem atualizar as versões do SDK para realizar a migração. A maioria dos aplicativos do Firebase se encaixa nessa categoria.

  • Os apps que fazem chamadas de API explicitamente para o ID da instância precisam atualizar as versões do SDK e fazer mudanças no código para substituir os métodos do ID da instância pelas instalações do Firebase ou equivalentes do FCM. Se o app usa o ID da instância para recuperar os tokens de registro do FCM ou usa explicitamente o ID da instância para segmentar instâncias de apps ou para qualquer outra finalidade, você precisa atualizar o código do aplicativo.

Atualmente, o FIS é compatível com versões anteriores do ID da instância legada do Firebase do identificador. Excluir um IID é um método alternativo de solicitação de exclusão de dados com estes SDKs do Firebase:

  • iOS 6.14.0 e mais antigos
  • SDKs do Android anteriores a 27 de fevereiro de 2020

Isso significa que os apps não são obrigatórios na migração para as instalações do Firebase. No entanto, essa ação é altamente recomendada.

Como fazer upgrade para versões mínimas do SDK para instalações do Firebase

Para migrar do ID da instância para as instalações do Firebase, verifique se os aplicativos usam pelo menos os números das versões mínimas listados destes SDKs do Firebase:

SDK do Firebase Versão mínima do Android Versão mínima do iOS
Firebase Cloud Messaging v20.3.0 v6.34.0
Configuração remota v19.2.0 v6.24.0
Google Analytics para Firebase \ (SDK de medição) v17.4.4 v6.18.0
Mensagens no app v19.0.7 v6.24.0
Monitoramento de desempenho v19.0.8 v6.21.0
Crashlytics v17.2.1 v6.23.0
Kit de ML v22.1.2 v6.28.0

Como atualizar o código que chama explicitamente as APIs de ID da instância

Se o app para Android ou Apple usa diretamente os métodos do SDK do ID da instância, é possível substituir esse uso por alternativas idênticas no SDK das instalações do Firebase ou no SDK do FCM.

Como recuperar um identificador

Os métodos para receber IDs de instâncias são substituídos por métodos para receber um ID de instalações. Exemplo:

Antes

Swift

Messaging.messaging().token { token, error in
  if let error = error {
    print("Error fetching remote FCM registration token: \(error)")
  } else if let token = token {
    print("Remote instance ID token: \(token)")
    self.remoteFCMTokenMessage.text = "Remote FCM registration token: \(token)"
  }
}

Objective-C

[[FIRMessaging messaging] tokenWithCompletion:^(NSString * _Nullable token, NSError * _Nullable error) {
   if (error != nil) {
     NSLog(@"Error fetching the remote FCM registration token: %@", error);
   } else {
     NSLog(@"Remote FCM registration token: %@", token);
     NSString* message =
       [NSString stringWithFormat:@"FCM registration token: %@", token];
     self.remoteFCMTokenMessage.text = message;
   }
 }];

Java

FirebaseInstanceId.getInstance().getInstanceId()
        .addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
            @Override
            public void onComplete(@NonNull Task<InstanceIdResult> task) {
                Log.d("IID_TOKEN", task.getResult().getToken());
            }
        });

Kotlin+KTX

FirebaseInstanceId.getInstance().instanceId
        .addOnSuccessListener { result ->
            Log.d("IID_TOKEN", result.token)
        }

Depois

Swift

Installations.installations().installationID { (id, error) in
  if let error = error {
    print("Error fetching id: \(error)")
    return
  }
  guard let id = id else { return }
  print("Installation ID: \(id)")
}

Objective-C

[[FIRInstallations installations] installationIDWithCompletion:^(NSString *identifier, NSError *error) {
  if (error != nil) {
    NSLog(@"Error fetching Installation ID %@", error);
    return;
  }
  NSLog(@"Installation ID: %@", identifier);
}];

Java

FirebaseInstallations.getInstance().getId()
        .addOnCompleteListener(new OnCompleteListener<String>() {
    @Override
    public void onComplete(@NonNull Task<String> task) {
        if (task.isSuccessful()) {
            Log.d("Installations", "Installation ID: " + task.getResult());
        } else {
            Log.e("Installations", "Unable to get Installation ID");
        }
    }
});

Kotlin+KTX

FirebaseInstallations.getInstance().id.addOnCompleteListener { task ->
    if (task.isSuccessful) {
        Log.d("Installations", "Installation ID: " + task.result)
    } else {
        Log.e("Installations", "Unable to get Installation ID")
    }
}

Como excluir um identificador

Os métodos para excluir IDs de instâncias foram substituídos por métodos para excluir IDs de instalações do Firebase. Exemplo:

Antes

Swift

InstanceID.instanceID().deleteID { error in
  if let error = error {
    print("Error deleting instance ID: \(error)")
  }
}

Objective-C

[FIRInstanceID instanceID] deleteIDWithHandler:^(NSError *error) {
  if error != nil {
    NSLog(@"Error deleting instance ID: %@", error);
  }
}];

Android

FirebaseInstanceId.deleteInstanceId();

Depois

Swift

func delete(completion: @escaping (Error?) -> Void)

Objective-C

- (void)deleteWithCompletion:(nonnull void (^)(NSError *_Nullable))completion;

Java

FirebaseInstallations.getInstance().delete()
        .addOnCompleteListener(new OnCompleteListener<Void>() {
    @Override
    public void onComplete(@NonNull Task<Void> task) {
        if (task.isSuccessful()) {
            Log.d("Installations", "Installation deleted");
        } else {
            Log.e("Installations", "Unable to delete Installation");
        }
    }
});

Kotlin+KTX

FirebaseInstallations.getInstance().delete().addOnCompleteListener { task ->
    if (task.isComplete) {
        Log.d("Installations", "Installation deleted")
    } else {
        Log.e("Installations", "Unable to delete Installation")
    }
}

Como recuperar um token de registro do FCM

Antes do lançamento das instalações do Firebase, os clientes do FCM recuperavam os tokens de registro no ID da instância. Agora, o SDK do FCM oferece métodos para recuperação do token de registro.

Antes

Java

FirebaseInstanceId.getInstance().getInstanceId()
        .addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
            @Override
            public void onComplete(@NonNull Task<InstanceIdResult> task) {
                if (!task.isSuccessful()) {
                    Log.w(TAG, "getInstanceId failed", task.getException());
                    return;
                }

                // Get new Instance ID token
                String token = task.getResult().getToken();

                // Log and toast
                String msg = getString(R.string.msg_token_fmt, token);
                Log.d(TAG, msg);
                Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
            }
        });

Kotlin+KTX

FirebaseInstanceId.getInstance().instanceId
        .addOnCompleteListener(OnCompleteListener { task ->
            if (!task.isSuccessful) {
                Log.w(TAG, "getInstanceId failed", task.exception)
                return@OnCompleteListener
            }

            // Get new Instance ID token
            val token = task.result?.token

            // Log and toast
            val msg = getString(R.string.msg_token_fmt, token)
            Log.d(TAG, msg)
            Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
        })

Swift

Messaging.messaging().token { token, error in
  if let error = error {
    print("Error fetching remote FCM registration token: \(error)")
  } else if let token = token {
    print("Remote instance ID token: \(token)")
    self.remoteFCMTokenMessage.text = "Remote FCM registration token: \(token)"
  }
}

Objective-C

[[FIRMessaging messaging] tokenWithCompletion:^(NSString * _Nullable token, NSError * _Nullable error) {
   if (error != nil) {
     NSLog(@"Error fetching the remote FCM registration token: %@", error);
   } else {
     NSLog(@"Remote FCM registration token: %@", token);
     NSString* message =
       [NSString stringWithFormat:@"FCM registration token: %@", token];
     self.remoteFCMTokenMessage.text = message;
   }
 }];

Depois

Java

FirebaseMessaging.getInstance().getToken()
    .addOnCompleteListener(new OnCompleteListener<String>() {
        @Override
        public void onComplete(@NonNull Task<String> task) {
          if (!task.isSuccessful()) {
            Log.w(TAG, "Fetching FCM registration token failed", task.getException());
            return;
          }

          // Get new FCM registration token
          String token = task.getResult();

          // Log and toast
          String msg = getString(R.string.msg_token_fmt, token);
          Log.d(TAG, msg);
          Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
        }
    });

Kotlin+KTX

FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
    if (!task.isSuccessful) {
        Log.w(TAG, "Fetching FCM registration token failed", task.exception)
        return@OnCompleteListener
    }

    // Get new FCM registration token
    val token = task.result

    // Log and toast
    val msg = getString(R.string.msg_token_fmt, token)
    Log.d(TAG, msg)
    Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
})

Swift

Messaging.messaging().token { token, error in
  if let error = error {
    print("Error fetching FCM registration token: \(error)")
  } else if let token = token {
    print("FCM registration token: \(token)")
    self.fcmRegTokenMessage.text  = "Remote FCM registration token: \(token)"
  }
}

Objective-C

[[FIRMessaging messaging] tokenWithCompletion:^(NSString *token, NSError *error) {
  if (error != nil) {
    NSLog(@"Error getting FCM registration token: %@", error);
  } else {
    NSLog(@"FCM registration token: %@", token);
    self.fcmRegTokenMessage.text = token;
  }
}];