Context.getFilesDir() 和 Context.getExternalFilesDir() 的区别是什么?

解读

这道题在国内面试中出现频率极高,面试官想确认两点:

  1. 候选人是否真正写过文件存储代码,而不是只会“百度路径”;
  2. 能否把“私有、安全、随卸载、随扫描”这些关键词与业务场景对应起来,避免上线后因为路径选错导致用户投诉或合规下架。
    回答时务必结合国内 ROM(MIUI、EMUI、ColorOS 等)的“存储重定向”“分区存储”“权限弹窗”差异,让面试官感觉你踩过坑。

知识点

  1. 返回路径
    getFilesDir() → /data/data/<包名>/files,位于内部存储,无需任何权限,其它 App 与用户均不可见。
    getExternalFilesDir(String type) → /storage/emulated/0/Android/data/<包名>/files/[type],位于外部私有目录,需 READ/WRITE_EXTERNAL_STORAGE(Android 10 以前)或“所有文件访问”权限(Android 11+ 若走 MediaStore 可豁免)。

  2. 可见性与生命周期
    内部目录随 App 卸载自动删除,不会被 MediaStore 扫描,适合敏感缓存、账号票据。
    外部私有目录同样随卸载删除,但用户可在文件管理器里直接看到,且国内部分 ROM 会把它纳入“清理垃圾”白名单,容易被误删;另外插入电脑 MTP 也能浏览,敏感文件需加密后再写。

  3. 权限与兼容性
    Android 10 分区存储(Scoped Storage)生效后,getExternalFilesDir 不受“共享存储空间”限制,是少数仍能直接 File API 读写的路径,因此国内 App 普遍把“拍照、下载、导出”放在这里,避免 MediaStore 繁琐适配。
    Android 11 引入“所有文件访问” MANAGE_EXTERNAL_STORAGE,但国内商店(应用宝、华为、小米、OPPO)审核趋严,若滥用该权限会被驳回;此时把文件落到 getExternalFilesDir 是最低成本合规方案。

  4. 性能与大小限制
    内部存储在低端机可能只剩几百兆,频繁写大文件(如视频缓存)容易触发“磁盘空间不足”弹窗;外部私有目录可用空间等同于 SD 卡剩余容量,但 SD 卡 IO 延迟高,需在子线程读写。

  5. 备份与恢复
    内部目录可通过 AndroidManifest 中 android:fullBackupContent 规则一键云备份;外部私有目录默认不备份,国内厂商自研备份通道(华为云备份、小米云)也可能跳过它,重要数据需主动迁移至内部或 Database。

答案

getFilesDir() 返回应用内部私有目录,路径为 /data/data/包名/files,无需权限,其他应用无法访问,随卸载自动删除,适合存放敏感或小体积文件;getExternalFilesDir() 返回外部私有目录,路径为 /storage/emulated/0/Android/data/包名/files,Android 10 以前需 WRITE_EXTERNAL_STORAGE 权限,10 以后无需权限即可读写自身目录,用户和 MediaStore 可见,随卸载也自动删除,适合存放拍照、下载、缓存视频等大文件,是国内 App 在分区存储时代合规使用 File API 的主要路径。简单说:前者“内部、安全、小文件”,后者“外部、可见、大文件”,但两者都属于私有空间,卸载即清,不会留下垃圾。

拓展思考

  1. 如果产品要求“卸载后仍保留用户草稿”,两个路径都不满足,只能存到 MediaStore/Download 或 SAF 用户自选目录,并做好文件名冲突处理。
  2. 国内 targetSdk 34 后,getExternalFilesDir 在后台写入时仍可能被“资源访问限制”拦截,需结合 WorkManager 前台服务或用户可见通知,避免触发“后台频繁读写”弹窗。
  3. 折叠屏/多用户场景下,getExternalFilesDir 返回的路径会随用户分身变化,若 App 把绝对路径写死到数据库,切换分身后再读会崩溃,必须动态调用 API 重新获取。