Firebase 安装服务 (FIS) 为每个已安装的 Firebase 应用实例提供一个 Firebase 安装 ID (FID)。 Firebase 安装 ID 由以下 Firebase 服务在内部使用:
火力地堡服务 | Firebase 安装功能 |
---|---|
Firebase 云消息传递 | Firebase 云消息传递使用 Firebase 安装 ID 来定位设备以进行消息传递。 |
Firebase 应用内消息 | Firebase 应用内消息使用 Firebase 安装 ID 来定位设备以进行消息传递。 |
Firebase 性能监控 | 性能监控使用 Firebase 安装 ID 来计算访问网络资源的唯一 Firebase 安装数量,以确保访问模式充分匿名。它还使用 Firebase 安装 ID 和 Firebase Remote Config 来管理性能事件报告的速率。 |
Firebase 远程配置 | Remote Config 使用 Firebase 安装 ID 来选择配置值以返回给最终用户设备。 |
火力地堡机器学习 | 在与应用程序实例交互时,Firebase ML 使用称为安装身份验证令牌的凭证进行设备身份验证,例如,将开发人员模型分发到应用程序实例。 |
Firebase 用户细分存储 | Firebase User Segmentation Storage 存储 Firebase 安装 ID 和相关属性和细分,以便为使用它们的其他 Firebase 服务提供定位信息。 |
通常,Firebase 服务使用 Firebase 安装服务,无需开发人员直接与 FIS API 交互。但是,在某些情况下,应用程序开发人员可能希望直接调用 FIS API,例如:
- 删除 Firebase 安装和与安装相关的数据。
- 检索标识符(Firebase 安装 ID)以定位特定的应用程序安装。
- 检索安装身份验证令牌以验证 Firebase 安装。
要开始直接调用 FIS API,请将 SDK 添加到您的应用程序。
将 Firebase 安装 SDK 添加到您的应用
iOS+
- 将 Firebase 安装的依赖项添加到 Podfile:
pod 'FirebaseInstallations'
- 运行
pod install
并打开创建的.xcworkspace
文件。 - 在您的
UIApplicationDelegate
中导入FirebaseCore
模块,以及您的应用委托使用的任何其他Firebase 模块。例如,要使用 Cloud Firestore 和身份验证:斯威夫特用户界面
import SwiftUI import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
迅速
import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
目标-C
@import FirebaseCore; @import FirebaseFirestore; @import FirebaseAuth; // ...
- 在您的应用委托的
application(_:didFinishLaunchingWithOptions:)
方法中配置一个FirebaseApp
共享实例:斯威夫特用户界面
// Use Firebase library to configure APIs FirebaseApp.configure()
迅速
// Use Firebase library to configure APIs FirebaseApp.configure()
目标-C
// Use Firebase library to configure APIs [FIRApp configure];
- 如果您使用的是 SwiftUI,则必须创建一个应用程序委托并通过
UIApplicationDelegateAdaptor
或NSApplicationDelegateAdaptor
将其附加到您的App
结构。您还必须禁用应用委托调配。有关详细信息,请参阅SwiftUI 说明。斯威夫特用户界面
@main struct YourApp: App { // register app delegate for Firebase setup @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate var body: some Scene { WindowGroup { NavigationView { ContentView() } } } }
安卓
将 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.16.0/firebase-installations.js"></script>
扑
在 Flutter 项目的根目录中,运行以下命令来安装 Firebase 安装插件:
flutter pub add firebase_app_installations
重建你的项目:
flutter run
导入 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"); }
目标-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)") }
目标-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 安装进行身份验证。例如,在为 Remote Config 设计 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)") })
目标-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() }
目标-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 实例 ID。删除 IID是使用这些 Firebase SDK 请求删除数据的替代方法:
- iOS 6.14.0 及更低版本
- 2020 年 2 月 27 日之前的 Android SDK
这意味着应用程序不需要迁移到 Firebase 安装;但是,强烈建议这样做。
升级到 Firebase 安装的最低 SDK 版本
要从实例 ID 迁移到 Firebase 安装,请确保您的应用程序至少使用以下 Firebase SDK 列出的最低版本号:
火力地堡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)" } }
目标-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)") }
目标-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)")
}
}
目标-C
[FIRInstanceID instanceID] deleteIDWithHandler:^(NSError *error) {
if error != nil {
NSLog(@"Error deleting instance ID: %@", error);
}
}];
安卓
FirebaseInstanceId.deleteInstanceId();
后
迅速
func delete(completion: @escaping (Error?) -> Void)
目标-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 客户端从实例 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)" } }
目标-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)" } }
目标-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; } }];