Android监听用户的截屏、投屏、录屏行为
一.截屏
方案一:使用系统广播监听截屏操作
从Android Q(10.0)开始,Intent.ACTION_SCREEN_CAPTURED_CHANGED字段不再被支持。这是因为Google在安卓10 中引入了一个新的隐私限制,即限制应用在用户开启了屏幕录制功能或截屏功能时获取相应的广播。
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)) {
// 截屏操作
// 在这里执行你的逻辑操作
}
}
}
<receiver
android:name=".ScreenCaptureReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.SCREEN_CAPTURE_CHANGED" />
</intent-filter>
</receiver>
ScreenCaptureReceiver receiver = new ScreenCaptureReceiver();
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_CAPTURE_CHANGED);
registerReceiver(receiver, filter);
unregisterReceiver(receiver);
public class ScreenCaptureReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_SCREEN_CAPTURE_CHANGED.equals(action)) {
// 截屏操作
Toast.makeText(context, "用户进行了截屏操作", Toast.LENGTH_SHORT).show();
}
}
}
方案二:使用ContentObserver监听截屏操作
另一种监听截屏操作的方法是使用ContentObserver来监听系统截屏文件的变化。以下是一个示例代码:
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);
}
}
ScreenCaptureObserver observer = new ScreenCaptureObserver(this);
observer.start();
对比与选型建议
使用 BroadcastReceiver
方案一的优点:
方案一的缺点:
使用 ContentObserver
方案二的优点:
方案二的缺点:
选型建议
根据需求,如果只关心截屏的发生与否,并不需要获取截屏的具体内容,方案一可以考虑。如果需要获取截屏内容的具体信息,方案二比较适合。如果只需要监听应用内的截屏操作,方案一比较方便。如果需要监听系统级别的截屏操作,需要使用方案二。
二.录屏
在 Android 开发中,要监听用户的录屏操作,可以使用以下两种方案:
方案一:使用 MediaProjection API
private MediaProjectionManager mediaProjectionManager;
private MediaProjection mediaProjection;
private MediaProjection.Callback projectionCallback;
mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
private static final int REQUEST_CODE_SCREEN_CAPTURE = 1;
Intent intent = mediaProjectionManager.createScreenCaptureIntent();
startActivityForResult(intent, REQUEST_CODE_SCREEN_CAPTURE);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_SCREEN_CAPTURE && resultCode == RESULT_OK) {
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
startScreenCapture();
}
}
private VirtualDisplay virtualDisplay;
private MediaRecorder mediaRecorder;
private void startScreenCapture() {
DisplayMetrics metrics = getResources().getDisplayMetrics();
int screenWidth = metrics.widthPixels;
int screenHeight = metrics.heightPixels;
int screenDensity = metrics.densityDpi;
mediaRecorder = new MediaRecorder();
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setVideoSize(screenWidth, screenHeight);
mediaRecorder.setVideoFrameRate(30);
mediaRecorder.setOutputFile(getOutputFilePath());
Surface surface = mediaRecorder.getSurface();
virtualDisplay = mediaProjection.createVirtualDisplay(
"ScreenCapture",
screenWidth,
screenHeight,
screenDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
surface,
null,
null);
mediaRecorder.prepare();
mediaRecorder.start();
projectionCallback = new MediaProjection.Callback() {
@Override
public void onStop() {
stopScreenCapture();
}
};
mediaProjection.registerCallback(projectionCallback, null);
}
private void stopScreenCapture() {
if (virtualDisplay != null) {
virtualDisplay.release();
virtualDisplay = null;
}
if (mediaRecorder != null) {
mediaRecorder.stop();
mediaRecorder.reset();
mediaRecorder.release();
mediaRecorder = null;
}
if (mediaProjection != null) {
mediaProjection.unregisterCallback(projectionCallback);
mediaProjection.stop();
mediaProjection = null;
}
}
方案二:使用 ContentObserver 监听屏幕录制状态变化
public class ScreenRecordObserver extends ContentObserver {
private static final String SCREEN_RECORD_STATE_PATH = "/sys/class/graphics/fb0/screen_state";
private OnScreenRecordStateChangedListener listener;
public ScreenRecordObserver(Handler handler) {
super(handler);
}
public void setOnScreenRecordStateChangedListener(OnScreenRecordStateChangedListener listener) {
this.listener = listener;
}
@Override
public void onChange(boolean selfChange, Uri uri) {
if (listener != null) {
boolean isRecording = isScreenRecording();
listener.onScreenRecordStateChanged(isRecording);
}
}
private boolean isScreenRecording() {
try {
FileInputStream fis = new FileInputStream(SCREEN_RECORD_STATE_PATH);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fis));
String state = bufferedReader.readLine();
bufferedReader.close();
return !"0".equals(state);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
public interface OnScreenRecordStateChangedListener {
void onScreenRecordStateChanged(boolean isRecording);
}
private ScreenRecordObserver screenRecordObserver;
screenRecordObserver = new ScreenRecordObserver(new Handler());
screenRecordObserver.setOnScreenRecordStateChangedListener(new OnScreenRecordStateChangedListener() {
@Override
public void onScreenRecordStateChanged(boolean isRecording) {
if (isRecording) {
// 屏幕开始录制
} else {
// 屏幕停止录制
}
}
});
getContentResolver().registerContentObserver(Uri.parse("content://" + SCREEN_RECORD_STATE_PATH), true, screenRecordObserver);
对比与选型建议
使用 MediaProjection API
方案一的优点:
方案一的缺点:
使用 ContentObserver 监听屏幕录制状态变化
方案二的优点:
方案二的缺点:
选型建议
根据需求,如果需要准确监听录屏的开始和结束时间,并且需要获取到录屏的具体内容,推荐使用方案一。
但如果只是需要知道录屏状态变化,而不关心具体的时间和内容,方案二比较简单方便。
三.投屏
在 Android 开发中,要监听用户的投屏操作,可以使用以下两种方案:
方案一:使用 MediaRouter API
首先,在你的 AndroidManifest.xml 文件中添加以下权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
private MediaRouter mediaRouter;
private MediaRouter.Callback mediaRouterCallback;
mediaRouter = (MediaRouter) getSystemService(Context.MEDIA_ROUTER_SERVICE);
mediaRouterCallback = new MediaRouter.Callback() {
@Override
public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo route) {
// 投屏开始
}
@Override
public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route) {
// 投屏结束
}
};
mediaRouter.addCallback(MediaRouter.ROUTE_TYPE_LIVE_VIDEO, mediaRouterCallback);
方案二:使用 DisplayManager API
首先,在 AndroidManifest.xml 文件中添加以下权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
- 创建一个
DisplayManager.DisplayListener
对象,并重写onDisplayAdded()
、onDisplayRemoved()
和onDisplayChanged()
方法。
private DisplayManager displayManager;
private DisplayManager.DisplayListener displayListener;
displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
displayListener = new DisplayManager.DisplayListener() {
@Override
public void onDisplayAdded(int displayId) {
// 投屏开始
}
@Override
public void onDisplayRemoved(int displayId) {
// 投屏结束
}
@Override
public void onDisplayChanged(int displayId) {
// 投屏状态变化
}
};
displayManager.registerDisplayListener(displayListener, null);
对比与选型建议
使用 MediaRouter API
方案一的优点:
方案一的缺点:
使用 DisplayManager API
方案二的优点:
方案二的缺点:
选型建议
根据需求,如果只需要监听特定类型的投屏操作,并且需要获取投屏的具体内容,推荐使用方案一。
如果需要监听所有类型的投屏操作,方案二比较适合。
同时,如果只关心投屏的开始和结束时间,并不需要具体的投屏内容,两种方案都可以考虑。
原文地址:https://blog.csdn.net/ldld1717/article/details/134756724
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_36920.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!