Xamarin.Forms安卓真机启动时Firestore获取文档提示客户端离线
问题场景
在Xamarin.Forms项目的App.xaml.cs中,启动阶段通过Firestore检查指定文档是否存在,代码如下:
public partial class App : Application { public App() { CrossFirebaseCrashlytics.Current.HandleUncaughtException(); InitializeComponent(); MainPage = new Page(); MainThread.BeginInvokeOnMainThread(async () => await Loader()); } private async Task Loader() { var firebaseDocExists = false; var firebaseDoc = await CrossCloudFirestore.Current .Instance .Collection("myCollection") .Document("docId") .GetAsync(); firebaseDocExists = firebaseDoc.Exists; if (firebaseDocExists == false) MainPage = new MyPage(); else MainPage = new NavigationPage(new MainPage()); } }
在API 29/31的安卓物理设备启动应用时,触发以下错误:
crc64[alphanumeric_string].CrashlyticsException: Plugin.CloudFirestore.CloudFirestoreException: Failed to get document because the client is offline.
at MyApp.App.Loader ()(:0)
at MyApp.App.<.ctor>b__0_0 ()(:0)
已尝试在Firestore调用前添加await CrossCloudFirestore.Current.Instance.EnableNetworkAsync();但问题未解决;所有API级别的模拟器运行均正常。
解决思路
检查安卓网络权限配置
物理设备可能存在权限缺失,确保AndroidManifest.xml中添加必要权限:<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />针对API 23+,需动态申请网络状态权限,避免系统权限限制导致无法联网。
添加重试机制与缓存策略
Firestore的GetAsync()在缓存无数据且网络未就绪时会直接报错,可添加重试逻辑,同时指定优先从服务器获取、缓存回退的策略:int retryCount = 3; bool success = false; while (retryCount > 0 && !success) { try { var firebaseDoc = await CrossCloudFirestore.Current .Instance .Collection("myCollection") .Document("docId") .GetAsync(Source.ServerAndCache); firebaseDocExists = firebaseDoc.Exists; success = true; } catch (CloudFirestoreException ex) when (ex.Message.Contains("offline")) { retryCount--; await Task.Delay(1000); // 延迟1秒后重试 } }同时确认Firestore离线持久化已启用:
await CrossCloudFirestore.Current.Instance.EnablePersistenceAsync();延后Firestore操作时机
App构造函数属于应用启动早期阶段,此时安卓设备网络服务可能未完全就绪。可将Loader()调用移至OnStart()生命周期方法:protected override async void OnStart() { base.OnStart(); await Loader(); }或者先监听网络状态,确认设备联网后再执行Firestore操作:
var currentState = Connectivity.NetworkAccess; if (currentState != NetworkAccess.Internet) { await Task.Run(async () => { while (Connectivity.NetworkAccess != NetworkAccess.Internet) { await Task.Delay(500); } await Loader(); }); return; } await Loader(); }检查Firebase初始化完整性
确认安卓项目的google-services.json配置正确,Firebase组件初始化完成后再执行Firestore操作:public App() { InitializeComponent(); // 先初始化Firebase FirebaseApp.InitializeApp(Android.App.Application.Context); CrossFirebaseCrashlytics.Current.HandleUncaughtException(); MainPage = new Page(); MainThread.BeginInvokeOnMainThread(async () => await Loader()); }适配Android API 29+特殊配置
API 29+可能存在网络请求限制,在AndroidManifest.xml的<application>标签中添加:android:usesCleartextTraffic="true"API 31及以上需额外添加WiFi状态权限:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />排查物理设备网络环境
确认物理设备处于稳定网络环境,排除弱网、VPN或代理拦截问题;测试设备能否正常访问firestore.googleapis.com,排查DNS解析或网络拦截故障。
内容的提问来源于stack exchange,提问作者Costas

