【问题标题】:How to transfer files between Android applications running on the same device?如何在同一设备上运行的 Android 应用程序之间传输文件?
【发布时间】:2011-11-07 16:57:43
【问题描述】:

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

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

我想到了两种实现方法:

选项 1 - 使用 ContentProvider.openFile

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

选项 2 - 通过服务使用 Messenger

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

选项 3 - 混合方法

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

总结

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

混合方法看起来相当健壮,但实施起来最复杂。文件实际上并没有被传递,所以性能应该很好。但是,我担心这会过度构建解决方案。

在同一 Android 设备上运行的应用程序之间传输文件的最佳方法是什么?当然,我愿意接受我的问题中没有列出的其他选项。

【问题讨论】:

  • 我会像 Android 那样做。将文件存储在 sdcard 上并通过 ContentProvider 提供对文件 URI 而非文件内容的访问。
  • 我只使用选项 1 进行检索,它符合目的。我不认为更新和插入应该更复杂 - 毕竟,你确实有一个与内容提供者的 crud 接口。
  • @mibollma - 我喜欢这个主意,但我不确定它是否能解决整个问题
  • 我会先仔细查看文档和来源,看看这个概念是否符合您的需求。至少听起来有些相似。这里是来源:android.git.kernel.org/?p=platform/packages/providers/…
  • @elevine 嵌入一个 3rd 方应用程序可以通过其通信的小型 http 服务器怎么样。所有请求都将通过 localhost。以前没有尝试过,但这似乎是一种简单的方法。

标签: android ipc android-contentprovider android-service


【解决方案1】:

内容提供商绝对是要走的路。如果您认为 google 几乎所有事情都使用这种方法,那么很明显这是预期的设计方法。

我不是在赞美他们的美德,但在盲人之地,独眼内容提供者为王。

更新

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

Source of Content Provider/Files

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

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

广告结尾

最好的起点是 android-sdk\samples\android-8\SampleSyncAdapter 中的 android SDK 示例,但请注意,有大量与联系人相关的东西掩盖了这些有趣的部分。我花了一段时间才发现我可以删除几乎所有的,除了同步适配器

【讨论】:

  • 我认为 ContenProvider API 在我的用例中缺少一些关键功能。我需要允许第 3 方应用程序请求下载文件,然后在它们准备好时收到通知。我发现它的实现与 ContentProvider 和 ContentObserver 很相配。此外,我的 ContentObservers 没有可靠地触发他们的 onChange 事件。切换到基于 Service/Messenger 的解决方案的情况要好得多。我还没有实现请求上传文件的 3rd 方应用程序的情况,但这似乎不适合 aContentObserver。
  • 使用我的更新中详述的 sych。 android sdk中有一个synch的例子
  • 我认为你是对的,同步适配器方法似乎是一种改进。你有其他好的资源来学习它吗?我的尝试一直基于 Google I/O 2010 Android REST 演讲中的前两种模式。它可能值得克服同步适配器的学习曲线并实现第三种模式:google.com/events/io/2010/sessions/…
  • 害怕我不得不在同样的学习曲线中挣扎。我已经更新了 SDK 示例。我使用的唯一其他资源是did you win yet tuorial。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

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

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

    虽然内容提供者/解析者感觉是处理事情的正确方式,但我确实认为它更多是针对特定于提供/消费内容的单向请求。

    【讨论】:

    • 我不认为 startActivityForResult 和 onActivityResult 完全符合要求。当应用程序想要与我的应用程序共享文件时,它不会启动我的应用程序的一个活动。另外,我发现使用 Messenger,您可以相对轻松地通过 IPC 进行双向通信。
    • 我正在再次使用服务查看 IPC,这还不错。这取决于客户端是否可以实现服务绑定回调和使用消息,但我可以看到 startActvityForResult 和 onActivityResult 对你不起作用。如果他们有 startServiceForResult 就好了。
    猜你喜欢
    • 2012-03-20
    • 1970-01-01
    • 2015-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-07
    • 1970-01-01
    相关资源
    最近更新 更多