美文网首页
Android 应用监听截屏操作

Android 应用监听截屏操作

作者: 普通的程序员 | 来源:发表于2018-05-13 12:22 被阅读0次

最近要求做一个app内监听截屏,然后调用自己的分享功能。

网上有很多方案。这里我采用的是内容监听方案。
参考
https://www.jianshu.com/p/d7aba5a03b0f

结合我的业务实际,以下是完整代码。

0.局部变量

private String data;//截图图片路径
private Handler mUiHandler;
private MediaContentObserver mInternalObserver;
private MediaContentObserver mExternalObserver;

private static final String[] MEDIA_PROJECTIONS = {
//            MediaStore.Images.ImageColumns.WIDTH,
//            MediaStore.Images.ImageColumns.HEIGHT,
            MediaStore.Images.ImageColumns.DATA,
            MediaStore.Images.ImageColumns.DATE_TAKEN
};

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"
};//国内机器截图路径有中文,有可能还得做国际化适配

  1. 自定义媒体内容观察者内部类(观察媒体数据库的改变)
private class MediaContentObserver extends ContentObserver {
        private Uri mediaContentUri;       // 需要观察的Uri

        public MediaContentObserver(Uri contentUri, Handler handler) {
            super(handler);
            mediaContentUri = contentUri;
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            // 处理媒体数据库反馈的数据变化
            handleMediaContentChange(mediaContentUri);
        }
    }

2.注册监听

private void initMediaContentObserver() {
        // 运行在 UI 线程的 Handler, 用于运行监听器回调
        mUiHandler = new Handler(Looper.getMainLooper());
        // 创建内容观察者,包括内部存储和外部存储
        mInternalObserver = new MediaContentObserver(MediaStore.Images.Media.INTERNAL_CONTENT_URI, mUiHandler);
        mExternalObserver = new MediaContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mUiHandler);
        // 注册内容观察者
        getContentResolver().registerContentObserver(
                MediaStore.Images.Media.INTERNAL_CONTENT_URI, false, mInternalObserver);
        getContentResolver().registerContentObserver(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, false, mExternalObserver);
    }

3.处理数据

    private void handleMediaContentChange(Uri contentUri) {
        Cursor cursor = null;
        try {
            // 数据改变时查询数据库中最后加入的一条数据
            cursor = getContentResolver().query(contentUri,
                    MEDIA_PROJECTIONS,
                    null, null, MediaStore.Images.ImageColumns.DATE_ADDED + " desc limit 1");

            if (cursor == null) return;
            if (!cursor.moveToFirst()) return;

            // cursor.getColumnIndex获取数据库列索引
            int dateTakenIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATE_TAKEN);
            long dateTaken = cursor.getLong(dateTakenIndex);  // 图片生成时间

//因为该监听也会监听到删除截图的操作,所以判断最后一张图的时间和现在时间,如果相差8s内,则认为是刚截图
//国内部分机器刚截的图并不是马上就写进去,而是放在内存了,8s是一个经验值
            if (System.currentTimeMillis() - dateTaken > 8000) return;

            int dataIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
            data = cursor.getString(dataIndex);        // 图片存储地址

//            int width = 0;
//            int height = 0;
//            int widthIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.WIDTH);
//            int heightIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.HEIGHT);
//            width = cursor.getInt(widthIndex);    // 获取图片高度
//            height = cursor.getInt(heightIndex);  // 获取图片宽度

            // 处理获取到的第一行数据
            handleMediaRowData(data);

        } catch (AndroidRuntimeException e) {
            //1.Android7.0以下机器要求用FLAG_ACTIVITY_NEW_TASK启动
            //2.部分机器写入截图实在是太慢,给个800ms延迟
            mUiHandler.postDelayed(() ->
                    startActivity(ShareCapturePicActivity.newIntent(this, data,
                            Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP)), 800);
            e.printStackTrace();
        } finally {
            if (cursor != null && !cursor.isClosed()) {
                cursor.close();
            }
        }
    }

  //处理监听到的资源
    private void handleMediaRowData(String data) {
        if (checkScreenShot(data)) {
            startActivity(ShareCapturePicActivity.newIntent(this, data, Intent.FLAG_ACTIVITY_SINGLE_TOP));
        }
    }

    //判断是否是截屏
    private boolean checkScreenShot(String data) {
        data = data.toLowerCase();
        // 判断图片路径是否含有指定的关键字之一, 如果有, 则认为当前截屏了
        for (String keyWork : KEYWORDS) {
            if (data.contains(keyWork)) {
                return true;
            }
        }
        return false;
    }

至于FLAG_ACTIVITY_NEW_TASK的问题,我在这篇文章有说。
非activity环境启动activity还需要FLAG_ACTIVITY_NEW_TASK吗?

顺带提一下
onNewIntent的周期
第一次singleTop启动,正常onCreate--start--resume
后续就是 onNewIntent---start--resume

相关文章

  • Android 应用监听截屏操作

    最近要求做一个app内监听截屏,然后调用自己的分享功能。 网上有很多方案。这里我采用的是内容监听方案。参考http...

  • Android 监听系统截屏操作(已适配Android Q)

    Android系统没有提供现成的Api来监听到用户的截屏操作,所以我们需要自己实现对用户截屏的监听。 针对这个特殊...

  • Android中截屏监听实现

    目的 监听到用户在使用我们的app时进行了截屏操作 方案 由于Android没有提供系统级别的监听,只能自己动手搞...

  • 截屏状态监听 - iOS

    既接到电话状态监听的需求之后再次添加了截屏状态的监听,当使用 App 时若用户执行截屏操作需要对当前状态进行监听操...

  • iOS 截屏&长截屏

    截屏在 iOS 开发中经常用到,本篇文章讲的是监听用户截屏操作,并且获取截屏图片,如果当前是UIScrollVie...

  • Android监听截屏

    Android系统没有提供默认的截屏事件监听方式,需要开发者自己想办法实现。查看了网上推荐的实现方式,主要是通过内...

  • Android 手势密码锁的使用细说

    监听屏幕锁屏和解锁事件 启动时进行检测 基类中全局进行监听 构造广播监听锁屏截屏事件 应用Application里...

  • iOS 屏幕录制监听并获取截取的图片

    1.屏幕截取监听,iOS会监听系统截屏操作,加上通知即可 2.在userDidTakeScreenshot进行操作...

  • Android之防截屏

    Android防截屏是防止泄密的措施之一,防截屏的措施有两种,一种是禁止截屏,另一种是监听用户是否截屏,这样就知道...

  • 基于MediaProjection实现Android移动手机截屏

    Android软件应用经常要求实现截屏和录屏的功能,那么如何实现Android软件截屏和录屏功能呢?本文将介绍基于...

网友评论

      本文标题:Android 应用监听截屏操作

      本文链接:https://www.haomeiwen.com/subject/wgfldftx.html