You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 22:45:29