监听Android系统截屏

公司的项目由于安全需要,对某一特定的页面需要监听是否被用户截屏了。

简单搜了一下,很少有这方面的问题,没办法,只能自己折腾了。

目前想到三种思路:

1、监听广播

当然,前提是系统在截屏的时候发送某一广播,然而并没有。

2、监听按键

Android手机按下“电源键+音量减”会进行截屏,此外大部分手机状态栏下拉的页面中也会有截屏按钮。遗憾的是,监听这两处的操作并不是一件让人开心的事儿~~。

3、监听手机中图片的变化

开始只想到了MediaStore这个类,可以通过它拿到手机中的所有图片,每隔一段时间监听图片数量。这似乎是个不错的主意,直到我转角遇到了ContentObserver。

从名字就可以知道,它是一个内容观察者。通过给ContentProvider注册ContentObserver,可以实现对数据的监听。

[java] view plain copy

  1. public class ScreenshotContentObserver extends ContentObserver {
  2. private Context mContext;
  3. private int imageNum;
  4. private static ScreenshotContentObserver instance;
  5. private ScreenshotContentObserver(Context context) {
  6. super(null);
  7. mContext = context;
  8. }
  9. public static void startObserve() {
  10. if (instance == null) {
  11. instance = new ScreenshotContentObserver(Facade.context());
  12. }
  13. instance.register();
  14. }
  15. public static void stopObserve() {
  16. instance.unregister();
  17. }
  18. private void register() {
  19. mContext.getContentResolver().registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, false, this);
  20. }
  21. private void unregister() {
  22. mContext.getContentResolver().unregisterContentObserver(this);
  23. }
  24. @Override
  25. public void onChange(boolean selfChange) {
  26. super.onChange(selfChange);
  27. String[] columns = {
  28. MediaStore.MediaColumns.DATE_ADDED,
  29. MediaStore.MediaColumns.DATA,
  30. };
  31. Cursor cursor = null;
  32. try {
  33. cursor = mContext.getContentResolver().query(
  34. MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
  35. columns,
  36. null,
  37. null,
  38. MediaStore.MediaColumns.DATE_MODIFIED + " desc");
  39. if (cursor == null) {
  40. return;
  41. }
  42. int count = cursor.getCount();
  43. if (imageNum == 0) {
  44. imageNum = count;
  45. } else if (imageNum >= count) {
  46. return;
  47. }
  48. imageNum = count;
  49. if (cursor.moveToFirst()) {
  50. String filePath = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DATA));
  51. long addTime = cursor.getLong(cursor.getColumnIndex(MediaStore.MediaColumns.DATE_ADDED));
  52. if (matchAddTime(addTime) && matchPath(filePath) && matchSize(filePath)) {
  53. doReport(filePath);
  54. }
  55. }
  56. } catch (Exception e) {
  57. e.printStackTrace();
  58. } finally {
  59. if (cursor != null) {
  60. try {
  61. cursor.close();
  62. } catch (Exception e) {
  63. e.printStackTrace();
  64. }
  65. }
  66. }
  67. }
  68. /**
  69. * 添加时间与当前时间不超过1.5s,大部分时候不超过1s。
  70. *
  71. * @param addTime 图片添加时间,单位:秒
  72. */
  73. private boolean matchAddTime(long addTime) {
  74. return System.currentTimeMillis() - addTime * 1000 < 1500;
  75. }
  76. /**
  77. * 尺寸不大于屏幕尺寸(发现360奇酷手机可以对截屏进行裁剪)
  78. */
  79. private boolean matchSize(String filePath) {
  80. Point size = Util.getScreenWidthAndHeight(mContext);//获取屏幕尺寸
  81. BitmapFactory.Options options = new BitmapFactory.Options();
  82. options.inJustDecodeBounds = true;
  83. BitmapFactory.decodeFile(filePath, options);
  84. return size.x >= options.outWidth && size.y >= options.outHeight;
  85. }
  86. /**
  87. * 已调查的手机截屏图片的路径中带有screenshot
  88. */
  89. private boolean matchPath(String filePath) {
  90. String lower = filePath.toLowerCase();
  91. return lower.contains("screenshot");
  92. }
  93. private void doReport(String filePath) {
  94. //删除截屏
  95. File file = new File(filePath);
  96. file.delete();
  97. //TODO:
  98. }
  99. }

上面通过register()和unregister()两个静态方法进行监听器的注册和反注册。建议在onStart()方法中进行注册,在onStop()方法中进行反注册,因为截屏并不会引起当前页面生命周期的变化。

在onChange()回调方法中,通过查询,拿到最近添加的那张图片,从创建时间、尺寸、路径3个方面进行匹配,判断是否是截屏图片。

  • 创建时间:大多时候,截屏图片的创建时间和当前系统时间不超过1000ms
  • 图片尺寸:大多数手机截屏之后,直接保存图片,所以尺寸和屏幕尺寸一致。但有些手机,比如360奇酷手机,截屏后允许用户裁剪。所以图片尺寸的判断放宽到不大于屏幕尺寸
  • 图片路径:目前,大多数手机的截屏路径中包含“screenshot”,还未发现例外

匹配成功后,就可以在doReport中做自己想做的事了~~

时间: 2024-08-10 00:34:08

监听Android系统截屏的相关文章

Android系统截屏的实现(附代码)

1.背景 写博客快两年了,写了100+的文章,最火的文章也是大家最关注的就是如何实现android系统截屏.其实我们google android_screen_shot就会找到很对办法,但那些都是很多年前的了,在android4.*版本后,android对于源码进行了更正,使得以前的方法都不能够使用. 感谢cjd6568358这名网友,我们一起讨论,最终由他实现了android系统截屏功能,为了让以后想要这个功能的coder可以少走一些弯路,我们整理的代码做成开源项目. 2.思路 其实主要思路还

Android 系统截屏与系统内置DVR录像冲突,导致SystemUI重启的问题解决与分享

上周六加班在解决一个关于SystemUI内嵌的DVR录像与系统截屏操作冲突的问题,介于问题的复杂性,所以我把这个分享出来便 于以后自己更加的理解,又方便以后遇到此问题的同行能够提供一些帮助,若有疑问可向鄙人的博客提供你的宝贵意见! 首先我们需要找到系统截屏的按键定义,并且知道它在哪里执行的,先摈弃从硬件底层的协议,我们直接从framework层开始 讲,因为底层底层硬件返回的结果由.c.o.h这些文件,再由Binder aidl 将结果给到framework,所以我们就从开始从framework

Android系统截屏功能提取

Android在4.0版本之后同时按电源键和音量键可以截取当前屏幕,截图后会有一个过渡动画效果,这里提取了将效果这部分提取出来,可以用于应用截图分享功能. 截图功能在源码中的位置是com.android.systemui.screenshot,下面有四个类 其中主要工作都在GlobalScreenshot中,包括截图后的动画效果.保存到本地和显示到通知栏.为了简单,下面的代码只保留了过渡动画部分 class GlobalScreenshot { private static final Stri

监听Android CTS测试项解决方案(二)

二,监听当前测试项是否是Accelerometer Measurement Test测试项 通过第一种方式介绍的,我们可以得到当前处于活动状态的Activity类似监听CTS测试当前的测试项.但是由于是监听Android系统中所有Activity,因此会大大降低系统的性能,因此这里有一种效率更高的方式来精确定位当前CTS正在测试的测试项,而不会对系统造成很大的影响.(当然不能修改CTS源码,我们需要使用Android提供的原生CTS APK进行验证) 那么我们这里以Accelerometer M

Android 监听 Android中监听系统网络连接打开或者关闭的实现代码

本篇文章对Android中监听系统网络连接打开或者关闭的实现用实例进行了介绍.需要的朋友参考下 很简单,所以直接看代码 复制代码 代码如下: package xxx; import android.content.BroadcastReceiver;  import android.content.Context;  import android.content.Intent;  import android.net.ConnectivityManager;  import android.ne

Android 长截屏原理

https://android-notes.github.io/2016/12/03/android%E9%95%BF%E6%88%AA%E5%B1%8F%E5%8E%9F%E7%90%86/   android长截屏原理 小米系统自带的长截屏应该很多人都用过,效果不错.当长截屏时listview就会自动滚动,当按下停止截屏时,就会得到一张完整的截屏. 该篇就介绍一下长截屏的原理 上篇中介绍了android屏幕共享实现方式,该篇的原理和上一篇基本一致. 获取view影像 当我们想得到一个view

监听Android CTS测试项解决方案(一)

前言: 首先这里需要详细叙述一下标题中"监听Android CTS测试项解决方案"的需求.这里的需求是指我们需要精确的监听到当前CTS测试正在测试的测试项. 因为我们知道CTS认证是获得Google推出的 Android 系统中 Android Market 服务的前提.CTS 兼容性测试的主要目的和意义在于使得用户在 Android 系统的应用过程中,有更好的用户体验,并展现出 Android 系统的优越特性:使得 Android 应用程序编写者更容易编写高质量的应用程序:充分展现

Android长截屏-- ScrollView,ListView及RecyclerView截屏

http://blog.csdn.net/wbwjx/article/details/46674157       Android长截屏-- ScrollView,ListView及RecyclerView截屏 https://github.com/BoBoMEe/AndroidDev/blob/master/common/common/src/main/java/com/bobomee/android/common/util/ScreenUtil.java /* * Copyright (C)

Android自动截屏小脚本

Android自动截屏小脚本(脱离手工操作,自动保存到PC上) @echo offecho * 截图文件将保存在 E:\takeshont下,以当前日期+时间命名.echo =================================================echo * 如果在停止截图后,无法删除或者上传,可到任务管理器中删除adb.exe进程echo =================================================================