Tích hợp module chặn chụp ảnh màn hình với React Native (block screenshot ios and android)
Sau đầy là phần tích hợp module về chặn chụp ảnh(block screenshot) trên Android và Ios.
Tuy nhiên sau khi TíT tìm hiểu thì trên ios không cho chặn chụp ảnh, còn android thì tuỳ vào hệ điều hành khác nhau mà sẽ xử lý khác nhau.
Ví dụ như máy của TíT là hãng realme thì ổn, còn với một số máy khác có thể sẽ cho chụp ảnh tuy nhiên ảnh sẽ hiển thị chỉ là màu đen hoặc màu trắng thôi.
- ANDROID:
Trong folder java của với đường dẫn android/app/src/main/java. Tạo mới 1 folder như TíT đang đặt là screenshot. Và trong đó tạo 2 file:
- CustomPreventScreenshotPackage.java
package screenshot;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class CustomPreventScreenshotPackage implements ReactPackage {
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
return Arrays.<NativeModule>asList(new PreventScreenshotModule(reactContext));
}
}
- PreventScreenshotModule.java
package screenshot;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Promise;
import android.view.WindowManager;
import static com.facebook.react.bridge.UiThreadUtil.runOnUiThread;
public class PreventScreenshotModule extends ReactContextBaseJavaModule {
private static final String PREVENT_SCREENSHOT_ERROR_CODE = "PREVENT_SCREENSHOT_ERROR_CODE";
private final ReactApplicationContext reactContext;
PreventScreenshotModule(ReactApplicationContext context) {
super(context);
reactContext = context;
}
@Override
public String getName() {
return "PreventScreenshotModule";
}
@ReactMethod
public void forbid(Promise promise) {
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
getCurrentActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
promise.resolve("Done. Screenshot taking locked.");
} catch(Exception e) {
promise.reject(PREVENT_SCREENSHOT_ERROR_CODE, "Forbid screenshot taking failure.");
}
}
});
}
@ReactMethod
public void allow(Promise promise) {
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
getCurrentActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
promise.resolve("Done. Screenshot taking unlocked.");
} catch (Exception e) {
promise.reject(PREVENT_SCREENSHOT_ERROR_CODE, "Allow screenshot taking failure.");
}
}
});
}
}
Các bạn hãy chú ý trong log nếu hiện dòng message trong promise.resole là đã chặn, ngược lại promise.reject là đã bỏ chặn nha. Sau đó tại file MainApplication.java hãy thêm module này:
Và add module này vào packages:
- IOS
Tiếp theo là với Ios, sẽ chỉ làm được là chạy vào hàm để ở React Native biết là khi nào người dùng chụp ảnh thôi. Còn đâu lưu ý là không chặn được đâu nha.
Đầu tiên trong folder ios của ứng dụng, tạo mới folder ScreenshotDetector, trong folder này tạo 2 file (tạo NewGroup từ XCode, rồi từ đó mới tạo NewFile nha)
- RNScreenshotDetector.h
#import <React/RCTEventEmitter.h>
#import <React/RCTBridgeModule.h>
@interface RNScreenshotDetector : RCTEventEmitter <RCTBridgeModule>
- (void)setupAndListen:(RCTBridge*)bridge;
- (void)screenshotDetected:(NSNotification*)notification;
@end
- RNScreenshotDetector.m
#import "RNScreenshotDetector.h"
#import <React/RCTBridge.h>
#import <React/RCTEventDispatcher.h>
@implementation RNScreenshotDetector
RCT_EXPORT_MODULE(PreventScreenshotModule);
- (NSArray<NSString *> *)supportedEvents {
return @[@"ScreenshotTaken"];
}
- (void)setupAndListen:(RCTBridge*)bridge {
// First set up native bridge
[self setBridge:bridge];
// Now set up handler to detect if user takes a screenshot
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationUserDidTakeScreenshotNotification
object:nil
queue:mainQueue
usingBlock:^(NSNotification *notification) {
[self screenshotDetected:notification];
}];
}
- (void)screenshotDetected:(NSNotification *)notification {
[self.bridge.eventDispatcher sendAppEventWithName:@"ScreenshotTaken" body:nil];
}
@end
Sau đó trong file AppDelegate.m của dự án, hãy thêm module này như sau:
#import "RNScreenshotDetector.h"
Chỗ "..." là tuỳ thuộc vào dự án của mọi người nha...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
// Somewhere below this you can setup the screenshot detector to listen for events
RNScreenshotDetector* screenshotDetector = [[RNScreenshotDetector alloc] init];
[screenshotDetector setupAndListen:rootView.bridge];
return YES;
}
Vậy là đã setup xong cho cả ios và android rồi đó. Tới bước import native module vào react native nào👯
Bạn hãy tạo một file như này để sử dụng nè 💪💪💪:
import { NativeEventEmitter, NativeModules } from "react-native";
// for IOS
const { PreventScreenshotModule } = NativeModules;
export const SCREENSHOT_EVENT = "ScreenshotTaken";
export function subscribeScreenshot(cb) {
const eventEmitter = new NativeEventEmitter(PreventScreenshotModule);
let emitterSubscription = eventEmitter.addListener(SCREENSHOT_EVENT, cb, {});
return emitterSubscription;
}
// for Android
export const forbidFunction = async () => {
try {
await PreventScreenshotModule.forbid();
} catch (e) {
console.log(e);
}
};
export const allowFunction = async () => {
try {
await PreventScreenshotModule.allow();
} catch (e) {
console.log(e);
}
};
Đối với ios thì hãy gọi hàm subscribeScreenshot ở componentDidMount nha.
this.screenShootSub = subscribeScreenshot(() => {
// code here
});
Và nhớ unsubscribe ở componentWillUnmount nha.
this.screenShootSub.remove();
Đối với android thì đơn giản hơn, gọi hàm forbidFunction là sẽ chặn chụp ảnh, còn allowFunction thì sẽ cho chụp ảnh trở lại.
Vậy là đã xong phần tích hợp module chặn chụp ảnh màn hình vào React Native. TíT sẽ tiếp tục tìm hiểu các module khác và chia sẻ với mọi người. Mong rằng mọi người hãy góp ý để TíT hoàn thiện tốt hơn