截屏事件监听实现

现在很多app都有监听截屏的功能,可以提示用户分享或者发送截屏图片,进一步提升app的用户体验。例如,微信在截屏后,点击输入框+号,会提示发送刚才的截屏图片,非常方便实用。其实,微信不光对截屏的图片进行了监听,你的手机sdcard里的大部分目录下新增图片时,都会被监听到。比如,你可以直接复制一张相册里的图片,微信也会提示。之前以为微信只是监听了系统截屏时发送的广播,然而查了文档并没有发现任何截屏类的广播。上述微信的例子也很好的解释了,其实对于截屏以及其他新增图片的监听是通过对sdcard文件内容变动的监听。
实现截屏监听主要有两种方式,使用FileObserver和ContentObserver,顾名思义,一个是基于文件或者目录的监听,一个是基于内容的监听。下面利用这两种方式简单实现了对于图片文件变动的监听。

FileObserver

FileObserver主要用于监听指定路径的目录或者文件的变动情况,包括监听目录下的子目录和文件以及目录本身,同时也可以指定监听文件变动的形式,例如创建、删除、移动、修改等,或者全部事件都监听。例如这里我们需要监听sdcard截屏目录,并且指定监听事件为FileObserver.CREATE,这样当screenshots目录下新增截屏图片时,onEvent事件就会触发,并且回调了截屏文件的相对路径,拿到路径我们就可以做想做的事情了。主要测试代码如下:

private void addFileObserver() {
    String screenPath = getScreenshotPath();
    fileObserver = new ScreenshotFileObserver(screenPath, FileObserver.CREATE);
    fileObserver.startWatching(); // 开始监听
}

class ScreenshotFileObserver extends FileObserver {

    public ScreenshotFileObserver(String path) {
        super(path);
    }

    public ScreenshotFileObserver(String path, int mask) {
        super(path, mask);
    }

    @Override
    public void onEvent(int event, final String path) {
        if (event == FileObserver.CREATE) {
            Log.d("screenshot", path);
            File file = new File(getScreenshotPath() + path);
            // todo sth. with the screenshot picture
            ...
        }
    }
}

需要注意的是使用FileObserver可能需要声明WRITE_EXTERNAL_STORAGE和MOUNT_UNMOUNT_FILESYSTEMS权限,虽然官方文档并没有提到这点,但是不加权限可能导致FileObserver不能正常工作,但仅仅是监听不到文件变动而已,程序不会crash。
FileObserver用法非常简单,但是一个FileObserver只能监听一个目录。如果需要监听多个目录会比较麻烦,可能你会觉得直接监听sdcard根目录可以搞定,但是那样sdcard下任何一个文件的变动都会被监听,效率和性能可能是个问题。而且有时候我们其实并不清楚需要监听的目录的具体路径,比如不同厂商的手机保存截屏的目录可能不尽相同。
另外,FileObserver在android 6.0以上存在bug,监听不到目录的变动,只能监听指定的具体文件,具体讨论可见:https://code.google.com/p/android/issues/detail?id=189231

ContentObserver

ContentObserver主要用于监听ContentProvider内容的变动,例如图片数据、音频数据、视频数据等。当有内容变动时,系统会相应修改其在ContentProvider中的记录。不同于FileObserver监听的是具体的文件或者目录路径,ContentObserver监听的是一个指定的Uri,通常可以理解为需要监听的数据类型。例如,这里我们需要监听截屏,可以向ContentResolver注册一个ContentObserver,并指定uri为系统媒体图片,那么当图片数据发生变化时,onChange方法就会被回调。根据回调返回的Uri,我们可以判断变动是否来自截屏图片,这样就可以实现对截屏事件的监听。

private void addContentObserver() {
    contentObserver = new ScreenshotContentObserver(new Handler(getMainLooper()));
    Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    getContentResolver().registerContentObserver(uri, false, contentObserver);
}

class ScreenshotContentObserver extends ContentObserver {

    public ScreenshotContentObserver(Handler handler) {
        super(handler);
    }

    @Override
    public void onChange(boolean selfChange, Uri uri) {
        super.onChange(selfChange, uri);
        // 处理uri获取真实的filepath,判断是否是截屏图片,通常filepath会包含screenshot关键字
        ...
    }
}

ContentObserver监听的仅仅只是ContentProvider的记录变动,实际对应文件的变动可能还没有完成,两者可能是个异步的过程或者是操作顺序的问题。例如监听截屏事件,测试时发现onChange被回调了,但是立即操作回调的uri对应的文件却无法得到正确的结果。这是因为截屏文件还没有完全写入导致的,通常的解决方法是提供给用户一个交互界面来缓冲下。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在移动端应用中,可以通过监听系统的截屏事件实现截屏行为的监听。不同平台的实现方式略有不同,下面我将分别介绍Android和iOS平台的监听方法。 对于Android平台,可以通过注册广播接收器来监听截屏事件。首先,在AndroidManifest.xml文件中添加以下权限和声明: ```xml <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application ...> ... <receiver android:name=".ScreenshotReceiver"> <intent-filter> <action android:name="android.intent.action.SCREEN_ON" /> <action android:name="android.intent.action.SCREEN_OFF" /> <action android:name="android.intent.action.USER_PRESENT" /> </intent-filter> </receiver> </application> ``` 然后,创建一个名为ScreenshotReceiver的广播接收器类,并在其中重写`onReceive()`方法: ```java public class ScreenshotReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (Intent.ACTION_SCREEN_ON.equals(action)) { // 屏幕点亮时的逻辑处理 } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 屏幕关闭时的逻辑处理 } else if (Intent.ACTION_USER_PRESENT.equals(action)) { // 解锁屏幕时的逻辑处理 } } } ``` 通过在`onReceive()`方法中添加逻辑处理,可以对不同的截屏事件做出相应的响应。 对于iOS平台,可以使用`UIScreen`的`UIScreenDidScreenshotNotification`通知来监听截屏事件。在需要监听的地方,添加以下代码: ```swift NotificationCenter.default.addObserver(self, selector: #selector(handleScreenshot), name: UIScreen.capturedDidChangeNotification, object: nil) @objc func handleScreenshot(notification: NSNotification) { // 截屏事件的处理逻辑 } ``` 在`handleScreenshot()`方法中,可以编写对截屏事件的处理逻辑。 请注意,在iOS平台上,监听截屏事件只能获取到截屏已经完成的通知,无法阻止截屏行为的发生。因为iOS系统保护了用户的隐私,不允许应用直接干涉截屏操作。以上方法只适用于监听截屏事件并作出响应,而无法禁止截屏行为的发生。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值