This is extremely difficult. I spent several years trying to do it. I eventually succeeded, but any solution will involve commercial as well as technical effort.
2015 年 3 月更新
下面的大部分内容不再是最新的。这么多年过去了,现在有一个android.media.projection
包裹https://developer.android.com/reference/android/media/projection/package-summary.html这终于可以满足您的需求了!
捕获您自己的应用程序的屏幕图像
为了完整起见,我想添加您自己的评论,您可以使用以下命令捕获您自己的应用程序的图像Bitmap.createBitmap(rootview.getDrawingCache());
和类似的机制。
当您在后台时捕获另一个应用程序的屏幕
使用READ_FRAMEBUFFER
允许
首先,你是对的,普通应用程序无法使用READ_FRAMEBUFFER
许可,因为它是“签名”级别的。这意味着您必须使用与 Android 系统 ROM 相同的密钥进行签名才能进行此类屏幕截图。
我觉得这有点悲伤,所以早在 2009 年我就提交了一个 Android 开源项目,要求开放它1。 Android 架构师 Dianne Hackborn 的回应是:
不。绝对不是。
那么,一切顺利!因此这个权限仍然是signature
至今为止的水平。
但是,如果您有此权限,您可以致电captureScreen
成员ISurfaceComposer
2。您需要使用 Android NDK 以及一些未记录的 API 编写一些本机代码来访问此函数。然而,这是可能的。
在 Android 图形子系统内部,这使用了glReadPixels
调用将像素从 GPU 检索回 CPU。 (Android 上的大部分合成都使用 GPU。事实上,Android 4.0+ 支持额外的硬件合成器,Surface Flinger 必须做更多的工作才能将这些像素拉回 CPU。)
除了一些小问题之外,这个调用工作得很好:
- 使用不受支持的 API 的风险可能随时中断;
- 在C++中调用它的麻烦
- 它会导致 GPU 管道停顿,这可能会让 GPU 设计者感到不安,但实际上并不会造成问题
- 它依赖于 GPU 的大带宽back到CPU。这有时会产生问题,因为内存架构被设计为以相反的方向发送数据。然而,我似乎记得所有现代 Android 芯片组架构都直接在 GPU 和 CPU 之间共享内存,除了一个(可能是 Broadcom? - 我不记得了),这可能会导致该机制非常慢。
...还有一个大问题...
- 最重要的是,作为一个普通的应用程序编写者,由于需要签名级别的权限,您甚至无法调用此 API。
尽管如此,在大多数 Android 设备上,您仍可以获得每秒 10 帧的速度。更好的是,这个 API 实际上支持缩放结果图像在 GPU 上的硬件中,所以如果您足够聪明,您可以在像素到达 CPU 之前将图像预先缩放到您需要的大小。因此它可以具有极高的性能。
当然,请注意,作为应用程序编写者,您无法调用glReadPixels
因为您无权访问相关的 OpenGL 上下文。它属于表面抛掷器所有。
Using /dev/graphics/fb0
和类似的
有些人试图读取这些代表帧缓冲区的 Linux 设备文件。然而,存在三个问题:
- 你需要root。
- 有时他们甚至不在那里。
- 通常,它们并不代表真实的屏幕图像。请记住,在 Android 上,图形是在 GPU 上合成的。因此,CPU 没有理由有权访问完整合成屏幕图像的副本,而且通常也不能访问。该文件有时包含撕裂(最好的情况)和垃圾图像(最坏的情况)。有趣的是,一些针对root手机的工具确实使用了这种方法,我认为这是一个错误。如果你有root权限,那么根据定义你就拥有所有Android权限,因此可以调用上面的命令
captureScreen
用于获取正确图像的 API。
使用硬件合作伙伴
现在我们讨论需要商业行动的解决方案。
与 Android 芯片组制造商交谈通常会提出解决方案。由于他们设计了硬件,因此他们可以访问帧缓冲区 - 并且他们通常能够通过直接访问其自定义内核驱动程序来提供完全避免 Android 权限模型的库。
如果您的目标是特定的手机型号,这通常是一个很好的方法。当然,您很可能需要与手机制造商以及芯片制造商合作。
有时这可以提供杰出的结果。例如,我听说在某些硬件上可以将手机硬件帧缓冲区直接传输到手机硬件 H.264 视频编码器中,并检索手机屏幕上任何内容的预编码视频流。杰出的。 (不幸的是,我只know这在逐渐退出手机市场的 TI OMAP 芯片上是可能的3).
利用安全漏洞
Android 严格执行其权限模型,并且几乎没有安全漏洞。然而,Android OEM 厂商有时可能会比较粗心。
例如,一家名称以 S 开头的主要 OEM 已经实现了一种使用击键来捕获屏幕的方法。它将其保存到 SD 卡上的全球可读文件中。假设您也许能够找到拦截这些密钥的内容并了解其工作原理。也许你可以做类似的事情。
也许另一家名称也以 S 开头的主要 OEM 有办法。
不,我不会详细介绍本节。为了弄清楚如何做这些事情,我需要有逆向工程软件,这可能是非法的。不过祝你好运。
与手机制造商合作
如前所述,手机制造商可以随时访问 API,该 API确实有效。手机制造商有signature
需要-级权限。
因此,您所需要做的就是安排手机制造商对您的软件进行签名。
然而,这是hard。通过对软件进行签名,手机制造商可以保证其质量 - 因此他们应该审核您的源代码。此外,由于 Android 的性质 - 如果他们签署了该软件,他们就必须是分发该软件的人。如果它是由其他人签名的,则您不能将其放入市场。
然而,OEM 不需要将其包含在 ROM 中 - 他们仍然可以在 Android 市场上分发它。但你不能。
一个好的解决方案是每个供应商都签署一个小型库,然后可以通过通用 SDK 访问该库。这导致我...
与已经解决此问题的软件合作伙伴合作
我对这方面了解很多,因为我曾经在 RealVNC 工作过。我们与所有主要 Android 手机供应商合作,以访问这些签名级 API。我无法过分强调实现这一目标所需的许多、许多人年的努力(商业上和技术上)。一些 OEM 已经公开了这项工作 - 例如4.
I 不工作我不再在 RealVNC 工作了,所以我从广告他们的软件中得不到任何好处。但如果你真的真的希望能够在多个 Android 设备上捕获屏幕,您可能希望与他们联系以重新使用他们的远程控制服务或 Android VNC SDK5。它不是开源的,所以你应该期待付费,相信我,考虑到与所有这些 Android OEM 合作所付出的巨大努力,这是足够公平的。
为了平衡,我应该指出其他供应商也在这方面与手机制造商合作 - 例如索蒂。但我相信他们都提供特定的设备管理解决方案,而不是通用的远程控制/事件注入SDK。
Over USB
另一种选择 -adb
通过 USB 侦听调试连接的守护进程比普通应用程序具有稍多的权限,这就是它能够抓取屏幕的原因(您可以使用ddms
工具)。如果您能够使用以下命令运行任何命令adb
那么您也可以获得这些权限(根据之前链接的 android-screenshot-library)。
为Android开源项目做出贡献
最终这个问题让我灰飞烟灭,我离开了,不再尝试从 Android 手机中榨取像素。
不过,在我离开 RealVNC 之前,我们再次尝试将这些 API 贡献给 Android 开源项目。这次我们得到了更积极的反应6。简而言之,有人认为我们的安全方法几乎是正确的,但图形系统过于混乱而无法接受我们的补丁。好消息是图形系统不再陷入混乱 - 事实上它现在已经有了captureScreen
API 这意味着无需对图形系统进行任何更改。因此,有可能围绕这个 API 向 AOSP 提交一个新的安全机制,最终解决这个问题。