Android takeScreenshot API实战:CircleToSearch无权限截屏与HardwareBuffer解析
【免费下载链接】CircleToSearchCircleToSearch with multi search engine support for all android项目地址https://gitcode.com/gh_mirrors/ci/CircleToSearch点击查看免费下载CircleToSearch是一款面向所有 Android 设备的多引擎识图搜索应用Google、Bing、Yandex、TinEye。它的核心技术就是借助 Android 11API 30为无障碍服务提供的takeScreenshot API在不申请 MediaProjection、不弹系统授权对话框的情况下截取当前屏幕再对截屏结果中的 HardwareBuffer 进行包装与解析。本文将结合这个开源项目的源码完整拆解这条从无权限截屏到软件位图的链路。为什么选 takeScreenshot无权限截屏的关键Android 应用截屏传统上有两条路体验都不好方案痛点MediaProjection 虚拟屏每次使用都要弹是否允许录屏对话框且流程繁琐读系统截屏文件Android 10 存储隔离基本不可行而 Android 11 引入的AccessibilityService.takeScreenshot()让已开启的无障碍服务可以直接抓取指定 Display 的当前画面✅ 无需MediaProjection权限、无系统弹窗截屏零打断⚠️ 前提是用户手动开启无障碍服务这本身就是系统级授权且服务需声明canTakeScreenshottrue这也是 CircleToSearch 能在任意应用之上随手圈选搜索的底层能力——截屏必须发生在 Overlay 弹出之前否则截到的就是自己的界面。前置条件无障碍服务配置中开启截屏能力整个能力的第一块拼图在 accessibility_service_config.xml 中accessibility-service android:canRetrieveWindowContenttrue android:canPerformGesturestrue android:canTakeScreenshottrue ... /同时 AndroidManifest.xml 中服务需绑定BIND_ACCESSIBILITY_SERVICE权限。另外项目在onServiceConnected中还会叠加FLAG_RETRIEVE_INTERACTIVE_WINDOWS等标志见 CircleToSearchAccessibilityService.kt用于读取多窗口内容保证截屏与文本节点坐标对齐。takeScreenshot 实战从调用到回调核心实现在 performCapture()骨架如下if (Build.VERSION.SDK_INT Build.VERSION_CODES.R) { takeScreenshot( Display.DEFAULT_DISPLAY, // 目标显示 executor, // 回调执行的线程池 object : TakeScreenshotCallback { override fun onSuccess(screenshot: ScreenshotResult) { /* 处理 HardwareBuffer */ } override fun onFailure(errorCode: Int) { /* 记录错误码 */ } } ) }三个要点版本门槛是 API 30R低版本需走其他触发通道或降级回调在指定 Executor 上执行项目用单线程 Executor不是主线程后续拉起 Activity 前注意线程切换成功回调拿到的是ScreenshotResult它不直接给 Bitmap而是携带一块HardwareBufferColorSpace——这正是下一节要解析的部分。HardwareBuffer 解析wrapHardwareBuffer 与 ARGB_8888 拷贝ScreenshotResult.hardwareBuffer是 GPU 侧的显存块不能直接当普通 Bitmap 裁剪、读取像素。项目采用包装 → 拷贝 → 释放三步曲源码位置val hardwareBuffer screenshot.hardwareBuffer val colorSpace screenshot.colorSpace // ① 硬件包装得到一个 GPU 支撑的不可变Bitmap val bitmap Bitmap.wrapHardwareBuffer(hardwareBuffer, colorSpace) if (bitmap null) { hardwareBuffer.close() // 包装失败立即释放缓冲 return } // ② 拷贝为纯软件位图可裁剪、可逐像素访问 val copy bitmap.copy(Bitmap.Config.ARGB_8888, false) hardwareBuffer.close() // ③ 拷贝完成显式关闭 HardwareBuffer BitmapRepository.setScreenshot(copy) launchOverlay(searchModeOverride)为什么要传 ColorSpace高分辨率屏幕常使用广色域如 Display P3包装时带上原始 ColorSpace 可以避免颜色偏移。为什么要再 copy 一次wrapHardwareBuffer返回的 Bitmap 是硬件支撑的hardware-backed对它的读写受 GPU 限制且不可修改copy(ARGB_8888, false)生成纯 CPU 位图后后续的Bitmap.createBitmap()裁剪、OCR 像素读取才能正常工作。必须close()吗必须。HardwareBuffer实现了ExplicitCloseable忘记关闭会泄漏显存重复 close 也会抛异常——所以项目里包装失败与拷贝完成两条路径都显式调用了close()。内存级接力BitmapRepository 的无落盘设计截屏完成后位图并不通过 Intent 传递Bitmap 太大parceling 有 1MB 上下限风险而是存进一个内存单例 BitmapRepository.ktobject BitmapRepository { private var screenshot: Bitmap? null fun setScreenshot(bitmap: Bitmap?) { screenshot bitmap } fun getScreenshot(): Bitmap? screenshot fun clear() { screenshot null } }接力链非常简洁无障碍服务setScreenshot(copy)写入OverlayActivity.loadScreenshot() 启动后读取渲染出圈选界面关闭 Overlay 时BitmapRepository.clear()onDestroy 再做兜底清理。这个设计的隐私收益很直观截屏全程只在内存中流转从不落盘即使用户保存选区写入相册的也只是用户圈定的裁剪区域见 ImageUtils.kt 的cropBitmap。整体架构可参考官方文档 docs/image_search.md。多条触发路径一次截屏逻辑多种入口同一个performCapture()被多个入口复用用户按习惯选择即可⚡快速设置磁贴下拉通知栏点击 CTS 磁贴CircleToSearchTileService.kt️设为默认助手长按 Home 键触发此时系统直接回调onHandleScreenshot(Bitmap)截屏由系统完成AssistSessionService 只需存入 Repository 并拉起 Overlay状态栏双击 / 悬浮气泡由无障碍服务自行调用takeScreenshot多条路径最终都收敛到BitmapRepository → OverlayActivity这一条主干新增触发方式时几乎不用改动图像管线。踩坑清单4 个最容易翻车的地方忘记hardwareBuffer.close()—— 显存泄漏建议放在 finally 或两条分支都显式调用直接在硬件 Bitmap 上裁剪——wrapHardwareBuffer结果不可写、不可部分裁剪务必先copy(ARGB_8888, false)线程假设错误——TakeScreenshotCallback在 Executor 上回调不要默认它在主线程忽略onFailure—— 系统繁忙、多屏等场景可能失败至少记录errorCode并给用户提示。总结CircleToSearch 用不到 50 行代码演示了 takeScreenshot API 的完整范式声明canTakeScreenshot→ 回调取 HardwareBuffer →wrapHardwareBuffer包装 → 拷贝为 ARGB_8888 → 内存单例接力 → 用完即清。它证明了在 Android 上无权限、无打断的截屏能力并不需要任何灰色手段——只要你的应用场景符合无障碍服务的定位这是官方给的正经通道。如果你想在自己的无障碍类应用屏幕翻译、内容提取、辅助搜索等中实现类似能力这套链路可以直接照搬。赞分享【免费下载链接】CircleToSearchCircleToSearch with multi search engine support for all android项目地址https://gitcode.com/gh_mirrors/ci/CircleToSearch点击查看免费下载相关推荐揭秘Android截屏限制FLAG_SECURE深度解析与实战解决方案揭秘Android截屏限制FLAG_SECURE深度解析与实战解决方案 在Android生态系统中FLAG_SECURE安全标志如同无形的屏障影响着用户对移动开发DisableFlagSecure彻底解放Android截屏权限的终极工具DisableFlagSecure彻底解放Android截屏权限的终极工具 你是否曾遇到过这样的困扰想要保存银行应用的交易记录、记录游戏精彩瞬间或备份重要文移动开发Android FLAG_SECURE限制突破全面解锁截屏权限的终极方案Android FLAG_SECURE限制突破全面解锁截屏权限的终极方案 在移动应用安全防护体系中FLAG_SECURE标志作为Android系统的重要安全移动开发上一篇免费开源的GTA5线上小助手实测被NPC教做人之后我用十分钟接管了洛圣都下一篇Parler-TTS Mini使用指南用描述词精准控制语音性别、音高、语速与背景噪声创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考