您的位置:首页 > 移动开发 > Android开发

监听Android系统截屏

2016-08-01 14:02 381 查看
公司的项目由于安全需要,对某一特定的页面需要监听是否被用户截屏了。

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

目前想到三种思路:

1、监听广播

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

2、监听按键

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

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

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

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

[java] view plain copy







public class ScreenshotContentObserver extends ContentObserver {

private Context mContext;

private int imageNum;

private static ScreenshotContentObserver instance;

private ScreenshotContentObserver(Context context) {

super(null);

mContext = context;

}

public static void startObserve() {

if (instance == null) {

instance = new ScreenshotContentObserver(Facade.context());

}

instance.register();

}

public static void stopObserve() {

instance.unregister();

}

private void register() {

mContext.getContentResolver().registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, false, this);

}

private void unregister() {

mContext.getContentResolver().unregisterContentObserver(this);

}

@Override

public void onChange(boolean selfChange) {

super.onChange(selfChange);

String[] columns = {

MediaStore.MediaColumns.DATE_ADDED,

MediaStore.MediaColumns.DATA,

};

Cursor cursor = null;

try {

cursor = mContext.getContentResolver().query(

MediaStore.Images.Media.EXTERNAL_CONTENT_URI,

columns,

null,

null,

MediaStore.MediaColumns.DATE_MODIFIED + " desc");

if (cursor == null) {

return;

}

int count = cursor.getCount();

if (imageNum == 0) {

imageNum = count;

} else if (imageNum >= count) {

return;

}

imageNum = count;

if (cursor.moveToFirst()) {

String filePath = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DATA));

long addTime = cursor.getLong(cursor.getColumnIndex(MediaStore.MediaColumns.DATE_ADDED));

if (matchAddTime(addTime) && matchPath(filePath) && matchSize(filePath)) {

doReport(filePath);

}

}

} catch (Exception e) {

e.printStackTrace();

} finally {

if (cursor != null) {

try {

cursor.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

/**

* 添加时间与当前时间不超过1.5s,大部分时候不超过1s。

*

* @param addTime 图片添加时间,单位:秒

*/

private boolean matchAddTime(long addTime) {

return System.currentTimeMillis() - addTime * 1000 < 1500;

}

/**

* 尺寸不大于屏幕尺寸(发现360奇酷手机可以对截屏进行裁剪)

*/

private boolean matchSize(String filePath) {

Point size = Util.getScreenWidthAndHeight(mContext);//获取屏幕尺寸

BitmapFactory.Options options = new BitmapFactory.Options();

options.inJustDecodeBounds = true;

BitmapFactory.decodeFile(filePath, options);

return size.x >= options.outWidth && size.y >= options.outHeight;

}

/**

* 已调查的手机截屏图片的路径中带有screenshot

*/

private boolean matchPath(String filePath) {

String lower = filePath.toLowerCase();

return lower.contains("screenshot");

}

private void doReport(String filePath) {

//删除截屏

File file = new File(filePath);

file.delete();

//TODO:

}

}

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

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

创建时间:大多时候,截屏图片的创建时间和当前系统时间不超过1000ms

图片尺寸:大多数手机截屏之后,直接保存图片,所以尺寸和屏幕尺寸一致。但有些手机,比如360奇酷手机,截屏后允许用户裁剪。所以图片尺寸的判断放宽到不大于屏幕尺寸

图片路径:目前,大多数手机的截屏路径中包含“screenshot”,还未发现例外

匹配成功后,就可以在doReport中做自己想做的事了~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: