如何在同一设备上运行的Android应用程序之间传输文件?

时间:2011-08-31 14:58:52

标签: android ipc android-contentprovider android-service

我正在编写一个与RESTful服务接口的Android应用程序。此Web服务基本上是文件系统的前端,并提供元数据以及对文件的CRUD访问。我的应用程序检索元数据,并通过ContentProvider将其公开给第三方应用程序。

我需要为与我的应用程序在同一设备上运行的第三方应用程序添加能力,通过向我/我的应用程序发送请求(而不是直接与服务器)来CRUD实际文件。这意味着他们需要通过我的应用程序发送或接收文件的内容(通常是XML或图像)。

我想到了实现这个的两种方法:

选项1 - 使用ContentProvider.openFile

这似乎是让第三方应用程序能够从我的ContentProvider读取文件的明显选择。我认为当这些应用程序需要通过我的`ContentProvider'创建或更新文件时,它开始变得棘手。完成后我需要回调才能知道何时将新的/更改的文件发送回服务器。我相信我可以使用FileObserver来达到这个目的。

选项2 - 通过服务使用Messenger

通过这种方法,我可以通过Messenger在我的应用程序和客户端应用程序之间发送文件。这些文件必须通过Bundle传递,所以我不确定传输它们的最佳格式是什么(FileFileDescriptor,字节数组,还有其他什么?)。如果文件变得很大,我不能很好地处理这会导致问题。

选项3 - 混合方法

  1. 将外部存储空间中的文件夹用作下拉框
  2. 通过Messenger / Service
  3. 传达CRUD请求和删除框内容
  4. 使用ContentProvider存储请求状态
  5. 第三方应用通过ContentObserver
  6. 接收状态更新

    摘要

    我认为使用ContentProvider将是理想的解决方案,但似乎API并不完全支持我的用例。我担心尝试沿着这条路走下去可能会导致一个愚蠢的实施。如果我采用MessengerService方法,我不确定通过Bundle传输文件的最强大方法。

    混合方法看起来非常强大,但实施起来最复杂。文件实际上并没有被传递,因此性能应该很好。但是,我担心这会过度设计解决方案。

    在同一个Android设备上运行的应用程序之间传输文件的最佳方法是什么?当然,我对其他选项持开放态度,我没有在我的问题中概述过。

3 个答案:

答案 0 :(得分:16)

内容提供商绝对是您的选择。如果你认为谷歌几乎所有的东西都使用这种方法,那么这就是预期的设计方法。

我并不是在颂扬他们的美德,但在盲人的土地上,独眼的内容提供商是王者。

<强>更新

有一个如何在CommonsWare书中执行此操作的示例,请参阅提供的链接。

Source of Content Provider/Files

对内容提供商使用synch框架。只需维护一个请求列表,然后安排同步以下载这些文件。您也可以通过网络勾选等方式执行此操作。您可以使用广播意图或contentobserver通知客户端文件已下载。

本质上这可能类似于你的第三个选项,但重要的是它使用Android提供的工具而不是自己动手。

Ad Endum

最好的起点是android SDK示例:android-sdk \ samples \ android-8 \ SampleSyncAdapter但要注意的是,有大量的联系人相关的东西掩盖了多汁的比特。我花了一段时间才发现除了syncadapter

之外我几乎可以删除所有内容

答案 1 :(得分:3)

可以在进程之间发送

http://developer.android.com/reference/android/os/ParcelFileDescriptor.html。我相信有一个巧妙的地方,这些被明确列入黑名单,允许被置于意图之中。它们可以通过AIDL发送。 另外,请勿使用SD卡。这只是在寻找麻烦。一张SD卡是世界可读的,所以任何人都可以看到它。此外,您并不总是有权写入SD卡(它被删除或放入UMS)。

答案 2 :(得分:2)

使用SD卡绝对是recommended在Android上共享文件的方式。

但是,我会使用经过修改的混合解决方案,该解决方案在客户端使用startActivityForResult()onActivityResult()(文档here)来传达CRUD请求(并将Uri发送到如果您不介意创建虚拟活动作为服务的前端,则SD卡上的文件(如果需要)。一旦完成文件,客户可以再次致电startActivityForResult()以提醒您的应用更改。

当然,这可以通过startService() / bindService()完成,但是它不能为客户提供获取状态结果的简便方法,尤其是在您需要IPC时。

虽然内容提供商/解析器感觉是正确的做事方式,但我觉得更多的是针对提供/消费内容的单向请求。