如何在没有root权限的情况下以编程方式截取其他应用的截图,如Screenshot UX Trial?

如何在没有root权限的情况下以编程方式截取其他应用的截图,如Screenshot UX Trial?

  1. 我知道我可以在我的应用程序中捕获根视图的位图。 但是当我的应用程序在后台运行时,我无法获得其他应用程序的根视图

    bitmap = Bitmap.createBitmap(rootview.getDrawingCache());

  2. 在Manifest中有捕获当前帧缓冲区的权限: android.permission.READ_FRAME_BUFFER 。 但是有些网站说它只是用于签名应用程序。

    检查Android权限 – 保护级别

在尝试Screenshot UX Trial之后,我读取了权限:

  • 互联网:用于连接到本地电话的本地屏幕截图服务器。
  • SYSTEM_ALERT_WINDOW:最顶端的相机button。
  • 振动:振动反馈。
  • WRITE_EXTERNAL_STORAGE:保存屏幕截图。
  • GET_TASKS:用于检测前景非根和非预加载捕获方法的开发设置活动。

看来SYSTEM_ALERT_WINDOWGET_TASKS允许应用程序截图。 我有两个猜测它是如何工作的:

  1. 它可能能够访问前台活动的Activity ,它获取Activity的根视图,捕获其截图。
  2. 调用glreadpixels

如果你尝试了我的一个猜测,请让我知道结果。

这是非常困难的。 我花了好几年的时间去尝试。 我最终成功了,但任何解决scheme都将涉及商业和技术上的努力。


2015年3月更新

大部分下面的东西不再是最新的。 现在,毕竟这些年来,一个android.media.projectionhttps://developer.android.com/reference/android/media/projection/package-summary.html它最终允许你所需要的!;


捕获您自己的应用程序的屏幕图像

为了完整性,我想包括你自己的评论,你可以使用Bitmap.createBitmap(rootview.getDrawingCache());捕获自己的应用程序的图像Bitmap.createBitmap(rootview.getDrawingCache()); 和类似的机制。

在后台捕获另一个应用程序的屏幕

使用READ_FRAMEBUFFER权限

首先,你是正确的,一个正常的应用程序不能使用READ_FRAMEBUFFER权限,因为它是“签名”级别。 这意味着您必须使用与Android系统ROM相同的密钥进行签名才能获得此类屏幕截图。

我觉得这有点难过,所以早在2009年,我就提出了一个Android开放源代码项目提案,要求将其开放1 。 Android架构师Dianne Hackborn的回应是:

不。 绝对肯定不是。

那么,那就很好,那么! 因此,这个许可至今仍是signature级别的。

但是,如果您有此权限,则可以调用ISurfaceComposer 2的captureScreen成员。 你需要编写一些本地代码来访问这个函数,使用Android NDK以及一些未公开的API。 但是,这是可能的。

在Androidgraphics子系统内部,这使用glReadPixels调用将GPU中的像素检索回CPU。 (GPU用于Android上的大部分合成,实际上Android 4.0+支持额外的硬件合成器,Surface Flinger必须做更多的工作才能将这些像素拉回CPU。

这个调用的效果很好,除了一些小问题:

  • 使用不受支持的API的风险可能随时破坏;
  • 在C ++中调用它的麻烦
  • 它会导致GPUpipe线失速,这可能会使GPUdevise者感到不适,但实际上并不会造成问题
  • 它依靠GPU的大带宽返回到CPU。 这有时是有问题的,因为内存架构被devise为以相反的方向发送数据。 然而,我似乎记得所有现代Android芯片组架构直接共享GPU和CPU之间的内存,除了一个(可能是Broadcom? – 我不记得),这可能会导致这种机制非常缓慢。

…还有一个大问题

  • 最重要的是,作为一个普通的应用程序编写器,由于所需的签名级权限,您甚至无法调用此API。

不过,在大多数Android设备上,每秒钟可以获得10帧。 更好的是,这个API实际上支持在GPU上以硬件方式缩放产生的图像,所以如果你聪明的话,可以在像素甚至碰到CPU之前,将图像缩放到你需要的大小。 所以它可以是非常高的性能。

注意,当然,作为一个应用程序编写器的你不能调用glReadPixels因为你没有权限访问相关的OpenGL上下文。 它由表面抛掷物拥有。

使用/dev/graphics/fb0和类似的

有些人试图去读这些代表帧缓冲区的Linux设备文件。 但是,有三个问题:

  • 你需要root。
  • 有时他们甚至不在那里。
  • 通常,它们不代表真实的屏幕图像。 在Android上记住,graphics是在GPU上合成的。 所以没有理由为什么CPU应该可以访问完整的合成屏幕图像的副本,而且通常不会。 该文件有时包含撕裂(最好)和垃圾图像(最坏的情况下)。 有趣的是,一些根植电话的工具确实使用了这种方法,我认为这是一个错误。 如果你有root权限,你可以定义所有的Android权限,因此可以调用上面的captureScreen API来获取正确的图像。

使用硬件合作伙伴

现在我们进入需要商业行动的解决scheme。

与Android芯片制造商交谈通常会提供一个解决scheme。 由于他们devise硬件,所以他们可以访问framebuffer,而且他们通常可以通过直接访问自定义的内核驱动来提供完全避免Android权限模式的库。

如果您正在瞄准特定的手机型号,这往往是一个很好的前进方向。 当然,有可能你需要与手机制造商以及芯片制造商合作。

有时这可以提供出色的结果。 例如,我听说在某些硬件上可能会将手机硬件帧缓冲区直接放入手机硬件H.264video编码器,并检索手机屏幕上任何预编码的videostream。 优秀。 (不幸的是,我只知道 TI OMAP芯片上有这种可能,这些芯片正逐渐从手机市场退出3 )。

使用安全漏洞

Android严格执行其许可模式,并且几乎没有安全漏洞。 但是,Android OEMs有时可能更加粗心。

例如,一个名字以S开头的大型OEM已经实现了一种使用按键捕捉屏幕的方法。 它将其保存到SD卡上的世界可读文件中。 假设你可能能够find截取这些键的东西,看看它是如何工作的。 也许你可以做类似的事情。

也许还有另外一个主要的OEM的名字也以S开头

不,我不打算在这一节中详细介绍。 为了弄清楚如何做这些事情,我需要有反向工程软件,这可能是非法的。 祝你好运,但。

与手机制造商合作

如前所述,手机制造商已经准备好访问可以工作的API。 而手机制造商具有所需的signature级权限。

所以,你需要做的就是安排你的软件由电话制造商签名。

然而,这很难 。 通过签署软件,手机制造商正在保证其质量 – 所以他们应该想要审核你的源代码。 另外,由于Android的特性 – 如果他们签署了软件,他们需要成为分发它的人。 如果由他人签名签名,则不能将其投放市场。

但是,OEM不需要将其包含在ROM中 – 它们仍然可以在Android市场上发布。 但是你不能。

一个好的解决scheme是,如果每个供应商签署了一个小型库,然后可以通过一个共同的SDK访问。 这导致我…

与已经解决此问题的软件合作伙伴合作

我知道很多,因为我曾经在RealVNC工作。 我们与所有主要的Android手机供应商合作,以访问这些签名级的API。 为了实现这个目标,我不能过分强调许多人工(商业和技术上)的努力。 一些原始设备制造商已经公布了这项工作 – 例如4 。

不再在RealVNC上工作 ,所以我没有什么可以从他们的软件广告中获益。 但是,如果您确实希望能够捕获多个Android设备上的屏幕,则可能希望向他们提供关于重新使用Remote Control Service或Android VNC SDK 5的方法 。 这不是开源的,所以你应该期待付出,相信我这是公平的,考虑到与所有这些Android OEMs合作的史诗般的努力。

为了平衡,我应该指出其他供应商也与这个手机制造商合作 – 例如Soti。 但我相信他们都提供特定的设备pipe理解决scheme,而不是一般的遥控/事件注入SDK。

通过USB

另一个选项 – 监听通过USBdebugging连接的adb守护进程比正常的应用程序具有更多的权限,这就是为什么它能够抓取屏幕(你可以使用ddms工具看到它的图像)。 如果你能够使用adb运行任何命令,那么你也可以获得这些权限(根据之前链接的android-screenshot-library)。

贡献Android开源项目

最终,这个问题使我灰飞烟灭,而我离开了更加绿色的牧场,这并不涉及从Android手机中挤出像素。

虽然在离开RealVNC之前,我们再次尝试将这些API贡献给Android开放源代码项目。 这一次我们得到了更积极的反应6 。 简而言之,有人认为我们的安全方法几乎是正确的,但是graphics系统处于动荡之中,无法接受我们的补丁。 好消息是,graphics系统不再处于动荡之中 – 实际上现在已经有了captureScreen API,这意味着不需要任何graphics系统的改变。 因此,有可能围绕这个API向AOSP提交一个新的安全机制,最终解决这个问题。

祝你好运!

也许Android的屏幕截图库可以帮助。 但是在他们的用法页面中,它表示它需要一个以adb开头的本地服务(从android sdk开始)。

PS:请记住,截图UX不适用于每个无根电话。

我不认为Android会允许你访问另一个应用程序的帧缓冲区。 这只是Android安全性的一部分。 每个应用程序应该保持自己的资源。

如果你真的需要获取任何应用程序的屏幕截图,我会build议使用本机屏幕抓取“手势”。 以Nexus 7为例,只需“同时按住电源button和音量降低button约2秒”。

谷歌search通常会find你的设备的伎俩。