探秘Android应用如何监听屏幕截图操作,从系统广播到ContentObserver方法

移动开发 Android
通过ContentObserver观察MediaStore.Images.Media.EXTERNAL_CONTENT_URI或MediaStore.Images.Media.INTERNAL_CONTENT_URI来检测媒体文件(截屏)保存触发的变化事件。

使用系统广播监听截屏操作

从Android10.0开始,Intent.ACTION_SCREEN_CAPTURED_CHANGED不再被支持。因为Google在安卓10中引入了一个新的隐私限制,即限制应用在用户开启了屏幕录制功能或截屏功能时获取相应的广播。

  1. 创建一个BroadcastReceiver类来接收截屏广播:
public class ScreenCaptureReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (Intent.ACTION_SCREEN_CAPTURES_CHANGED.equals(action)) {
            // 截屏操作
            Toast.makeText(context, "用户进行了截屏操作", Toast.LENGTH_SHORT).show();
        }
    }
}
  1. 在AndroidManifest.xml文件中声明截屏广播接收器:
<receiver
    android:name=".ScreenCaptureReceiver"
    android:enabled="true">
    <intent-filter>
        <action android:name="android.intent.action.SCREEN_CAPTURE_CHANGED" />
    </intent-filter>
</receiver>
  1. 注册截屏广播接收器,开始监听截屏操作:
ScreenCaptureReceiver receiver = new ScreenCaptureReceiver();
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_CAPTURE_CHANGED);
registerReceiver(receiver, filter);
  1. 在不需要监听时,取消注册截屏广播接收器:
unregisterReceiver(receiver);

使用ContentObserver监听截屏操作

通过ContentObserver观察MediaStore.Images.Media.EXTERNAL_CONTENT_URI或MediaStore.Images.Media.INTERNAL_CONTENT_URI来检测媒体文件(截屏)保存触发的变化事件。

public class ScreenCaptureObserver extends ContentObserver {
    private static final String TAG = "ScreenCaptureObserver";
    private static final String SCREENSHOTS_DIR = Environment.getExternalStorageDirectory().toString() + "/Pictures/Screenshots";
    private Context mContext;

    public ScreenCaptureObserver(Context context) {
        super(null);
        mContext = context;
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        Log.d(TAG, "Screen capture detected");
        if (uri.toString().matches(MediaStore.Images.Media.EXTERNAL_CONTENT_URI.toString() + "/[0-9]+")) {
            Cursor cursor = null;
            try {
                cursor = mContext.getContentResolver().query(uri, new String[]{MediaStore.Images.Media.DATA}, null, null, null);
                if (cursor != null && cursor.moveToFirst()) {
                    String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
                    if (path != null && path.startsWith(SCREENSHOTS_PATH)) {
                        // 此处为用户截屏行为的响应逻辑
                    }
                }
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        }
    }

    public void start() {
        ContentResolver contentResolver = mContext.getContentResolver();
        contentResolver.registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, this);
    }

    public void stop() {
        ContentResolver contentResolver = mContext.getContentResolver();
        contentResolver.unregisterContentObserver(this);
    }
}

使用示例:

new ScreenCaptureObserver(this).start();

这种方法有几个限制和注意事项:

  1. 「不是所有截屏都会触发媒体扫描」:有些设备或应用可能会将截屏保存到一个不会触发媒体扫描的目录中。
  2. 「延迟」:媒体扫描器可能不会立即运行,因此可能会在截屏发生后的一段时间内才收到通知。
  3. 「可能收到非截屏图片的通知」:任何新添加到媒体数据库的图片都会触发你的ContentObserver。

两种方式对比

方式一的优点:

  • 直接监听 Intent.ACTION_SCREENSHOT,无需处理 Uri 的变化。
  • 适用于监听应用内的截屏操作。

方式一的缺点:

  • 只能监听到整个屏幕的截屏操作,无法获取到具体的截屏内容。
  • 从Android Q(10.0)开始,Intent.ACTION_SCREEN_CAPTURED_CHANGED字段不再被支持。

方式二的优点:

  • 可以监听到截屏操作发生的具体 Uri,可以进一步获取截屏的文件路径和信息。
  • 适用于监听系统级别的截屏操作。

方式二的缺点:

  • 需要指定监听的 Uri,可能需要考虑兼容性问题。
  • 需要在代码中处理 Uri 的变化,并解析截屏的文件路径。

「选型建议」根据需求,如果只关心截屏的发生与否,并不需要获取截屏的具体内容,方式一可以考虑。如果需要获取截屏内容的具体信息,方式二比较适合。如果只需要监听应用内的截屏操作,方式一比较方便。如果需要监听系统级别的截屏操作,需要使用方式二。

责任编辑:武晓燕 来源: 沐雨花飞蝶
相关推荐

2010-01-28 14:01:32

Android监听通话

2010-08-18 10:13:55

IntentAndroid

2017-12-13 16:50:14

传播

2019-02-22 15:40:50

Windows 10截取屏幕截图

2019-11-06 11:00:49

Windows 10屏幕截图Windows

2019-03-12 10:10:44

Windows 10禁用屏幕截图

2009-08-07 15:54:51

敏感信息检测系统UnisSISS

2010-02-07 14:54:13

Android

2013-08-13 11:25:56

屏幕尺寸Android应用

2018-01-19 22:48:27

谷歌操作系统Android

2013-05-27 13:37:42

Android开发移动开发屏幕截图

2010-01-25 13:56:58

Android本地广播

2018-10-24 14:15:40

Windows 10应用程序屏幕截图

2019-11-14 16:45:52

Windows10计算机屏幕屏幕截图

2018-11-07 09:45:39

Windows 10 剪切工具屏幕截图

2010-03-05 16:47:11

Android操作系统

2011-07-28 10:32:32

操作系统军方

2009-03-26 08:47:55

Windows Mob微软移动OS

2010-02-06 16:02:57

Android 应用程

2010-04-14 16:26:14

Unix操作系统
点赞
收藏

51CTO技术栈公众号