文件共享 IPC 面试十题精华笔记

深入理解 Android 文件共享机制,掌握面试高频考点

共 10 题 文件共享 面试必备 模拟面试

目录导航(点击跳转)

1 文件共享 vs Binder IPC 的优势与劣势
问题:文件共享 vs Binder IPC 的优势与劣势
参考答案:

优势

  • 无数据量限制:不受 Binder 1MB 限制,可传 GB 级文件
  • 数据持久化:进程死后数据仍在,重启可继续读写
  • 跨平台简单:纯文件操作,不依赖 Android Binder 框架

劣势

  • 无内置通知:读方不知道数据何时就绪,需额外通知机制
  • 速度慢:磁盘 IO 毫秒级,Binder 内存操作微秒级
  • 并发复杂:多进程同时读写需要自行处理锁或原子写入
你的回答:正确回答完整。
2 大视频下载后让另一进程播放
问题:大视频下载后让另一进程播放
参考答案:

存储位置

context.getExternalFilesDir(Environment.DIRECTORY_MOVIES)

  • 同应用多进程属同一 UID,可无障碍访问
  • 不需要存储权限
  • 路径深,用户不易误删

防损坏方案:原子操作

  • 1. 数据写入临时文件 video.mp4.tmp
  • 2. 全部下载完成后 tempFile.renameTo(targetFile)
  • 3. 同一分区内 renameTo 是原子操作,瞬间替换
  • 4. 读方永远读到完整的旧文件或完整的新文件

通知方式

  • 同应用:LocalBroadcastManagerFileObserver
  • 不同应用:全局广播(需权限控制)或 AIDL 回调
扩展知识:原子写入代码示例
fun safeWriteFile(targetFile: File, data: ByteArray) {
    val tempFile = File(targetFile.parent, "${targetFile.name}.tmp")
    tempFile.writeBytes(data)
    if (!tempFile.renameTo(targetFile)) {
        tempFile.delete()
        throw IOException("Failed to rename file")
    }
}
你的回答:正确回答完整。
3 renameTo 原子性原理及失败处理
问题:renameTo 原子性原理及失败处理
参考答案:

原子性原理

  • 文件名与数据块分离存储,renameTo 只是修改指针指向
  • 文件系统保证此操作不可中断,不存在“一半旧一半新”的中间状态

失败场景

  • 跨文件系统(如内部存储 ↔ SD卡)
  • 权限不足、磁盘满、目标目录不存在

失败处理

  • renameTo 失败时临时文件不自动删除,需手动 tempFile.delete()
  • 确保临时文件和目标文件在同一目录,避免跨分区
你的回答:正确回答完整。
4 文件就绪后的通知方式
问题:文件就绪后的通知方式
参考答案:
方式优点缺点适用场景
广播简单,可跨应用数据量小,全局广播不安全同应用低频率通知
FileObserver实时性好,高效仅限同 UID同应用多进程
ContentObserver标准跨应用通知需依赖 ContentProvider跨应用文件共享
Messenger/AIDL双向实时,可带结构化数据需绑定 Service双向通信场景
推荐组合:同应用→FileObserver;跨应用→ContentObserver + ContentProvider
你的回答:正确回答完整。
5 两进程同时写同一文件的解决方案
问题:两进程同时写同一文件的解决方案
参考答案:
  • 文件锁(FileLock)FileChannel.lock()排他锁,适用于短时小数据写入
  • 临时文件 + 原子重命名:每个进程写独立临时文件,最后 renameTo 原子替换(后写胜出)
  • 单一写者:只允许一个进程写入,其他只读,最简单可靠

选型建议

  • 小数据、短时间 → 文件锁
  • 大文件、覆盖写 → 原子 rename
  • 任何场景都可用 → 单一写者
你的回答:正确回答完整。
6 大 JSON 列表为什么必须流式序列化
问题:大 JSON 列表为什么必须流式序列化
参考答案:

一次性序列化会将整个对象列表和完整 JSON 字符串同时放在内存中,极易 OOM。

流式序列化(如 JsonWriter)遍历数据源,来一条写一条,内存中永远只保留当前一条数据的大小。

扩展知识:流式读写示例
// 流式写入
fun streamWriteJson(file: File, books: Flow) {
    FileOutputStream(file).use { outputStream ->
        JsonWriter(outputStream.writer()).use { writer ->
            writer.beginArray()
            books.collect { book ->
                writer.beginObject()
                writer.name("id").value(book.id)
                writer.name("name").value(book.name)
                writer.endObject()
            }
            writer.endArray()
        }
    }
}
你的回答:正确回答完整。
7 不同 App 之间安全共享文件
问题:不同 App 之间安全共享文件
参考答案:

推荐方案:FileProvider

  • 文件始终存放在私有目录
  • 通过 FileProvider.getUriForFile()生成 content://URI
  • Intent 携带 URI 并添加 FLAG_GRANT_READ_URI_PERMISSION临时授权
  • 接收方通过 contentResolver.openInputStream(uri)读取,无需存储权限
扩展知识:关键配置
<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="com.example.app.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths"/>
</provider>
你的回答:正确回答完整。
8 FileProvider 安全共享原理
问题:FileProvider 安全共享原理
参考答案:
  • 文件不动:始终在私有目录,不暴露真实路径
  • URI 映射:真实路径映射为 content://URI
  • 临时授权:通过 FLAG_GRANT_READ_URI_PERMISSION授予临时读权限,任务栈销毁后自动回收
  • 无需存储权限:接收方通过 ContentResolver 读取,由 FileProvider 进程打开文件并通过 Binder 传回数据
你的回答:正确回答完整。
9 高频小数据选文件共享还是 Messenger?
问题:高频小数据选文件共享还是 Messenger?
参考答案:

选择 Messenger:内存操作极快(微秒级),消息队列天然线程安全,数据到即通知。

文件共享磁盘 IO 慢(毫秒级),频繁写入伤闪存,且需要额外处理并发和通知。

决策原则

  • 小数据 + 高频 + 实时 → Binder 类(Messenger/AIDL)
  • 大数据 + 低频 + 持久化 → 文件共享
你的回答:正确回答完整。
10 多进程项目 IPC 综合决策
问题:多进程项目 IPC 综合决策
参考答案:
场景数据特点IPC 选择理由
下载进度回调高频、小数据AIDL 回调服务端主动推送,实时性高
启动下载任务一次性配置参数Bundle/Intent简单高效
下载完成的音乐文件大文件文件共享+广播突破 Binder 限制
播放状态同步状态小数据Messenger/AIDL低延迟双向

决策框架

  • 数据 >1MB? → 必须文件共享
  • 需要持久化? → 文件或数据库
  • 需要实时通知? → AIDL/Messenger
  • 跨应用安全共享? → FileProvider + URI 授权
你的回答:正确回答完整。

核心思想总结