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

时间:2012-09-17 15:57:19

标签: android android-ui

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

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

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

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

    Check Android Permissions - Protection Levels

  3. 尝试使用屏幕截图UX试用版后,我读取了权限:

    • INTERNET:用于连接roothost电话的localhost屏幕服务器。
    • SYSTEM_ALERT_WINDOW:用于最顶层的相机按钮。
    • VIBRATE:用于振动反馈。
    • WRITE_EXTERNAL_STORAGE:保存屏幕截图。
    • GET_TASKS:用于检测非根和非预加载捕获方法的前景开发设置活动。

    似乎SYSTEM_ALERT_WINDOWGET_TASKS允许该应用截取屏幕截图。 我有两个猜测它是如何工作的:

    1. 它可能能够访问前景活动的Activity,它获取Activity的根视图,捕获其屏幕截图。
    2. 致电glreadpixels
    3. 如果您尝试我的猜测,请告诉我结果。

3 个答案:

答案 0 :(得分:106)

这非常困难。我花了几年时间试图去做。我最终成功了,但任何解决方案都涉及商业和技术方面的努力。


2015年3月更新

以下大多数内容不再是最新的。经过这么多年,现在已经有了android.media.projection个包裹 https://developer.android.com/reference/android/media/projection/package-summary.html 最终允许你需要的东西!


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

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

当您在后台

时捕获另一个应用程序的屏幕

使用READ_FRAMEBUFFER权限

首先,您是正确的,正常的应用程序无法使用READ_FRAMEBUFFER权限,因为它是"签名" -level。这意味着您必须使用与Android系统ROM相同的密钥进行签名才能获取此类屏幕截图。

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

  嗯,不。绝对肯定不是。

那么,那就顺利了!因此,此权限仍然是signature - 到今天为止。

但是,如果您拥有此权限,则可以致电captureScreen 2ISurfaceComposer成员。您需要使用Android NDK以及一些未记录的API来编写一些本机代码来访问此功能。但是,这是可能的。

在Android图形子系统内部,它使用glReadPixels调用将GPU中的像素检索回CPU。 (GPU用于Android上的大部分合成。事实上,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上下文。它由地面抛弃物拥有。

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

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

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

使用硬件合作伙伴

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

与Android芯片组制造商交谈时经常提出解决方案。由于他们设计了硬件,因此他们可以访问帧缓冲区 - 而且他们通常只需直接访问自定义内核驱动程序就可以提供完全避免Android权限模型的库。

如果你的目标是特定的手机型号,这往往是一个很好的方法。当然,您可能需要与手机制造商以及硅制造商合作。

有时,这可以提供杰出的结果。例如,我听说可以在某些硬件上将电话硬件帧缓冲器直接传输到手机硬件H.264视频编码器中,并检索电话屏幕上任何内容的预编码视频流。优秀。 (不幸的是,我只是知道这可能在TI OMAP芯片上逐渐退出电话市场3。)

使用安全漏洞

Android严格执行其权限模型,并且安全漏洞很少。然而,Android OEM有时会更粗心。

例如,名称以S开头的主要OEM已实现了使用击键捕获屏幕的方法。它将其保存到SD卡上的世界可读文件中。假设您可以找到截取这些键的内容并查看其工作原理。也许你可以做类似的事情。

也许还有另一种主要OEM的方式,其名称也以S开头。

不,我不打算详细介绍这一部分。要弄清楚如何做这些事情,我需要有逆向工程软件,这可能是非法的。祝你好运。

与手机制造商合作

如前所述,手机制造商可以随时访问可行的API 。手机制造商需要signature级权限。

因此,您需要做的就是安排手机制造商签署您的软件。

然而,这是 hard 。通过签署软件,手机制造商保证其质量 - 因此他们应该想要审核您的源代码。此外,由于Android的性质 - 如果他们签署软件,他们需要是分发它的人。如果由其他人签名,您就无法将其投放市场。

然而,OEM不需要将其包含在ROM中 - 他们仍然可以在Android市场上分发它。但你不能。

一个好的解决方案是,如果每个供应商签署了一个小型库,然后可以通过通用SDK访问。这引导我进入......

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

我对此非常了解,因为我曾经在RealVNC工作过。我们与所有主要的Android手机供应商合作,以访问这些签名级API。我不能过分强调实现这一目标所需的许多工作量(商业和技术上)。一些OEM公布了这项工作 - 例如4

不再在RealVNC上工作,所以我在宣传他们的软件时没有任何好处。但是,如果您真的希望能够在多个Android设备上捕获屏幕,您可能希望与他们联系以重新使用他们的远程控制服务或Android VNC SDK 5。它不是开源的,所以你应该期望支付,并且相信我这是公平的,因为与所有这些Android OEM合作的史诗努力。

为了平衡,我应该指出其他供应商也与手机制造商合作 - 例如技工机构。但我相信它们都提供特定的设备管理解决方案,而不是通用的远程控制/事件注入SDK。

通过USB

另一个选项 - 通过USB侦听调试连接的adb守护程序具有比普通应用程序更多的权限,这就是它能够抓取屏幕的原因(您可以使用ddms工具)。如果您能够使用adb运行任何命令,那么您也可以获得这些权限(根据之前链接的android-screenshot-library)。

参与Android开源项目

最终这个问题让我陷入了灰尘,我离开了更加绿色的牧场,并没有试图从Android手机中挤出像素。

在我离开RealVNC之前,我们再次尝试将这些API贡献给Android开源项目。这次我们得到了更积极的反应6。简而言之,有人建议我们的安全方法几乎是正确的,但图形系统处于太大的混乱状态才能接受我们的补丁。嗯,好消息是图形系统不再处于动荡之中 - 事实上它现在有captureScreen API,这意味着不需要任何图形系统更改。因此,可以围绕此API向AOSP提交新的安全机制,最终解决了这个问题。

祝你好运!

答案 1 :(得分:3)

也许android-screenshot-library可以提供帮助。但是在他们的用法页面中,它说它需要一个以adb开头的本机服务(来自android sdk)。

PS:请记住,屏幕截图用户体验不适用于每个无根电话。

答案 2 :(得分:-1)

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

如果您确实需要获取任何应用的屏幕截图,我建议使用原生屏幕抓取“手势”。例如,对于Nexus 7,只需“......同时按住电源按钮和音量降低按钮约2秒钟。”

Google搜索通常会找到您设备的技巧。