Android学习记录044_监听Android截屏或者录屏

2023-11-05

一、源代码


package com.study.capturescreenlistener

import android.annotation.SuppressLint
import android.content.ContentResolver
import android.content.Context
import android.net.Uri
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import android.provider.MediaStore
import android.util.Log
import android.widget.Toast
import com.study.capturescreenlistener.contentobserver.UriObserver

/**
 * 判断是否被截屏或者录屏。
 * 因为Android并没有提供监听截屏或者录屏的api,但是可以知道的是不管截屏或者录屏生成的文件都会被保存到手机中,
 * 一般保存的文件夹命名如下KEYWORDS所示,所以可以通过监听相关的URI的的内容,从而达到监听截屏或者录屏的问题。
 * 添加一个内容观察者就好了,录制屏或者截图都会调用这个。
 * 如果添加两个内容观察者的话change方法将会被调用两次
 */
@SuppressLint("StaticFieldLeak")
object CaptureScreenUtils : UriObserver.UriChangeListener {

    private var contentResolver: ContentResolver? = null
//    private var videoObserver: UriObserver
    private var imageObserver: UriObserver
    private var mainHandler:Handler


    private var context: Context? = null
    private val KEYWORDS = arrayOf(
        "screenshot",
        "screen_shot",
        "screen-shot",
        "screen shot",
        "screencapture",
        "screen_capture",
        "screen-capture",
        "screen capture",
        "screencap",
        "screen_cap",
        "screen-cap",
        "screen cap"
    )
    private val screenPicture = mutableSetOf<String>()

    init {
        val handlerThread = HandlerThread("uriobserver")
        handlerThread.start()
        val handler = Handler(handlerThread.looper)
        mainHandler = Handler(Looper.getMainLooper())

//        videoObserver = UriObserver(handler)
//        videoObserver.setOnUriChangeListener(this)

        imageObserver = UriObserver(handler)
        imageObserver.setOnUriChangeListener(this)
    }


    override fun change(selfChange: Boolean, uri: Uri) {
        contentResolver?.let { it ->

            it.query(
                uri,
                null,
                null,
                null,
                MediaStore.Images.ImageColumns.DATE_ADDED + " desc limit 1"
            )?.takeIf { cursor ->
                cursor.moveToFirst()
            }?.use { cursor ->
                var path = ""
                var dateAdd = ""
                var relativePath = ""
                var type = ""
                val uriPath = uri.path?.toLowerCase() ?: ""
                Log.e(javaClass.simpleName, "uriPath=====$uriPath,  uri=====$uri")

                when {
                    uriPath.contains("video") -> { //录屏
                        type = "video"
                        val dataIndex = cursor.getColumnIndex(MediaStore.Video.VideoColumns.DATA)
                        path = cursor.getString(dataIndex).toLowerCase()

                        val relativePathIndex =
                            cursor.getColumnIndex(MediaStore.Images.ImageColumns.RELATIVE_PATH)
                        relativePath = cursor.getString(relativePathIndex)

                        val dateAddIndex =
                            cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATE_ADDED)
                        dateAdd = cursor.getString(dateAddIndex)
                    }
                    uriPath.contains("images") -> {//截屏
                        type = "images"
                        val dataIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA)
                        path = cursor.getString(dataIndex).toLowerCase()

                        val relativePathIndex =
                            cursor.getColumnIndex(MediaStore.Images.ImageColumns.RELATIVE_PATH)
                        relativePath = cursor.getString(relativePathIndex)

                        val dateAddIndex =
                            cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATE_ADDED)
                        dateAdd = cursor.getString(dateAddIndex)
                    }
                    else -> type = "未知"
                }

                Log.e(javaClass.simpleName, "type=====$type,  data=====$path,  uri=====$uri")
                Log.e(
                    javaClass.simpleName,
                    "type=====$type,  relativePath=====$relativePath,  uri=====$uri"
                )
                Log.e(javaClass.simpleName, "type=====$type,  dateAdd=====$dateAdd,  uri=====$uri")

                for (keyword in KEYWORDS) {
                    if (path.contains(keyword)) {
                        //还在子线程中,在这里处理发现被录屏或者截屏的逻辑
                        mainHandler.post { Toast.makeText(context,"当前被截屏了",Toast.LENGTH_SHORT).show() }
                        break
                    }
                }
            } ?: Toast.makeText(this.context, "数据为空", Toast.LENGTH_SHORT).show()
        }
    }

    fun register(context: Context) {
        this.context = context
        val contentResolver = context.contentResolver
        contentResolver?.let { contentResolver ->
            this.contentResolver = contentResolver
//            contentResolver.registerContentObserver(
//                MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
//                false,
//                videoObserver
//            )
            contentResolver.registerContentObserver(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                false,
                imageObserver
            )

        }
    }

    fun unregister() {
        contentResolver?.let {
//            it.unregisterContentObserver(videoObserver)
            it.unregisterContentObserver(imageObserver)
        }
        contentResolver = null
        context = null
    }
}

源码地址

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android学习记录044_监听Android截屏或者录屏 的相关文章

随机推荐

  • qt之槽函数的lambda写法

    文章目录 1 函数对象参数 2 操作符重载函数参数 3 可修改标示符 4 错误抛出标示符 5 函数返回值 6 函数体 一共包含六个部分 部分可以省略 1 函数对象参数 标识一个Lambda的开始 这部分必须存在 不能省略 函数对象参数是传递
  • 详细讲解C语言4(C语言系列)

    目录 前言 猜数字游戏 练习题 结束语 前言 在上一次博客中小编讲解了分支语句中的一些小习题 接下来小编带大家一起玩一个猜数字的小游戏 以及再和大家分享一些练习题 猜数字游戏 写一个猜数字游戏要求 1 自动产生1 100之间的随机数 2 猜
  • 【LeetCode】145.二叉树的后序遍历 - 使用迭代方式完成

    题目链接 LeetCode 145 二叉树的后序遍历 题目描述 给你一棵二叉树的根节点 root 返回其节点值的后序遍历 树中节点的数目在范围 0 100 0 100
  • 在maven中引入达梦包

    将达梦包install进maven仓库 可以 在idea运行中的工程中 terminal执行命令 Dfile 是jar包目录 尽量使用英文目录 DgroupId com dm DartifactId test Dversion 1 0 0
  • vue引用vant的弹出框Dialog

    1 消息提示 如下图 分两种弹框显示 点按钮 确认 提示弹出框 修改确认为圆角按钮风格 点按钮 确认 取消 提示弹出框
  • 挺起胸膛站下去

    试题内容 阅读下面的材料 根据要求写作 60分 好的故事 可以帮我们更好地表达和沟通 可以触动心灵 启迪智慧 好的故事 可以改变一个人的命运 可以展现一个民族的形象 故事是有力量的 以上材料引发了你怎样的联想和思考 请写一篇文章 要求 选准
  • 计算机电脑中了勒索病毒怎么办,Windows系统中了faust勒索病毒解密数据恢复

    电脑的操作系统被恶意软件攻击已不再是新鲜的话题了 而攻击的恶意软件中有一种叫做faust勒索病毒 常常袭击Windows电脑系统 如果我们的电脑在使用Windows操作系统时感染了faust勒索软件 请不要慌张 我们可以咨询专业的数据恢复厂
  • ECharts3使用入门

    最近项目中有用到百度ECharts 目前版本已经到3了 很多人说百度的这个东西是他最有良心的产品 用起来要比国外的插件简单点 这里主要讲一些简单的应用 算是简单的入门级别的 如果要是想更加的深入可以去看看范例 1 前期准备 1 相较于以前好
  • unix网络编程卷一:第四章——基本TCP套接口编程

    基本TCP套接口编程 4 1 过程 4 2 socket include
  • 数据挖掘分析概述

    目录 什么是数据挖掘分析 数据挖掘能够干什么 描述 评估 预测 分类 聚类 关联 数据挖掘的一般流程 业务理解阶段 数据理解阶段 数据准备阶段 建模阶段 评估阶段 部署阶段 什么是数据挖掘分析 数据挖掘是指从大量的数据中通过算法搜索隐藏于其
  • 关于在IDEA和jar包下MD5加密不一致问题

    关于在IDEA和jar包下MD5加密不一致问题 服务端 java 移动端 安卓 苹果 问题 MD5加密中文 在jar包下和idea下加密结果不一致问题 描述 移动端和服务端数据传输数据需要加解密 其中用到了AES RSA MD5 IDEA编
  • mysql导出表结构到excel

    1 执行如下sql 查询出想要的表信息 select c table name as 表名 t TABLE COMMENT as 表名描述 c column name as 字段名称 c column type as 数据类型 c COLU
  • vuecli2.0完成多页面应用中遇到的问题

    1 ECHO off SETLOCAL CALL find dp0 IF EXIST dp0 node exe SET prog dp0 node exe max old space size 4096 ELSE SET prog node
  • 拳王公社:知识付费项目!个体操作可年入千万!简单可复制!

    昨天 拳王分享了一篇 小白零基础靠副业年赚30W玩法 看懂一半至少年赚10W 揭秘了一个由个体思维转变到平台思维的网创人是怎么练就的 今天 我们分享的是 知识付费项目 个体操作可年入千万 简单可复制 这是在互联网上的一个纯粹的好项目 顺应互
  • 微服务可观测平台设计-总体设计

    背景 服务可观测性 预测与发现系统性能瓶颈 透视系统状态 为系统调优和查故障提供可靠数据支撑 参考和关键词 参考资料 https www cnblogs com erda p 15204516 html Metrics Metrics 计算
  • 嵌入式之fastboot的初步学习笔记

    注 如下内容参考朱老师物联网大讲堂课件 1 什么是fastboot 1 fastboot是android使用的一种刷机方法 android系统设计了2种刷机方式 fastboot和recovery fastboot是一种线刷 就是使用USB
  • 免费生成ios证书,利用Hbuilder打包ipa

    虽然xcode现在可以免证书进行测试了 但众多跨平台开发者 如果还没注册苹果开发者账号 想安装到自己非越狱手机测试是无能为力了 不过新技术来了 只需要普通免费的苹果账号无需付费成为开发者就可以申请ios证书打包ipa安装到自己手机测试 强大
  • Java猜数小游戏

    用java实现猜数1 99 package Random import java util Random import java util Scanner public class numgame public static void ma
  • qt for android程序调用腾讯接口实现短信验证功能

    为实现保留用户信息 手机号码 的功能 采用了短信验证的方式 选择了讯云短信平台 通过调用他的接口实现 之前使用过js java本地调用的方式因为各种原因均未完全实现 在客户端本地也可以实现 自己慢慢研究吧 现在采用新的思路如下 1 在公网服
  • Android学习记录044_监听Android截屏或者录屏

    一 源代码 package com study capturescreenlistener import android annotation SuppressLint import android content ContentResol