Android实现截屏功能(已适配Android11)

您所在的位置:网站首页 安卓手机截屏功能在哪里找出来 Android实现截屏功能(已适配Android11)

Android实现截屏功能(已适配Android11)

2024-07-16 17:58| 来源: 网络整理| 查看: 265

写在开头

为满足监听用户截屏并展示悬浮反馈入口的需求,对Android端的用户截屏功能进行了简单的调研。由于Android系统并没有提供截屏通知相关的API,所有需要我们自己利用系统能提供的相关特性变通实现。

通过学习,看到网上大概了提供了三种解决方案:

利用FileObserver监听某个目录中资源变化情况利用ContentObserver监听图片资源的变化监听截屏快捷按键 ( 由于厂商自定义Android系统的多样性,再加上快捷键的不同以及第三方应用,监听截屏快捷键这事基本不靠谱,可以直接忽略 )

这里我的实现是通过第二种方案解决,具体为什么不用1,3两种,下面的博客给了很好的解释,我不在累赘。 Android 截屏监听:如何实现截图分享功能? 但是实现方式略微不同,欢迎大家一起学习指正。

ScreenShotMaster 先给github地址,对于截屏思路有了解的同学可以直接看gitgub示例。

原理介绍

大家都知道,Android系统有一个媒体数据库,不管我们是相机拍摄的照片还是使用系统截屏截取的图片,系统都会把这张图片的详细信息加入到这个媒体数据库,并发出内容改变通知,所以我们可以利用内容观察者(ContentObserver)监听媒体数据库的变化,当数据库有变化时,获取最后插入的一条图片数据,如果该图片符合我们特定的规则,则认为被截屏了。

那么我们需要怎么做才能确定是截图呢?

监听截图的资源URI(MediaStore.Images.Media.EXTERNAL_CONTENT_URI)因为我们要读取图片内容,所以我们需要读取SD卡的权限,android.permission.READ_EXTERNAL_STORAGE并动态申请。获得图片信息后判断图片是否符合截图规则。 截图规则

网上绝大多数规则:

时间判断,图片的生成时间在开始监听之后, 并与当前时间相隔10秒内:开始监听后生成的图片才有意义,相隔10秒内说明是刚刚生成的。路径判断,图片路径符合包含特定的关键词:这一点是关键,截屏图片的保存路径通常包含“screenshot”等截图string。 实现主要步骤(具体请移步Github)

###注册图片监听者

fun registerContentObserver() { if (contentObserver == null) { contentObserver = ScreenShotApplication.applicationContext.contentResolver.registerObserver( MediaStore.Images.Media.EXTERNAL_CONTENT_URI ) { //监听到截图后 _dataChanged.value = true } } } /** * 利用ContentResolver监听照片数据的变化 */ fun ContentResolver.registerObserver( uri: Uri, observer: (selfChange: Boolean) -> Unit ): ContentObserver { val contentObserver = object : ContentObserver(Handler()) { override fun onChange(selfChange: Boolean) { observer(selfChange) } } registerContentObserver(uri, true, contentObserver) return contentObserver } 获取截图图片

因为适配Android11后,查询图片的SQL发生了变化,所以需要针对查询的方式有了一些改变,详见下面的代码和这个博客。

解析 Android 11 getContentResolver 获取多媒体图片

/* * 获取截图图片 */ fun getScreentShotImage(bucketId: String? = null) { Thread { try { var data: ScreentShotInfo? = null if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { //11 高版本获取图片信息 data = queryImagesP(bucketId) } else { //低版本获取图片信息 data = queryImages(bucketId) } val imagePath = data.path?.toLowerCase() screenShoot.forEach { if (imagePath?.contains(it)!! && (System.currentTimeMillis() / 1000 - data.addTime


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3