本篇文章只快速介绍解决方案,详细分析看其他文章。通过配置延迟Firebase初始化,Android延时和ReactNative也是同理。
2020年7月工信部发布了《关于开展纵深推进APP侵害用户权益专项整治行动的通知》工信部信管函〔2020〕164号文。重点对专项行动中“APP、SDK违规处理用户个人信息”“设置障碍、频繁骚扰用户”“欺骗误导用户”“应用分发平台责任落实不到位”四方面10类问题进行集中排查。
2022年开始国内各大应用商店加大对APP合规的检查,像华为商店审核不通过就不让上架,其他商店在合规没通过的情况有可能被下架,问题最好能提前排查。
项目早期是以海外为主,后面又需要在国内上线,那就刚好进入本篇文章的坑。
google官方文档
flutter相关的firebase库,google官方独立了个网站。
Flutter v2.10.5
firebase_core: ^1.10.0
firebase_messaging: ^10.0.0
firebase_crashlytics: ^2.2.0
firebase_analytics: ^9.1.0
firebase_performance: ^0.7.0+3
dependency_overrides:
firebase_messaging_platform_interface: 3.1.6
firebase_crashlytics_platform_interface: 3.1.13
firebase_analytics_platform_interface: 3.0.5
根据工信部的要求,android合规检测中,发现firebase有以下3个问题。
FirebaseApp是Firebase核心类,也是其他firebase库必须依赖的类,只有这个被初始化完,其他的库才能初始化。
既然3个问题都是在App未经用户同意就触发不合规的行为,那只要在隐私政策中说明获取的目的,再等到用户同意隐私政策后,再执行这些行为。
问题分析:主要是firebase_performance库的问题,在初始化的时候会去获取软件安装列表,判断当前是否是主进程。
firebase_performance 根据官方说法主要作用是性能统计,会自动开始收集与应用生命周期相关的数据(例如应用启动时间),以及HTTP/S 网络请求的情况。
解决方案:
在AndroidManifest.xml中接入以下代码,重点在tools:node=“remove”,将这个provider移除掉。再在代码层面控制初始化即可。
<application>
...
<provider
android:authorities="${applicationId}.firebaseperfprovider"
android:exported="false"
android:initOrder="101"
android:name="com.google.firebase.perf.provider.FirebasePerfProvider"
tools:node="remove"/>
...
</>
然后再在同意隐私政策后初始化,参考初始化firebase_performance demo。
void initFlutterPerformance() async {
performance = FirebasePerformance.instance;
await performance!.setPerformanceCollectionEnabled(true);
final bool isEnabled = await performance!.isPerformanceCollectionEnabled();
print(isEnabled
? "Performance collection is enabled."
: "Performance collection is disabled.");
}
其实问题2、3可以通过同一个解决方案。
问题分析:主要是firebase_analytics库的问题,在初始化的时候会去发起请求配置文件,产生网络流量,但关闭App重新启动,第二次初始化会用缓存。并且在初始化中,会获取android id来判断当前手机是不是模拟器。
firebase_crashlytics Crashlytics 可收集有关应用程序中发生的崩溃和错误的分析和详细信息。
解决方案:
类似上面,在AndroidManifest.xml中的application层级加入以下代码,重点在tools:node=“remove”,将这个provider移除掉。
<application>
...
<provider
android:name="com.google.firebase.provider.FirebaseInitProvider"
android:authorities="${applicationId}.firebaseinitprovider"
android:exported="false"
tools:node="remove"
/>
...
</>
注意这里移除掉的是整个Firebase的初始化,不是移除FirebaseCrashlytics这个库,因为FirebaseCrashlytics的初始化是依赖Firebase核心的初始化(也叫FirebaseApp),所以只要延迟FirebaseApp的初始化就能延迟FirebaseCrashlytics初始化。
以Flutter为例,上面已经去掉了Firebase自动初始化的过程,还需要通过代码初始化才能保证功能正常。
正常来说,只要在合适的时机执行以下代码就能完成初始化。
Firebase.initializeApp();
由于Flutter Firebase库,在flutter层进行了限制,调用initializeApp函数什么都没有传递,则会抛出以下错误:
Firebase has not been correctly initialized.
源码分析:
注意这里的版本是firebase_core_platform_interface-4.2.4,最新v4.4.3版本有点小改动。
//firebase_core_platform_interface-4.2.4/lib/src/method_channel/method_channel_firebase.dart
@override
Future<FirebaseAppPlatform> initializeApp({
String? name,
FirebaseOptions? options,
}) async {
if (!isCoreInitialized) {
await _initializeCore();
}
if (name == null || name == defaultFirebaseAppName) {
// 获取默认的FirebaseApp
MethodChannelFirebaseApp? defaultApp =
appInstances[defaultFirebaseAppName];
// 什么都没传递,抛出错误
if (defaultApp == null && options == null) {
throw coreNotInitialized();
}
return appInstances[defaultFirebaseAppName]!;
}
...
}
所以按照官方文档的描述flutter firebase初始化文档,通过命令生成firebase_options.dart文件,再在初始化的时候引用该文件的方法。
正确的初始化方式如下:
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform,);
在使用firebase_analytics:8.1.0的版本时,也就是^9.1.0以下的版本时,发现按照以上解决方案在AndroidManifest.xml中去掉两个初始化provider,但没有效果,依然会自动初始化FirebaseApp核心库。
使用debug模式定位:
找到问题,在Flutter加载firebase_analytics插件时,就在原生侧调用了一次 FirebaseApp.initializeApp(applicationContext);,所以出现了自动初始化的问题,这个问题还是比较隐蔽,不容易发现。
解决办法:升级firebase_analytics: ^9.1.0以上即可。
Flutter调用onAttachedToEngine方法加载firebase_analytics插件时,并没有调用初始化initializeApp方法,这样才是正确的,把初始化的控制权限交给用户,而不是在某个Firebase库中。
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
initInstance(binding.getBinaryMessenger(), binding.getApplicationContext());
}
可以看到从firebase_analytics: ^9.1.0开始,就不会在库内初始化FirebaseApp,在使用firebase_analytics之前,自行完成相关初始化。