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

标签 android android-ui

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

  • 我知道我可以在我的应用程序中捕获根 View 的位图。但是当我的应用程序在后台运行时,我无法获得其他应用程序的根 View
    bitmap = Bitmap.createBitmap(rootview.getDrawingCache());
  • Manifest 中有捕获当前帧缓冲区的权限: android.permission.READ_FRAME_BUFFER 。但是有些网站说它仅适用于签名应用程序。

    Check Android Permissions - Protection Levels

  • 在尝试 Screenshot UX Trial 后,我阅读了权限:
  • INTERNET:用于连接到 localhost 屏幕截图服务器以获取 root 手机。
  • SYSTEM_ALERT_WINDOW:用于最顶部的相机按钮。
  • VIBRATE:用于振动反馈。
  • WRITE_EXTERNAL_STORAGE:保存截图。
  • GET_TASKS:用于检测非root和非预加载捕获方法的前景开发设置 Activity 。

  • 似乎 SYSTEM_ALERT_WINDOWGET_TASKS 允许应用程序截取屏幕截图。
    我有两个猜测它是如何工作的:
  • 或许可以访问前台 Activity 的Activity,获取Activity的根 View ,截图。
  • 调用 glreadpixels

  • 如果您尝试我的猜测之一,请告诉我结果。

    最佳答案

    这是极其困难的。我花了几年的时间试图做到这一点。我最终成功了,但任何解决方案都将涉及商业和技术方面的努力。

    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 相同的 key 签名才能截取此类屏幕截图。

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

    Um, no. Absolutely positively not.



    那么,一切顺利!因此,直到今天,此权限仍然是 signature 级别。

    但是,如果您拥有此权限,则可以调用 captureScreen 2ISurfaceComposer 成员。您需要使用 Android NDK 和一些未公开的 API 编写一些 native 代码来访问此功能。然而,这是可能的。

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

    除了一些小问题外,这个调用效果很好:
  • 使用不受支持的 API 的风险,该 API 可能随时中断;
  • C++调用的麻烦
  • 它会导致 GPU 流水线停滞,这会让 GPU 设计者感到不安,但实际上并不会真正引起问题
  • 它依赖于从GPU回到CPU的大带宽。这有时是有问题的,因为内存架构旨在以相反的方向发送数据。但是,我似乎记得所有现代 Android 芯片组架构都直接在 GPU 和 CPU 之间共享内存,除了一个(可能是博通? - 我不记得了)这可能会导致此机制非常慢。

  • ......还有一个大问题......
  • 最重要的是,作为一个普通的应用程序编写者,由于需要签名级别的权限,您甚至无法调用此API。

  • 尽管如此,在大多数 Android 设备上,您可以每秒获得 10 帧。更好的是,这个 API 实际上支持在 GPU 上的硬件中缩放生成的图像,所以如果你很聪明,你可以在像素到达 CPU 之前将图像预先缩放到你需要的大小。所以它可以是非常高性能的。

    请注意,当然,您作为应用程序编写者不能调用 glReadPixels,因为您无权访问相关的 OpenGL 上下文。它由表面抛油环拥有。

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

    有些人试图读取这些代表帧缓冲区的 Linux 设备文件。但是,存在三个问题:
  • 您需要root。
  • 有时它们甚至不存在。
  • 通常,它们不代表真实的屏幕图像。请记住,在 Android 上,图形是在 GPU 上合成的。因此,CPU 没有理由访问完整的合成屏幕图像的副本,而且通常不会。该文件有时包含撕裂(最好)和垃圾图像(最坏)。有趣的是,一些root手机的工具确实使用了这种方法,我认为这是一个错误。如果您有 root 用户,根据定义,您拥有所有 Android 权限,因此可以调用上面的 captureScreen API 来获取正确的图像。

  • 使用硬件合作伙伴

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

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

    如果您的目标是特定的手机型号,这通常是一个很好的前进方向。当然,您可能需要与手机制造商以及芯片制造商合作。

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

    使用安全漏洞

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

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

    也许还有一种方法可以让另一家名称也以 S 开头的主要 OEM 厂商。

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

    与手机制造商合作

    如前所述,手机制造商可以随时访问有效的 API。并且手机制造商拥有所需的 signature 级权限。

    因此,您需要做的就是安排让手机制造商对您的软件进行签名。

    然而,这很难。通过签署软件,手机制造商保证了它的质量——所以他们应该审核你的源代码。此外,由于 Android 的性质 - 如果他们签署软件,他们需要成为分发它的人。如果它是由其他人签名的,则您不能将其转换市场。

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

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

    与已经解决了这个问题的软件合作伙伴合作

    我对此非常了解,因为我曾经在 RealVNC 工作过。我们与所有主要的 Android 手机供应商合作,以访问这些签名级 API。为实现这一目标需要付出很多很多人年的努力(商业和技术上),我再怎么强调也不为过。一些 OEM 已经公布了这项工作——例如 4

    我不再在 RealVNC 工作,所以我从他们的软件广告中没有任何好处。但是,如果您真的希望能够在多个 Android 设备上捕获屏幕,您可能希望与他们联系以重新使用他们的远程控制服务或 Android VNC SDK 5 。它不是开源的,所以你应该期望付费,相信我,考虑到与所有这些 Android OEM 合作所付出的巨大努力,这已经足够公平了。

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

    通过 USB

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

    为 Android 开源项目做贡献

    最终,这个问题让我尘埃落定,我离开了更绿色的牧场,这不涉及试图从 Android 手机中挤出像素。

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

    祝你好运!

    关于android - 如何在没有 root 权限的情况下以编程方式截取其他应用程序的屏幕截图,例如 Screenshot UX Trial?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12462944/

    相关文章:

    安卓颜色,最快?

    java - 四个 Activity 不显示 Toast

    android - MonkeyRunner 中的西里尔文字

    android - 为什么这不会导致崩溃?我正在从其他线程更新 UI

    android - Android 中的圆表类型 UI?

    android - 在Android中录制并保存音频,其他应用程序不应访问该音频?

    android - 我可以在伴生对象中共享 ViewModel 吗?

    android - 样式 Android SearchView 下拉弹出窗口

    android - 在 ActionBar 中的选项卡下方添加行

    android - 有没有更快的方法来转储 UI 层次结构?