Как управлять установками и идентификаторами Firebase

Сервис установок Firebase предоставляет идентификатор установки Firebase для каждого установленного экземпляра приложения Firebase. Идентификатор установки Firebase используется внутри следующих сервисов Firebase:

Сервис Firebase Функции установки Firebase
Firebase Cloud Messaging

Firebase Cloud Messaging использует идентификаторы установки Firebase для таргетинга на устройства при доставке сообщений.

Firebase Crashlytics

Firebase Crashlytics меняет UUID установки Crashlytics в зависимости от изменений идентификатора установки Firebase экземпляра приложения. В будущем идентификатор установки может использоваться для включения функций, которые улучшают отчеты о сбоях и сервисы управления сбоями.

Firebase In-App Messaging

Firebase In-App Messaging использует идентификаторы установки Firebase для таргетинга на устройства при доставке сообщений.

Firebase Performance Monitoring

Performance Monitoring использует идентификаторы установок Firebase, чтобы рассчитать количество уникальных установок Firebase, которые обращаются к сетевым ресурсам. Это позволяет обеспечить достаточную анонимность шаблонов доступа. Кроме того, он использует идентификаторы установки Firebase с Firebase Remote Config, чтобы управлять частотой отправки отчетов о событиях, связанных с производительностью.

Firebase Remote Config

Remote Config использует идентификаторы установки Firebase, чтобы выбирать значения конфигурации, которые будут возвращаться на устройства конечных пользователей. Функция персонализации Remote Config использует идентификаторы установки Firebase, чтобы связывать данные о событиях в приложении с установками Firebase. Это позволяет прогнозировать и возвращать оптимальные значения конфигурации на устройства конечных пользователей.

Firebase ML

Учетные данные, называемые токенами аутентификации установки, используются Firebase ML для аутентификации устройств при взаимодействии с экземплярами приложения, например для распространения моделей разработчика в экземпляры приложения.

Firebase User Segmentation Storage

В хранилище сегментов пользователей Firebase хранятся Firebase идентификаторов установок, а также связанные с ними атрибуты и сегменты. Эти данные используются для таргетинга в других сервисах Firebase.

Обычно сервисы Firebase используют сервис установок Firebase, не требуя от разработчиков прямого взаимодействия с FIS API. Однако в некоторых случаях разработчикам приложений может потребоваться напрямую вызвать FIS API, например:

  • Удаление установки Firebase и связанных с ней данных.
  • Получать идентификаторы (идентификаторы установок Firebase), чтобы настраивать таргетинг на определенные установки приложения.
  • Получение токенов аутентификации для установок Firebase.

Чтобы начать напрямую вызывать FIS API, добавьте SDK в приложение.

Добавьте SDK установок Firebase в приложение

iOS+

  1. Добавьте в Podfile зависимость для установок Firebase:
    pod 'FirebaseInstallations'
  2. Запустите pod install и откройте созданный файл .xcworkspace.
  3. Импортируйте модуль FirebaseCore в UIApplicationDelegate, а также любые другие модули Firebase, которые использует делегат приложения. Например, чтобы использовать свойства Cloud Firestore и 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. Настройте общий экземпляр FirebaseApp в методе application(_:didFinishLaunchingWithOptions:) делегата приложения:

    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. Если вы используете SwiftUI, вам нужно создать делегат приложения и прикрепить его к структуре App с помощью UIApplicationDelegateAdaptor или NSApplicationDelegateAdaptor. Также необходимо отключить подмену делегата приложения. Дополнительную информацию можно найти в инструкциях по 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

Добавьте зависимость для Android SDK установок Firebase в файл Gradle модуля (на уровне приложения), обычно это app/build.gradle:

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

JavaScript

В зависимости от того, как размещено веб-приложение, его конфигурация может обрабатываться автоматически или вам может потребоваться обновить объект конфигурации Firebase.

Например, если зависимости добавлены в index.html, добавьте зависимость в элемент <head>:

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

Flutter

  1. Чтобы установить плагин установок Firebase, выполните следующую команду в корневом каталоге проекта Flutter:

    flutter pub add firebase_app_installations
    
  2. Пересоберите проект.

    flutter run
    
  3. Импортируйте плагин установок Firebase:

    import 'package:firebase_app_installations/firebase_app_installations.dart';
    

Как удалить установку Firebase

Данные, связанные с установкой Firebase, обычно не позволяют идентифицировать личность. Тем не менее, может быть полезно предоставить пользователям возможность управлять этими данными и удалять их.

Идентификаторы установки Firebase уникальны для каждой установки каждого приложения. У разных приложений на одном устройстве будут разные идентификаторы установки Firebase. Идентификаторы установки Firebase позволяют распознавать установки приложения и связанные с ними данные.

Когда вы удаляете идентификатор установки, связанные с ним данные удаляются из рабочих и резервных систем всех сервисов Firebase, которые используют идентификаторы установки Firebase для определения установок, в течение 180 дней. Этот процесс в общих чертах описан в заявлении Google об удалении и хранении данных.

Если вы не отключите все сервисы, генерирующие FID, в своем приложении, FIS создаст новый идентификатор в течение нескольких дней. Firebase считает новый идентификатор новой установкой Firebase и никак не связывает его с предыдущим идентификатором или данными.

Как удалить FID с помощью вызова API клиента

Чтобы удалить идентификаторы установок Firebase, созданные сервисами Firebase, вызовите соответствующий метод из SDK установок Firebase:

Swift

do {
  try await Installations.installations().delete()
  print("Installation deleted");
} catch {
  print("Error deleting installation: \(error)")
}

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

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();

Как удалить FID с помощью вызова API сервера

Чтобы удалить FID с помощью вызова API сервера, добавьте Firebase Admin SDK на сервер, если вы ещё этого не сделали.

После добавления SDK удалите FID, вызвав функцию удаления на выбранном вами языке. Обратите внимание, что за исключением Node.js, эти методы отражают именование идентификатора экземпляра. Однако все они удаляют FID при вызове с любым текущим Firebase SDK.

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)

Проложить маршрут

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)
}

Когда вы удаляете идентификатор установки Firebase с помощью вызова API сервера, сервисы Firebase начинают процесс удаления данных, связанных с этим идентификатором, перестают принимать новые данные для этого идентификатора в течение 1–2 дней, а затем уведомляют клиентское приложение о том, что идентификатор был удален. Пока Firebase не уведомит клиентское приложение, некоторые его сервисы могут по-прежнему использовать идентификатор. Например, в течение нескольких часов на установленное приложение Firebase могут приходить уведомления FCM.

Если вы хотите удалить текущий идентификатор установки Firebase и сразу же начать использовать сервисы Firebase с новым, не связанным с ним идентификатором, используйте клиентский API.

Получение идентификаторов клиентов

Если вам нужно идентифицировать определенные установки приложения, вы можете получить идентификатор установки Firebase. Например, чтобы создать сегменты установок приложений для импорта в BigQuery или провести тестирование во время разработки Firebase In-App Messaging, вы можете идентифицировать нужные устройства и настроить на них таргетинг, используя соответствующие идентификаторы установки Firebase.

Чтобы получить идентификатор установки Firebase, выполните следующие действия:

Swift

do {
  let id = try await Installations.installations().installationID()
  print("Installation ID: \(id)")
} catch {
  print("Error fetching id: \(error)")
}

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

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();

Как получить токены аутентификации установки

Сервисы Firebase могут выполнять аутентификацию установок Firebase с помощью токенов аутентификации, полученных от FIS. Например, при разработке A/B-тестирования для Remote Config вы можете аутентифицировать целевое тестовое устройство с помощью токена аутентификации установки.

Токен аутентификации установки – это токен на предъявителя с коротким сроком действия в формате веб-токена JSON (JWT), содержащий следующую информацию об установке:

  • Идентификатор установки Firebase
  • Связанный проект (projectNumber)
  • Идентификатор связанного приложения Firebase (appId).
  • Срок действия токена.

Токен авторизации установки нельзя отозвать, и он остается действительным до даты окончания срока действия. По умолчанию срок действия токена составляет одну неделю.

Чтобы получить токен аутентификации установки, выполните следующие действия:

Swift

do {
  let result = try await Installations.installations()
    .authTokenForcingRefresh(true)
  print("Installation auth token: \(result.authToken)")
} catch {
  print("Error fetching token: \(error)")
}

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

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();

Отслеживание жизненного цикла идентификатора установки Firebase

При нормальной работе приложения идентификаторы установки Firebase (FID) не требуют специального мониторинга. Однако в приложения, которые явно получают и используют FID, следует добавить логику для отслеживания потенциального удаления или ротации FID. Вот несколько примеров того, когда идентификаторы Firebase могут быть удалены или заменены:

  • Удаление или переустановка приложения, например когда конечный пользователь устанавливает его на новое устройство.
  • Конечный пользователь очищает кеш приложения или устройства.
  • Удаление FID запускается в бэкенде из-за неактивности приложения (в настоящее время пороговое значение составляет 270 дней неактивности).

В таких случаях приложениям назначается новый FID. Кроме того, токен аутентификации установки, связанный с удаленным FID, удаляется независимо от срока его действия и заменяется новым токеном аутентификации установки.

Приложения могут отслеживать эти изменения и реагировать на них.

Чтобы отслеживать ротацию FID:

Swift

installationIDObserver = NotificationCenter.default.addObserver(
        forName: .InstallationIDDidChange,
        object: nil,
        queue: nil
) { (notification) in
  // Fetch new Installation ID
  Task {
    await 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];
}];

При назначении нового идентификатора установки Firebase в NSNotificationCenter по умолчанию отправляется уведомление NSNotification с именем NSNotificationName.InstallationIDDidChange.

Android

Клиенты Kotlin и Java должны добавить логику повторных попыток, чтобы реагировать на неудачные вызовы для получения нового FID.

JavaScript

Веб-приложения могут подписаться на хук onIdChange.

При создании нового FID активируется обратный вызов:

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

Dart

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

Переход с Instance ID на установки Firebase

До появления установок Firebase Firebase использовал Instance ID SDK для идентификаторов установок приложений. Firebase. Приложения Firebase, которые зависят от Instance ID SDK, должны перейти на установки Firebase.

Процесс переноса зависит от типа приложения:

  • Приложения, которые не вызывают Instance ID API напрямую, можно перевести на новую версию, обновив SDK. К этой категории относится большинство приложений Firebase.

  • Если приложение явно вызывает API Instance ID, необходимо обновить SDK и изменить код, чтобы заменить методы Instance ID эквивалентными методами Firebase или FCM. Если ваше приложение использует Instance ID для получения токенов регистрации FCM или явным образом использует Instance ID для таргетинга на экземпляры приложения или в других целях, вам нужно обновить код приложения.

В настоящее время FIS обратно совместим с устаревшим идентификатором экземпляра Firebase. Удаление идентификатора экземпляра – это альтернативный способ запросить удаление данных с помощью следующих Firebase SDK:

  • iOS 6.14.0 и более ранних версий
  • Android SDK, выпущенные до 27 февраля 2020 г.

Это означает, что разработчикам не обязательно переходить на установки Firebase, однако мы настоятельно рекомендуем это сделать.

Переход на минимальные версии SDK для Firebase установок

Чтобы перейти с Instance ID на установки Firebase, убедитесь, что в ваших приложениях используются как минимум указанные ниже версии Firebase SDK:

Firebase SDK Минимальная версия Android Минимальная версия iOS
Firebase Cloud Messaging v20.3.0 v6.34.0
Remote Config v19.2.0 v6.24.0
Google Аналитика для Firebase \ (SDK для отслеживания) v17.4.4 v6.18.0
In-App Messaging 19.0.7 v6.24.0
Performance Monitoring v19.0.8 v6.21.0
Crashlytics v17.2.1 v6.23.0
ML Kit v22.1.2 v6.28.0

Обновление кода, который явно вызывает Instance ID API

Если в вашем приложении для Android или Apple напрямую используются методы Instance ID SDK, вы можете заменить их на аналогичные альтернативы в SDK Firebase или FCM.

Как получить идентификатор

Методы получения идентификаторов экземпляров заменены методами получения идентификаторов установок. Пример:

До

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)")
  }
}

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];
    // display message
    NSLog(@"%@", 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

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

После

Swift

do {
  let id = try await Installations.installations().installationID()
  print("Installation ID: \(id)")
} catch {
  print("Error fetching id: \(error)")
}

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

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

Удаление идентификатора

Методы удаления идентификаторов экземпляров заменены методами удаления идентификаторов установок Firebase. Пример:

До

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();

После

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

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

Получение токена регистрации FCM

До появления Firebase Installations клиенты FCM получали токены регистрации из Instance ID. Теперь SDK FCM предоставляет методы для получения токена регистрации.

До

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

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

InstanceID.instanceID().instanceID { result, error in
  if let error = error {
    print("Error fetching instance ID: \(error)")
  } else if let result = result {
    print("Instance ID token: \(result.token)")
  }
}

Objective-C

[[FIRInstanceID instanceID] instanceIDWithHandler:^(FIRInstanceIDResult * _Nullable result,
                                                    NSError * _Nullable error) {
  if (error != nil) {
    NSLog(@"Error fetching instance ID: %@", error);
  } else {
    NSLog(@"Instance ID token: %@", result.token);
  }
}];

После

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

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 remote FCM registration token: \(error)")
  } else if let token = token {
    print("Remote instance ID 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];
    // display message
    NSLog(@"%@", message);
  }
}];