Android Studio中如何访问应用从Firebase下载的文件?
问题分析与解决方案
你的代码存在两个核心问题,导致无法读取下载的XML文件:
1. 异步下载未等待完成就读取
DownloadManager是后台异步执行下载任务的,你在调用downloadFiles()后立刻执行readXML(),此时文件还没下载完成,自然找不到。
2. 文件保存路径与读取路径不匹配
setDestinationInExternalFilesDir()的第二个参数是外部存储应用私有目录的子目录名,不是绝对路径。你传入了getFilesDir().getPath()(内部存储的绝对路径),导致文件实际保存的路径和你读取时用的内部存储路径完全不一致。
修复步骤
步骤1:修正文件保存路径
将downloadFiles()方法中的保存路径改为内部存储(或正确的外部存储路径),这里以内部存储为例:
public long downloadFiles(Context context, String fileName, String fileExtenstion, String subDir, String url){ DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); Uri uri = Uri.parse(url); DownloadManager.Request request = new DownloadManager.Request(uri); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); // 保存到内部存储的应用私有目录,subDir传空字符串表示根目录 request.setDestinationInFilesDir(context, subDir, fileName + fileExtenstion); // 返回下载任务ID,用于后续验证 return downloadManager.enqueue(request); }
步骤2:监听下载完成广播,再读取文件
在Activity中注册广播接收器,等待下载完成后再调用readXML():
private BroadcastReceiver downloadCompleteReceiver; private long downloadId; // 保存当前下载任务的ID @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.your_activity_layout); // 初始化广播接收器 downloadCompleteReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { long completedId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); // 确认是当前下载任务完成 if (completedId == downloadId) { readXML(); } } }; // 注册下载完成的广播过滤器 registerReceiver(downloadCompleteReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); }
步骤3:修改Firebase下载回调,移除立即读取的代码
fDownRef = fStorage.child(lastUploaded); fDownRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() { @Override public void onSuccess(Uri uri) { String strUrl = uri.toString(); Toast.makeText(ExEmElFormat.this, "Downloading...", Toast.LENGTH_LONG).show(); // 保存下载任务ID,传入空字符串作为子目录 downloadId = downloadFiles(ExEmElFormat.this, "RecipeDown", ".xml", "", strUrl); // 移除这里的readXML()调用,等待广播触发 } });
步骤4:修正readXML()中的路径验证
确保验证的路径和保存路径一致:
public void readXML(){ try { fis = openFileInput("RecipeDown.xml"); isr = new InputStreamReader(fis); br = new BufferedReader(isr); sb = new StringBuffer(); String line = br.readLine(); String[] lines = new String[3]; int i = 0; while (i < 3) { sb.append(line+'\n'); line = br.readLine(); lines[i] = line; i++; } String new_name = lines[0].substring(lines[0].indexOf('=')+2, lines[0].indexOf('>')-1); String new_ing = lines[1].substring(lines[1].indexOf('=')+2, lines[1].indexOf('>')-2); String new_steps = lines[2].substring(lines[2].indexOf('=')+2, lines[2].indexOf('>')-2); nameET.setText(new_name); ingredientsET.setText(new_ing); stepsET.setText(new_steps); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // 验证路径是否正确 File xmlf = new File(this.getFilesDir(), "RecipeDown.xml"); System.out.println("XMLF Path:" + xmlf.getAbsolutePath()); System.out.println("XMLF Exists:" + xmlf.exists()); }
步骤5:注销广播接收器(避免内存泄漏)
@Override protected void onDestroy() { super.onDestroy(); if (downloadCompleteReceiver != null) { unregisterReceiver(downloadCompleteReceiver); } }
内容的提问来源于stack exchange,提问作者yuval navon
相关产品推荐
相关产品推荐

