功能需求:
App内截屏监控功能,当发现用户在我们的app内进行了截屏操作时,进行对图片的二次操作,例如添加二维码,公司logo等一系列操作。
首先来app界面图及截屏监听图添加效果图
主要是利用内容观察者(ContentObserver)监听媒体数据库的变化,当数据库有变化时,获取最后插入的一条图片数据,如果该图片符合特定的规则,则认为被截屏了,下面看看截屏管理类
ScreenShotListenManager.java
package com.test.base;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Point;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import com.test.R;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* @CreateDate: 2020/9/17
* @Author:lp
* @Description:
*/
public class ScreenShotListenManager {
private static final String TAG = "ScreenShotListenManager";
/**
* 读取媒体数据库时需要读取的列
*/
private static final String[] MEDIA_PROJECTIONS = {
MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.DATE_ADDED
};
/**
* 读取媒体数据库时需要读取的列, 其中 WIDTH 和 HEIGHT 字段在 API 16 以后才有
*/
private static final String[] MEDIA_PROJECTIONS_API_16 = {
MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.DATE_ADDED,
MediaStore.Images.ImageColumns.WIDTH,
MediaStore.Images.ImageColumns.HEIGHT,
};
/**
* 截屏依据中的路径判断关键字
*/
private static final String[] KEYWORDS = {
"screenshot", "screen_shot", "screen-shot", "screen shot",
"screencapture", "screen_capture", "screen-capture", "screen capture",
"screencap", "screen_cap", "screen-cap", "screen cap", "Screenshots", "Screenshot"
};
private static Point sScreenRealSize;
/**
* 已回调过的路径
*/
private final static List<String> sHasCallbackPaths = new ArrayList<String>();
private Context mContext;
private OnScreenShotListener mListener;
private long mStartListenTime;
/**
* 内部存储器内容观察者
*/
private MediaContentObserver mInternalObserver;
/**
* 外部存储器内容观察者
*/
private MediaContentObserver mExternalObserver;
/**
* 运行在 UI 线程的 Handler, 用于运行监听器回调
*/
private final Handler mUiHandler = new Handler(Looper.getMainLooper());
private ScreenShotListenManager(Context context) {
if (context == null) {
throw new IllegalArgumentException("The context must not be null.");
}
mContext = context;
// 获取屏幕真实的分辨率
if (sScreenRealSize &