Android App内截屏监控及涂鸦功能实现

Android App内截屏监控及涂鸦功能实现

Android截屏功能是一个常用的功能,可以方便的用来分享或者发送给好友,本文介绍了如何实现app内截屏监控功能,当发现用户在我们的app内进行了截屏操作时,将自动展示该截屏,并提供用户随意圈点涂鸦,添加马赛克,撤销,分享等功能。

本文GitHub源码地址
实现效果如下:
监听截屏,展示截屏并涂鸦

实现该功能有以下技术需求:

1.	当app在前台展示的时候能够自动监听用户在app内的截屏,当app进入后台,停止监听
2.	监听到截屏后展示该截屏,并提供涂鸦(包括随意圈点和敏感信息马赛克)和上传分享功能
3.	涂鸦的每一步都可以撤销

涉及如下知识点:

1. App内截屏监听
2. 大图压缩
3. ImageView尺寸自适应
4. 自定义View实现涂鸦功能
5. 涂鸦撤销操作

对于截图监听有两种常用方案,方案一是通过FileObserver监听截屏文件夹,当有新的截屏文件产生时,调用设定的回调函数执行相关操作。该方案优缺点如下:
优点:

1. 实现简单

缺点:

1. 不同手机默认的截屏路径可能不同,需要做适配处理
2. 不同手机截屏触发的事件名称可能不同,需要测试适配
3. 监听到截屏事件后马上获取图片获取不到,需要延迟一段时间

方案二是通过ContentObserver监听多媒体图片库资源的变化。当手机上有新的图片文件产生时都会通过MediaProvider类向图片数据库插入一条记录,以方便系统的图片库进行图片查询,可以通过ContentObserver接收图片插入事件,并获取插入图片的URI。
优点:

1. 不同手机触发的事件是一样的

缺点:

1. 不同手机截屏文件的前缀可能不同,需要做适配
2. 监听到截屏事件后马上获取图片获取不到,需要延迟一段时间

这两种方式都需要根据手机做适配,第一种方式可以控制截屏监控只在App前台展示的时候进行,操作简单,我们使用这种方式做截屏监控。

接下来通过代码介绍具体实现。

FileObserver通过startWatching/stopWatching方法进行启动/停止文件监控,我们在BaseActivity的onResume和onPause方法中分别调用两个方法,其他Activity继承BaseActivity,实现App进入前台开始监控,转入后台停止监控的效果。

BaseActivity.java

public class BaseActivity extends AppCompatActivity {
   
    @Override
    protected void onResume() {
   
        super.onResume();

        //  设置回调函数
        FileObserverUtils.setSnapShotCallBack(new SnapShotTakeCallBack(this));
        FileObserverUtils.startSnapshotWatching();
    }

    @Override
    protected void onPause() {
   
        super.onPause();

        FileObserverUtils.stopSnapshotWatching();
    }
}

通过setSnapShotCallBack设置回调函数,并进行FileObserver初始化:

public class FileObserverUtils {
   
    ...
    public static void setSnapShotCallBack(ISnapShotCallBack callBack) {
   
        snapShotCallBack = callBack;
        initFileObserver();
    }

    private static void initFileObserver() {
   
        SNAP_SHOT_FOLDER_PATH = Environment.getExternalStorageDirectory()
                + File.separator + Environment.DIRECTORY_PICTURES
                + File.separator + "Screenshots" + File.separator;

        fileObserver = new FileObserver(SNAP_SHOT_FOLDER_PATH, FileObserver.CREATE) {
   
            @Override
            public void onEvent(int event, String path) {
   
                if (null != path && event == FileObserver.CREATE && (!path.equals(lastShownSnapshot))){
   
                    lastShownSnapshot = path; // 有些手机同一张截图会触发多个CREATE事件,避免重复展示

                    String snapShotFilePath = SNAP_SHOT_FOLDER_PATH + path;

                    int tryTimes = 0;
                    while (true) {
   
                        try {
    // 收到CREATE事件后马上获取并不能获取到,需要延迟一段时间
                            Thread.sleep(600);
                        } catch (Exception e) {
   
                            e.printStackTrace();
                        }

                        try {
   
                            BitmapFactory.decodeFile(snapShotFilePath);
                            break;
                        } catch (Exception e) {
   
                            e.printStackTrace();
                            tryTimes++;
                            if (tryTimes >= MAX_TRYS) {
    // 尝试MAX_TRYS次失败后,放弃
                                return;
                            }
                        }
                    }

                    snapShotCallBack.snapShotTaken(path);
                }
            }
        };
    }
    ...
}

FileObserver初始化传入要监控的截屏图片文件夹路径,当该文件夹下面的文件发生变化,包括截图生成新的图片时,调用onEvent函数,传入event和文件的path。我们根据event过滤出截屏事件,在这里是FileObserver.CREATE事件。收到事件后马上获取截图是获取不到的,需要过几百毫秒才能获取到,这里会让线程sleep一段时间再尝试获取,重试两次如果还获取失败就放弃。获取成功的话调用设置好的回调函数进行下一步操作。

我们的回调函数很简单,就是打开一个用于展示截屏的新的Activity叫SnapShotEditActivity,并传入截屏路径:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值