Google 致力于为黑人社区推动种族平等。查看具体举措

管理 Firebase 安装

Firebase 安装服务 (FIS) 为每个已安装的 Firebase 应用实例提供一个 Firebase 安装 ID (FID)。这些 Firebase 服务在内部使用 Firebase 安装 ID:

Firebase 服务Firebase 安装功能
Firebase 云消息传递

Firebase 云消息传递使用 Firebase 安装 ID 来定位设备以进行消息传递。

Firebase 应用内消息

Firebase 应用内消息传递使用 Firebase 安装 ID 来定位设备以进行消息传递。

Firebase 性能监控

性能监控使用 Firebase 安装 ID 来计算访问网络资源的唯一 Firebase 安装数量,以确保访问模式足够匿名。它还使用 Firebase 安装 ID 和 Firebase 远程配置来管理性能事件报告的速率。

Firebase 远程配置

远程配置使用 Firebase 安装 ID 选择配置值以返回给最终用户设备。

Firebase 机器学习

Firebase ML 在与应用实例交互时使用称为安装身份验证令牌的凭据进行设备身份验证,例如,将开发人员模型分发到应用实例。

Firebase 用户分段存储

Firebase 用户分段存储存储 Firebase 安装 ID 和相关属性和分段,以向使用它们的其他 Firebase 服务提供定位信息。

通常,Firebase 服务使用 Firebase 安装服务,而无需开发人员直接与 FIS API 交互。但是,在某些情况下,应用程序开发人员可能希望直接调用 FIS API,例如:

  • 删除 Firebase 安装和与安装相关的数据。
  • 检索标识符(Firebase 安装 ID)以定位特定的应用安装。
  • 检索安装身份验证令牌以对 Firebase 安装进行身份验证。

要开始直接调用 FIS API,请将 SDK 添加到您的应用程序中。

将 Firebase 安装 SDK 添加到您的应用

iOS+

  1. 将 Firebase 安装的依赖项添加到您的 Podfile:
    pod 'FirebaseInstallations'
  2. 运行pod install并打开创建的.xcworkspace文件。
  3. 在您的UIApplicationDelegate中导入FirebaseCore模块,以及您的应用委托使用的任何其他Firebase 模块。例如,要使用 Cloud Firestore 和身份验证:

    迅速

    import FirebaseCore
    import FirebaseFirestore
    import FirebaseAuth
    // ...
          

    Objective-C

    @import FirebaseCore;
    @import FirebaseFirestore;
    @import FirebaseAuth;
    // ...
          
  4. 在您的应用委托的application(_:didFinishLaunchingWithOptions:)方法中配置FirebaseApp共享实例:

    迅速

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

    Objective-C

    // Use Firebase library to configure APIs
    [FIRApp configure];

安卓

将 Firebase 安装 Android SDK 的依赖项添加到您的模块(应用级)Gradle 文件(通常是app/build.gradle ):

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

JavaScript

根据您的 Web 应用程序的托管方式,您的配置可能会自动处理,或者您可能需要更新Firebase 配置对象

例如,如果您的依赖项添加在 index.html 中,请在 <head> 元素中添加依赖项:

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

  1. 在 Flutter 项目的根目录中,运行以下命令来安装 Firebase 安装插件:

    flutter pub add firebase_app_installations
    
  2. 重建你的项目:

    flutter run
    
  3. 导入 Firebase 安装插件:

    import 'package:firebase_app_installations/firebase_app_installations.dart';
    

删除 Firebase 安装

与 Firebase 安装相关的数据通常不会识别个人身份。尽管如此,为用户提供管理和删除这些数据的选项还是很有帮助的。

Firebase 安装 ID 对于每个应用程序的每次安装都不同;同一设备上的不同应用程序具有不同的 Firebase 安装 ID。 Firebase 安装 ID 标识应用安装以及与这些应用安装相关的数据。

当您删除安装 ID 时,与该安装 ID 关联的数据会在 180 天内从所有使用 Firebase 安装 ID 识别安装的 Firebase 服务的实时和备份系统中移除。 Google关于删除和保留的声明中对这一过程进行了高级描述。

除非您在应用程序中禁用所有 FID 生成服务,否则 FIS 会在几天内创建一个新 ID。 Firebase 将新创建的 ID 视为新的 Firebase 安装,并且不会以任何方式将其与之前的 ID 或数据相关联。

使用客户端 API 调用删除 FID

要删除 Firebase 服务生成的 FID,请从 Firebase 安装 SDK 调用相应的方法:

迅速

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

使用服务器 API 调用删除 FID

要使用服务器 API 调用删除 FID,请将 Firebase Admin SDK 添加到您的服务器(如果您还没有)。

添加 SDK 后,通过以您选择的语言调用删除函数来删除 FID(注意:除了 Node.js,这些方法反映的是实例 ID 命名。但是,当使用任何当前 Firebase 调用时,它们实际上都会删除 FID开发工具包)。

节点.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)
}

当您使用服务器 API 调用删除 Firebase 安装 ID 时,Firebase 服务会启动删除与该安装 ID 关联的数据的过程,在 1-2 天内停止接受该 ID 的新数据,然后通知客户端应用该ID已被删除。在 Firebase 通知客户端应用之前,该应用的某些服务可能仍以该 ID 为目标 - 例如,Firebase 安装可能会在几个小时内继续接收 FCM 通知。

如果您想删除当前的 Firebase 安装 ID 并立即使用具有新的、不相关的 ID 的 Firebase 服务,请使用客户端 API 来处理删除。

检索客户端标识符

如果您需要识别应用的特定安装,可以通过检索 Firebase 安装 ID 来实现。例如,要在 Firebase 应用内消息开发期间执行测试,您可以使用其 Firebase 安装 ID 识别和定位正确的测试设备。

要检索 Firebase 安装 ID:

迅速

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

检索安装授权令牌

Firebase 服务可以使用从 FIS 检索到的身份验证令牌对 Firebase 安装进行身份验证。例如,在为远程配置设计 A/B 测试时,您可以使用安装身份验证令牌对目标测试设备进行身份验证。

安装身份验证令牌是 JSON Web 令牌 (JWT) 格式的短期不记名令牌,其中包含以下安装信息:

  • Firebase 安装 ID
  • 关联项目 ( projectNumber )
  • 关联的 Firebase 应用程序 ID ( appId )
  • 令牌的到期日期

安装授权令牌不能被撤销,并且在其到期日期之前一直有效。默认令牌生命周期为一周。

要检索安装身份验证令牌:

迅速

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

FirebaseInstallations.getInstance().getToken(/* forceRefresh */ true)
    .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 安装 ID 生命周期

在应用正常运行期间,Firebase 安装 ID (FID) 不需要特殊监控。但是,显式检索和使用 FID 的应用程序应添加逻辑来监控 FID 的潜在删除或轮换。以下是一些可以删除或轮换 FID 的情况:

  • 卸载或重新安装应用程序,例如当最终用户在新设备上安装时。
  • 最终用户清除应用或设备的缓存。
  • 由于应用不活动(当前的阈值是 270 天不活动),在后端触发 FID 删除。

当应用程序在这些情况下遇到 FID 轮换或删除时,它们会被分配一个新的 FID。此外,与已删除 FID 关联的安装身份验证令牌将被删除,无论其自身成熟度如何,并替换为新的安装身份验证令牌。

应用程序可以监控这些变化并做出相应的响应。

要监控 FID 轮换:

迅速

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];
}];

每当分配一个新的 FID 时,一个名为NSNotificationName.InstallationIDDidChange的 NSNotification 就会发布到默认的 NSNotificationCenter。

安卓

Kotlin 和 Java 客户端应添加重试逻辑以响应失败的调用以检索新的 FID。

JavaScript

Web 应用程序可以订阅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');
});

从实例 ID 迁移到 Firebase 安装

在引入 Firebase 安装之前,Firebase 依赖 Instance ID SDK 来识别应用安装。与 Instance ID 相比,Firebase 安装在可靠性、性能和安全性方面具有显着优势。依赖 Instance ID SDK 的 Firebase 应用应迁移到 Firebase 安装。

迁移过程因您的应用而异:

  • 不直接调用 Instance ID API 的应用可以通过更新其 SDK 版本进行迁移。大多数 Firebase 应用都属于这一类。

  • 明确对实例 ID 进行 API 调用的应用必须更新 SDK 版本进行代码更改,以将实例 ID 方法替换为其 Firebase 安装或 FCM 等效项。如果您的应用程序使用实例 ID 来检索 FCM 注册令牌或明确使用实例 ID 来定位应用程序实例或用于任何其他目的,您将需要更新您的应用程序代码。

目前,FIS 与旧标识符 Firebase Instance ID 向后兼容。删除 IID是使用这些 Firebase SDK 请求数据删除的另一种方法:

  • iOS 6.14.0 及更低版本
  • 早于 2020 年 2 月 27 日的 Android SDK

这意味着应用不需要迁移到 Firebase 安装;但是,强烈建议这样做。

为 Firebase 安装升级到最低 SDK 版本

要从实例 ID 迁移到 Firebase 安装,请确保您的应用程序至少使用以下 Firebase SDK 列出的最低版本号:

Firebase SDK最低安卓版本最低 iOS 版本
Firebase 云消息传递v20.3.0 v6.34.0
远程配置v19.2.0 v6.24.0
Google Analytics for Firebase \(测量 SDK) v17.4.4 v6.18.0
应用内消息v19.0.7 v6.24.0
性能监控v19.0.8 v6.21.0
崩溃分析器v17.2.1 v6.23.0
机器学习套件v22.1.2 v6.28.0

更新显式调用实例 ID API 的代码

如果您的 Android 或 Apple 应用直接使用 Instance ID SDK 方法,您可以使用 Firebase 安装 SDK 或 FCM SDK 中的相同替代方法替换该用法。

检索标识符

获取实例 ID 的方法被替换为获取安装 ID 的方法。例如:

迅速

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

迅速

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

删除标识符

删除实例 ID 的方法已替换为删除 Firebase 安装 ID 的方法。例如:

迅速

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

安卓

FirebaseInstanceId.deleteInstanceId();

迅速

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

检索 FCM 注册令牌

在引入 Firebase 安装之前,FCM 客户端从 Instance ID 检索注册令牌。现在,FCM SDK 提供了检索注册令牌的方法。

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

迅速

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

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

迅速

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;
  }
}];