Android 截屏检测
最近项目中新接到一个需求,对手机截屏进行检测并进行后续操作,类似于Snapchat,iOS具有先天优势,因iOS系统提供了相关API!Google无果之后原作者决定再次造轮子,为了持续表达对Rx的敬意,命名为RxScreenshotDetector, github 源码地址 。
效果有图有真相

原理
安卓系统并没有提供任何截屏检测相关的API,网上针对Snapchat的这项功能进行了分析,大致猜测可能有以下几种途径:
使用FileObserver,监听Screenshots目录下的文件变化;
使用ContentObserver,监听MediaStore.Images.Media.EXTERNAL_CONTENT_URI资源的变化;
重载(hook)截屏组合键(不靠谱),有的机型使用的是特殊手势进行截屏;
主要参考了 StackOverflow上面的这个回答 。
核心代码如下:
private static final String TAG = "RxScreenshotDetector";
private static final String EXTERNAL_CONTENT_URI_MATCHER =
MediaStore.Images.Media.EXTERNAL_CONTENT_URI.toString();
private static final String[] PROJECTION = new String[] {
MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media.DATA,
MediaStore.Images.Media.DATE_ADDED
};
private static final String SORT_ORDER = MediaStore.Images.Media.DATE_ADDED + " DESC";
private static final long DEFAULT_DETECT_WINDOW_SECONDS = 10; final ContentResolver contentResolver = context.getContentResolver();
final ContentObserver contentObserver = new ContentObserver(null) {
@Override
public void onChange(boolean selfChange, Uri uri) {
Log.d(TAG, "onChange: " + selfChange + ", " + uri.toString());
if (uri.toString().matches(EXTERNAL_CONTENT_URI_MATCHER)) {
Cursor cursor = null;
try {
cursor = contentResolver.query(uri, PROJECTION, null, null,
SORT_ORDER);
if (cursor != null && cursor.moveToFirst()) {
String path = cursor.getString(
cursor.getColumnIndex(MediaStore.Images.Media.DATA));
long dateAdded = cursor.getLong(cursor.getColumnIndex(
MediaStore.Images.Media.DATE_ADDED));
long currentTime = System.currentTimeMillis() / 1000;
Log.d(TAG, "path: " + path + ", dateAdded: " + dateAdded +
", currentTime: " + currentTime);
if (path.toLowerCase().contains("screenshot") &&
Math.abs(currentTime - dateAdded) <=
DEFAULT_DETECT_WINDOW_SECONDS) {
// screenshot added!
}
}
} catch (Exception e) {
Log.d(TAG, "open cursor fail");
} finally {
if (cursor != null) {
cursor.close();
}
}
}
super.onChange(selfChange, uri);
}
};
contentResolver.registerContentObserver(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, contentObserver);
RxScreenshotDetector.java hosted with ❤ by GitHub
主要有以下几点需要注意:
权限,读取资源的时候需要READ_EXTERNAL_STORAGE权限,这里我使用了 RxPermissions 来以reactive的方式请求权限;
从ContentResolver查询资源的时候,需要按照资源创建时间降序排列,针对最新的一个资源判断是否为截屏的图片,为contentResolver.query的最后一个参数传递MediaStore.Images.Media.DATE_ADDED + " DESC"即可,而判断图片是否为截图则比较简单,路径包含screenshot关键字,且添加时间在10s之内;
使用示例
RxScreenshotDetector完整使用代码如下:
RxScreenshotDetector.start(getApplicationContext())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.compose(this.<String>bindUntilEvent(ActivityEvent.PAUSE))
.subscribe(new Subscriber<String>() {
@Override
public void onCompleted() { } @Override
public void onError(Throwable e) {
e.printStackTrace();
} @Override
public void onNext(String path) {
mTextView.setText(mTextView.getText() + "\nScreenshot: " + path);
}
});
这里使用了 RxLifecycle ,在Activity onPause之后unsubscribe,以保证不会发生内存泄漏。此外subscribe传入的是完整的Subscriber,是为了防止授权失败时没有onError处理器,导致crash。
Android 截屏检测的更多相关文章
- Android截屏的几种实现
Android截屏的几种实现 微信公众号:CodingAndroid CSDN:http://blog.csdn.net/xinpengfei521 最近我们的APP要求需要截屏功能,网上看了看大致有 ...
- 【转】Android截屏
http://blog.csdn.net/xww810319/article/details/17607749 Android截屏浅析 链接:http://blog.sina.com.cn/s/bl ...
- android截屏
截屏是一个常用的操作,经常会有这种需求. 截屏的工具类 package com.fxb.screenshot; import android.app.Activity; import android. ...
- Android 截屏与 WebView 长图分享经验总结
最近在做新业务需求的同时,我们在 Android 上遇到了一些之前没有碰到过的问题,截屏分享. WebView 生成长图以及长图在各个分享渠道分享时图片模糊甚至分享失败等问题,在这过程中踩了很多坑,到 ...
- Android 截屏的各种骚操作
本文公众号「AndroidTraveler」首发. 背景 在实际的应用场景中,Android 手机的截屏其实是很普遍的. 比如说 PPT 演示,比如说技术博客图文并茂讲解. 因此懂得 Android ...
- android截屏:保存一个view的内容为图片并存放到SD卡
项目中偶尔会用到截屏分享,于是就有了下面这个截屏的方法~ 下面得saveImage()方法就是保存当前Activity对应的屏幕所有内容的截屏保存. private void saveImage() ...
- 快速简化Android截屏工作
1.安装Notepad++v6.9 2.插件管理器里Plugin Manager安装AndroidLogger 3.AndroidLogger里的capture功能抓取Android的当前屏幕截图到w ...
- Android手机截屏
刚开始打算做一个简单的截屏程序时,以为很轻松就能搞定. 在Activity上放一个按钮,点击完成截屏操作,并将数据以图片形式保存在手机中. 动手之前,自然是看书和网上各种查资料.结果发现了解的知识越多 ...
- Android开发笔记:安卓程序截屏方法
1,基于Android SDK的截屏方法 (1)主要就是利用SDK提供的View.getDrawingCache()方法.网上已经有很多的实例了.首先创建一个android project,然后进行L ...
随机推荐
- Could not publish server configuration for Tomcat v6.0 Server at localhost.错误问题解决
经常在使用tomcat服务器的时候 总会发生一些莫名其妙的错误. 就像下面这个错误: 在配置文件中存在多个/MyWeb的配置,导致不能发布服务. 错误信息: Could not publish ser ...
- 软工作业-wc(Python实现)
GitHub地址:GitHub PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟) Planning 计划 30 40 · Esti ...
- InpOutx64 替代 winIOx64
/***************************************************************************** * InpOutx64 替代 winIOx ...
- Linux字符界面访问U盘
首先查看U盘所在位置 fdisk -l 只需查看最后分区情况,例如找到U盘的位置为:/dev/sda1(视系统而定) 创建文件夹(用于挂载U盘内容) mkdir /mnt/usb 挂载 mount / ...
- Ubuntu server 安装samba
安装Samba时,出现了一下问题: linux-image-generic***依赖出现问题,无法安装Samba. 使用apt-get update 更新,吓尿了,全部是忽略,源是系统自带的.改成其他 ...
- [leetcode]_Binary Tree Level Order Traversal I && II
题目:给定一棵二叉树,对其进行层次遍历,将遍历结果存入二维链表中. 思路:二叉树的层次遍历关键在于使用Queue. 复习: Queue的定义.LinkedList实现了Queue接口,因此可用Link ...
- 智能电视软件安装(WIFI上网)
智能电视软件上网(电视可连接无线网的称之为:智能电视) 1.安装当贝市场 链接:http://www.dangbei.com/ 2.安装电视家浏览器 链接:http://www.tvapk.net/f ...
- P2P技术基础: 关于TCP打洞技术
4 关于TCP打洞技术 建立穿越NAT设备的p2p的 TCP 连接只比UDP复杂一点点,TCP协议的“打洞”从协议层来看是与UDP的“打洞”过程非常相似的.尽管如此,基于TCP协议的打洞至今为止还没有 ...
- C# 程序部署、调试时间长的解决办法
最近在做数控折弯机项目时,VS2008环境下采用C#..NET Compact Framework开发WinCE.Windows Mobile程序时,编译项目非常慢,看着进度条慢慢刷,有时候需要几分钟 ...
- webpack新版本4.12应用九(配置文件之多种配置类型)
除了导出单个配置对象,还有一些方式满足其他需求. 导出为一个函数 最终,你会发现需要在开发和生产构建之间,消除 webpack.config.js 的差异.(至少)有两种选项: 作为导出一个配置对象的 ...