安卓Unity应用后台调用Firebase Storage失败问题排查
问题:Unity安卓应用后台无法执行Firebase Storage调用
我们开发的Unity安卓应用,已创建Android Java插件,通过自定义Service连接并请求Firebase Storage,前台运行时功能完全正常。但启动操作流程(点击按钮)后将应用切至后台,流程虽会启动,但调用Firebase功能时直接停滞,Logcat里只能看到该步骤之前的日志。只有把应用切回前台,流程才会继续,Firebase的OnSuccess回调才会触发,相关日志也能正常显示。
插件调用的Android Service相关代码如下:
private void fbReadStorageTest(){ mHandler.postDelayed(() -> { Log.d(TAG, "[SGA][BgUploadService][fbReadStorageTest] - 10 - Will be testing fb write here [2]... "); StorageReference storageReference = storeRef.child("/test"); Log.d(TAG, "[SGA][BgUploadService][fbReadStorageTest] - 40 -About to read from: "+storageReference.getPath()); storageReference.listAll().addOnSuccessListener(new OnSuccessListener<ListResult>() { @Override public void onSuccess(ListResult listResult) { for (StorageReference item : listResult.getItems()) { // Process each item in the list // Here, you can access item properties like name, path, etc. Log.d("StorageExample", "[SGA][BgUploadService][fbReadStorageTest] - 50.1 - Item Name: " + item.getName()); Log.d("StorageExample", "[SGA][BgUploadService][fbReadStorageTest] - 50.3 - Item Path: " + item.getPath()); } Log.d(TAG, "[SGA][BgUploadService][fbReadStorageTest] - Got List"); } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Log.d(TAG, "[SGA][BgUploadService][fbReadStorageTest] - 140.4 - ListFiles Failed "+e.getMessage()); } }); }, 5000); }
原因分析
- Android后台服务限制:从Android 8.0(API 26)开始,系统对后台普通Service的资源使用有严格限制,应用进入后台后,这类服务会被系统降低优先级甚至暂停,导致Firebase的异步回调无法正常触发。
- 主线程绑定问题:代码里的
mHandler默认绑定主线程(UI线程),应用后台时主线程优先级被大幅降低,postDelayed的任务能启动,但后续Firebase回调依赖的主线程被系统阻塞,无法执行回调逻辑。 - Firebase回调线程策略:Firebase Storage的异步回调默认会回到调用它的线程(此处是主线程),后台状态下主线程受限,自然无法执行回调。
解决方案
- 改用前台Service:把自定义Service改成前台Service,通过显示通知让系统认定服务是用户可见的,避开后台限制。需要在Service中调用
startForeground()方法,传入通知ID和构建好的Notification。 - 后台线程执行Firebase操作:不要在主线程里发起Firebase调用,改用线程池或协程在后台线程执行请求,确保回调也在后台线程处理,不受前台主线程限制。示例代码:
// 创建单线程执行器 ExecutorService backgroundExecutor = Executors.newSingleThreadExecutor(); backgroundExecutor.execute(() -> { StorageReference storageReference = storeRef.child("/test"); Log.d(TAG, "[SGA][BgUploadService][fbReadStorageTest] - 40 -About to read from: "+storageReference.getPath()); storageReference.listAll().addOnSuccessListener(listResult -> { // 在后台线程处理结果 for (StorageReference item : listResult.getItems()) { Log.d("StorageExample", "[SGA][BgUploadService][fbReadStorageTest] - 50.1 - Item Name: " + item.getName()); Log.d("StorageExample", "[SGA][BgUploadService][fbReadStorageTest] - 50.3 - Item Path: " + item.getPath()); } Log.d(TAG, "[SGA][BgUploadService][fbReadStorageTest] - Got List"); }).addOnFailureListener(e -> { Log.d(TAG, "[SGA][BgUploadService][fbReadStorageTest] - 140.4 - ListFiles Failed "+e.getMessage()); }); }); - 检查Firebase初始化:确认Firebase初始化逻辑没有绑定应用前台生命周期,保证后台环境下能正常初始化并工作。
内容的提问来源于stack exchange,提问作者Shefy Gur-ary
相关产品推荐
相关产品推荐

