在移动互联网时代,人们使用的手机应用越来越多,其中很多应用运用到了相机、麦克风等设备,用户信息也随之泄漏。面对手机应用录屏等安全隐患,防止录屏成为一个迫切的问题。本篇文章将介绍几种常见的防止录屏的开发技术及其原理。
一、iOS 官方开发技术:ReplayKit
ReplayKit 是苹果官方为 iOS 提供的防止录屏的开发技术,可以帮助开发者创建防录屏的应用程序。 开发者可以使用 ReplayKit 提供的 API 防止其他应用对自己的应用进行屏幕录制。具体步骤如下:
1. 初始化 ReplayKit
开启 ReplayKit:
```
[RPSystemBroadcastPickerView class];
```
2. 实现 RPPreviewViewControllerDelegate 协议功能
在屏幕记录完成之后,系统会展示录像预览界面,此时可以通过实现 RPPreviewViewControllerDelegate 来进行界面的自定义处理。
3. 实现 RPBroadcastActivityViewControllerDelegate 协议功能
展示自定义录屏界面,可以通过实现 RPSystemBroadcastPickerView 的代理方法来进行控制。
二、Android 官方开发技术:Media Projection
Media Projection 是 Android 官方提供的一个防录屏技术,具体实现步骤如下:
1. 申请权限
在系统版本 Android 5.0 及以上,需要首先向系统申请 Media Projection 权限。
```
startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
```
在应用接收到系统的回应之后,在 onActivityResult() 回调方法中,可以去处理 ScreenCaptureIntent 数据。
2. 生成 bitmap 图像
通过 MediaProjection.createVirtualDisplay() 方法获取当前 Activity 在屏幕上的显示信息,按照指定格式生成 bitmap 图像。
3. 实现虚拟输入设备
通过创建虚拟输入设备,可以在应用启动时直接使用,避免了权限限制的问题。
```
public abstract class InputDevice implements Parcelable {
public static final int KEYBOARD_TYPE_UNKNOWN = 0x00000000;
public static final int KEYBOARD_TYPE_NON_ALPHABETIC = 0x00000001;
public static final int KEYBOARD_TYPE_ALPHABETIC = 0x00000002;
public static final int MOTION_RANGE_X = 0;
public static final int MOTION_RANGE_Y = 1;
public static final int MOTION_RANGE_PRESSURE = 2;
public static final int MOTION_RANGE_SIZE = 3;
public static final int MOTION_RANGE_TOOL_MAJOR = 4;
public static final int MOTION_RANGE_TOOL_MINOR = 5;
public static final int MOTION_RANGE_ORIENTATION = 6;
public static final int SOURCE_KEYBOARD = 0x00000100;
public static final int SOURCE_DPAD = 0x00000200;
public static final int SOURCE_GAMEPAD = 0x00000400;
public static final int SOURCE_TOUCHSCREEN = 0x00001000;
public static final int SOURCE_MOUSE = 0x00002000;
public static final int SOURCE_STYLUS = 0x00004000;
public static final int SOURCE_TOUCHPAD = 0x00100000;
public static final int SOURCE_JOYSTICK = 0x01000000;
public static final String ADDR = "device.addr";
public static final String BUDDY_SINK = "sink";
public static final String DEVICE_NAME = "device.name";
public static final String DEVICE_PRODUCT_ID = "device.productid";
public static final String DEVICE_VENDOR_ID = "device.vendorid";
public static final String FAILURE_REPORTED = "failures_reported";
protected InputDevice() {}
public abstract int getId();
public abstract int getControllerNumber();
public abstract String getDescriptor();
public abstract int getVendorId();
public abstract int getProductId();
public abstract String getName();
public abstract int getKeyboardType();
public abstract MotionRange getMotionRange(int axis);
public abstract MotionRange[] getMotionRanges();
public static InputDevice getDevice(int id) {
return InputManager.getInstance().getInputDevice(id);
}
public static int[] getDeviceIds() {
return InputManager.getInstance().getInputDeviceIds();
}
public static InputDevice[] getDeviceList() {
return InputManager.getInstance().getInputDevices();
}
public final boolean isVirtual() {
return !isExternal();
}
public final boolean isExternal() {
return getSources() == 0;
}
public final boolean supportsSource(int source) {
return (getSources() & source) == source;
}
public final boolean supportsKeyEvent(int keyCode) {
return false;
}
public final KeyEvent[] getEvents(MotionEvent motion) {
return KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD).getEvents(motion.getHistorySize(), motion.getEventTime(), motion.getPointerCount(),
motion.getPointerIds(), motion.getToolTypes(), motion.getXs(), motion.getYs(),
motion.getPressures(), motion.getOrientations(), motion.getButtonState(), KeyEvent.FLAG_SOFT_KEYBOARD);
}
public final boolean hasMicrophone() {
return (getSources() & AudioSource.MIC) == AudioSource.MIC;
}
public final boolean hasKeyboard() {
return (getSources() & SOURCE_KEYBOARD) == SOURCE_KEYBOARD;
}
public final boolean hasKeys(int[] keys) {
if (keys == null) {
throw new IllegalArgumentException("keys must not be null.");
}
int[] keyCodes = new int[keys.length];
for (int i = 0; i < keys.length; i++) {
keyCodes[i] = KeyEvent.keyCodeFromString(KEYCODE_UNKNOWN);
}
return hasKeys(keyCodes);
}
public final boolean hasKeys(int... keyCodes) {
if (keyCodes == null) {
throw new IllegalArgumentException("keyCodes must not be null.");
}
Arrays.sort(keyCodes);
int[] deviceKeyCodes = getKeyCodes();
Arrays.sort(deviceKeyCodes);
return Arrays.binarySearch(deviceKeyCodes, keyCodes) >= 0;
}
public final boolean hasKeys(List
if (keys == null) {
throw new IllegalArgumentException("keys must not be null.");
}
int[] keyCodes = new int[keys.size()];
for (int i = 0; i < keys.size(); i++) {
keyCodes[i] = keys.get(i).getKeyCode();
}
return hasKeys(keyCodes);
}
public final int getSources() {
return 0;
}
public final InputChannel getChannel() {
return mChannel;
}
@Deprecated
public final MotionRange getMotionRange(int axis, int source) {
if (source == InputDevice.SOURCE_CLASS_POINTER) {
return getMotionRange(axis);
} else {
return null;
}
}
@Deprecated
public final MotionRange[] getMotionRanges(int source) {
if (source == InputDevice.SOURCE_CLASS_POINTER) {
return getMotionRanges();
} else {
return MotionRange.EMPTY_ARRAY;
}
}
private InputChannel mChannel;
protected InputDevice(int id, int generation, int controllerNumber, String name, int vendorId, int productId, String descriptor, int sources) {
mChannel = new InputChannel();
}
protected void finalize() throws Throwable {
try {
mChannel.dispose();
} finally {
super.finalize();
}
}
public int[] getKeyCodes() {
return new int[0];
}
}
```
三、第三方开发技术:巧用 GLSurfaceView
GLSurfaceView 是一个基于 OpenGL ES 的适用于 Android 平台的开放源代码的 3D 渲染器,主要应用于处理高质量图像和视频,也可以用来实现防止录屏的效果。实现如下:
1. 配置 SurfaceView
在 Android 平台下,可以创建一个 SurfaceView,将视频播放在 SurfaceView 上,从而达到实现防录屏的目的。随着技术的发展,即使被伪装成黑屏,也可以防止被录制。
2. 应用铺屏技术
铺屏技术是通过展示自定义的图像,来实现防录屏的效果。铺屏技术具体实现过程如下:
① 首先创建一个 GLSurfaceView。
② 然后创建 TextureView 对象,将 GLSurfaceView 的预览画面传送到 TextureView 上。
③ 在 TextureView 的画面上显示图像,从而实现铺屏的目的。
综上所述,本文介绍了几种常见的防止录屏的方法,包括 iOS 官方开发技术:ReplayKit,Android 官方开发技术:Media Projection,以及第三方开发技术:巧用 GLSurfaceView,每种方法都有其特定的实现原理和应用场景。开发者可以根据自己应用的特点,选择适合的方式进行处理,从而达到防止录屏的效果。