android - 通过Seekable Pipe或Stream与其他Android应用共享?

标签 android android-intent android-contentprovider

许多Intent操作(例如ACTION_VIEW)都采用Uri指向应对其执行操作的内容。如果内容由文件支持-Uri是直接指向文件还是服务于文件的ContentProvider(see FileProvider ),则通常可以正常工作。

在某些情况下,开发人员不想让内容驻留在文件中以便与其他应用程序共享。一种常见的情况是加密:解密后的数据应驻留在RAM中,而不是磁盘上,以最大程度地降低有人获取解密后的数据的风​​险。

我从RAM共享的经典解决方案是use ParcelFileDescriptor and createPipe() 。但是,当响应ACTION_VIEW(或其他内容)的 Activity 在该管道上获得InputStream时,与ContentProvider提供文件中的内容时得到的流相比,结果流受到限制。例如,this sample app与Adobe Reader配合良好,会使QuickOffice崩溃。

基于past related问题,我的假设是createPipe()确实在创建管道,而pipes are non-seekable。试图“倒带”或“快进”的客户因此遇到了问题。

我正在寻找一种可靠的解决方案,用于与第三方应用程序共享内存内容,从而克服了这一限制。具体来说:

  • 它必须使用可能由客户端应用程序(即Uri实现者)认可的ACTION_VIEW语法;涉及到客户端应用程序不太可能识别的钝度的解决方案(例如,通过Intent额外地通过某某方式传递)不符合
  • 的条件
  • 作为共享的一部分,不能将要共享的数据写到文件中(当然,客户端应用程序可以将接收到的字节保存到磁盘上,但是暂时忽略这种风险)
  • 理想情况下,它不涉及寻求共享数据的应用程序以打开ServerSocket或以其他方式加剧安全风险

  • 可能的建议构想包括:
  • 重新配置createPipe()的某种方法,导致可搜索的管道
  • 使用基于套接字的FileDescriptor的某种方法,该方法导致可搜索的管道
  • 某种RAM磁盘或其他与Android其余部分类似的文件,但不是持久的

  • 一个可行的解决方案的一个关键标准是,是否可以从RAM中获取QuickOffice可以读取的PDF。

    有什么建议?

    谢谢!

    最佳答案

    您提出了一个非常困难的要求组合。

    让我们来看看您的解决方案构想:

    Possible suggested ideas include:

    • Some way to reconfigure createPipe() that results in a seekable pipe

    • Some way to use a socket-based FileDescriptor that results in a seekable pipe

    • Some kind of RAM disk or something else that feels like a file to the rest of Android but is not persistent



    第一个不起作用。这个问题是由OS实现的管道基元从根本上是不可寻求的。原因是支持寻求,这将要求OS缓冲整个管道的“内容” ...直到读取端关闭。这是无法实现的……除非您对可通过管道发送的数据量进行限制。

    出于几乎相同的原因,第二个也不起作用。操作系统级别的套接字不可搜索。

    在一个层面上,最终构想(RAM文件系统)的工作与Android OS支持这种功能的模数有关。 (毕竟,可以找到Ramfs文件。)但是,文件流不是管道。特别是,对于文件流和管道,关于文件结尾的行为是不同的。从读者的角度来看,要使文件流看起来像管道流,将需要在那一侧添加一些特殊的代码。 (该问题类似于在日志文件上运行tail -f的问题...)

    不幸的是,我认为没有其他方法可以使文件描述符相对于文件末尾表现得像管道,并且也是可寻求的……根本不需要对操作系统进行根本性的修改。

    如果您可以更改从流中读取的应用程序,则可以解决此问题。事实是,fd需要由QuickOffice读取和查找(我假设您无法修改)的事实排除在外。 (但是,如果您可以更改应用程序,则有多种方法可以使这项工作...)

    顺便说一句,我认为您在Linux或Windows上的这些要求会有一些问题。而且它们不是特定于Java的。

    更新

    关于此有很多有趣的评论,我想在这里解决一些问题:
  • OP解释了激发他的问题的用例。基本上,他想要一种方案,其中在应用程序实际运行时,如果用户设备被盗(或没收),则通过应用程序之间“ channel ”传递的数据将不会受到攻击。

    那是可以实现的吗?
  • 从理论上讲,不是。如果人们假设高度的技术复杂性(以及公众可能不了解的技术……),那么“坏蛋”可能会闯入操作系统并从共享内存中读取数据,而“ channel ”仍处于 Activity 状态。
  • 我怀疑这种攻击在实践中(当前)是否可能。
  • 但是,即使我们假设“ channel ”未向“光盘”写入任何内容,在内存中仍可能存在该 channel 的痕迹:
  • 仍安装的RAMfs或仍处于 Activity 状态的共享内存段,或
  • 先前RAMfs/共享内存的
  • 残余。

  • 从理论上讲,只要“坏蛋”没有打开或重新启动设备,就可以从理论上检索此数据。
  • 建议在这种情况下使用 ashmem :
  • 可以解决没有公共(public)Java API的问题(例如,通过编写第三方API)
  • 真正的绊脚石是对流API的需求。根据“ashmem”文档,它们具有类似文件的API。但是我认为这仅意味着它们符合“文件描述符”模型。这些FD可以从一个应用程序传递到另一个应用程序(跨fork/exec),您可以使用“ioctl”对其进行操作。但是没有迹象表明它们实现了“读取”和“写入”……更不用说“寻找”了。
  • 现在,您可以在 channel 的两端使用 native 和Java库,在ashmem之上实现可读写的流。但是,两个应用程序都需要“意识到”该过程,可能要达到提供用于设置 channel 的命令行选项的级别。

  • 这些问题也适用于旧式的shmem ...,但是 channel 设置可能更困难。
  • 另一个可能的选择是使用RAM fs。
  • 这更容易实现。 RAMfs中的文件的行为类似于“普通”文件。当由应用程序打开时,您将获得一个文件描述符,该文件描述符可以被读取,写入和查找...,具体取决于其打开方式。并且(我认为)您应该能够在fork/exec上传递RAMfs文件的可搜索FD。
  • 问题是RAMfs需要由操作系统“挂载”以使用它。挂载时,另一个(特权)应用程序也可以打开和读取文件。当某些应用程序打开了RAMfs文件的fds时,操作系统将不允许您卸载RAMfs。
  • 有一个(假设的)方案可以部分缓解上述问题。
  • 源应用程序创建并挂载“私有(private)” RAMfs。
  • 源应用程序创建/打开文件以进行读取/写入,然后取消链接。
  • 源应用程序从头开始使用fd写入文件。
  • 源应用程序派生/执行接收器应用程序,并传递fd。
  • 接收器应用程序从(我认为)仍可搜索的fd中读取,并根据需要进行搜索。
  • 当源应用程序注意到(子)接收器应用程序进程已退出时,它将卸载并销毁RAMfs。

  • 这将不需要修改读取(接收器)应用程序。

    但是,第三个(特权)应用程序仍可能会进入RAMfs,在内存中找到未链接的文件,然后读取它。
    但是,在回顾了以上所有内容之后,最实用的解决方案仍然是修改读取(接收器)应用程序,以将整个输入流读取为byte[],然后在缓冲的数据上打开ByteArrayInputStream。核心应用程序可以随意查找和重置它。

    关于android - 通过Seekable Pipe或Stream与其他Android应用共享?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21538989/

    相关文章:

    android - 需要在fragment-android中显示布局

    android - 如何在 Android 中加入(字面意思)两个/多个内容提供商?

    java - 在 android Activity 中播放重复的 AudioTrack

    java - 如何从“设置” Activity 中的“主要 Activity ”访问方法?

    android - Jetpack Compose LazyColumnFor 已弃用,如何将 LazyColumn 与 listState 和对象列表一起使用?

    android - 使用 Chrome/默认 Internet 浏览器启动 Servie/Activity

    android - 我应该怎么做才能调用 Native Wallpaper picker 来为我在 android 中的布局设置墙纸?

    Android Share intent,保持在同一个Activity中

    java - 每个联系人都有一个电话号码的光标

    安卓内容提供商锁