twonly-app-dependencies/no_screenshot/ios/Classes/IOSNoScreenshotPlugin.swift

182 lines
6.7 KiB
Swift

import Flutter
import UIKit
import ScreenProtectorKit
public class IOSNoScreenshotPlugin: NSObject, FlutterPlugin, FlutterStreamHandler {
private var screenProtectorKit: ScreenProtectorKit? = nil
private static var methodChannel: FlutterMethodChannel? = nil
private static var eventChannel: FlutterEventChannel? = nil
private static var preventScreenShot: Bool = false
private var eventSink: FlutterEventSink? = nil
private var lastSharedPreferencesState: String = ""
private var hasSharedPreferencesChanged: Bool = false
private static let ENABLESCREENSHOT = false
private static let DISABLESCREENSHOT = true
private static let preventScreenShotKey = "preventScreenShot"
private static let methodChannelName = "com.flutterplaza.no_screenshot_methods"
private static let eventChannelName = "com.flutterplaza.no_screenshot_streams"
private static let screenshotPathPlaceholder = "screenshot_path_placeholder"
init(screenProtectorKit: ScreenProtectorKit) {
self.screenProtectorKit = screenProtectorKit
super.init()
// Restore the saved state from UserDefaults
var fetchVal = UserDefaults.standard.bool(forKey: IOSNoScreenshotPlugin.preventScreenShotKey)
updateScreenshotState(isScreenshotBlocked: fetchVal)
}
public static func register(with registrar: FlutterPluginRegistrar) {
methodChannel = FlutterMethodChannel(name: methodChannelName, binaryMessenger: registrar.messenger())
eventChannel = FlutterEventChannel(name: eventChannelName, binaryMessenger: registrar.messenger())
let window = UIApplication.shared.delegate?.window
let screenProtectorKit = ScreenProtectorKit(window: window as? UIWindow)
screenProtectorKit.configurePreventionScreenshot()
let instance = IOSNoScreenshotPlugin(screenProtectorKit: screenProtectorKit)
registrar.addMethodCallDelegate(instance, channel: methodChannel!)
eventChannel?.setStreamHandler(instance)
registrar.addApplicationDelegate(instance)
}
public func applicationWillResignActive(_ application: UIApplication) {
persistState()
}
public func applicationDidBecomeActive(_ application: UIApplication) {
fetchPersistedState()
}
public func applicationWillEnterForeground(_ application: UIApplication) {
fetchPersistedState()
}
public func applicationDidEnterBackground(_ application: UIApplication) {
persistState()
}
public func applicationWillTerminate(_ application: UIApplication) {
persistState()
}
func persistState() {
// Persist the state when changed
UserDefaults.standard.set(IOSNoScreenshotPlugin.preventScreenShot, forKey: IOSNoScreenshotPlugin.preventScreenShotKey)
print("Persisted state: \(IOSNoScreenshotPlugin.preventScreenShot)")
updateSharedPreferencesState("")
}
func fetchPersistedState() {
// Restore the saved state from UserDefaults
var fetchVal = UserDefaults.standard.bool(forKey: IOSNoScreenshotPlugin.preventScreenShotKey) ? IOSNoScreenshotPlugin.DISABLESCREENSHOT :IOSNoScreenshotPlugin.ENABLESCREENSHOT
updateScreenshotState(isScreenshotBlocked: fetchVal)
print("Fetched state: \(IOSNoScreenshotPlugin.preventScreenShot)")
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "screenshotOff":
shotOff()
result(true)
case "screenshotOn":
shotOn()
result(true)
case "toggleScreenshot":
IOSNoScreenshotPlugin.preventScreenShot ? shotOn(): shotOff()
result(true)
case "startScreenshotListening":
startListening()
result("Listening started")
case "stopScreenshotListening":
stopListening()
result("Listening stopped")
default:
result(FlutterMethodNotImplemented)
}
}
private func shotOff() {
IOSNoScreenshotPlugin.preventScreenShot = IOSNoScreenshotPlugin.DISABLESCREENSHOT
screenProtectorKit?.enabledPreventScreenshot()
persistState()
}
private func shotOn() {
IOSNoScreenshotPlugin.preventScreenShot = IOSNoScreenshotPlugin.ENABLESCREENSHOT
screenProtectorKit?.disablePreventScreenshot()
persistState()
}
private func startListening() {
NotificationCenter.default.addObserver(self, selector: #selector(screenshotDetected), name: UIApplication.userDidTakeScreenshotNotification, object: nil)
persistState()
}
private func stopListening() {
NotificationCenter.default.removeObserver(self, name: UIApplication.userDidTakeScreenshotNotification, object: nil)
persistState()
}
@objc private func screenshotDetected() {
print("Screenshot detected")
updateSharedPreferencesState(IOSNoScreenshotPlugin.screenshotPathPlaceholder)
}
private func updateScreenshotState(isScreenshotBlocked: Bool) {
if isScreenshotBlocked {
screenProtectorKit?.enabledPreventScreenshot()
} else {
screenProtectorKit?.disablePreventScreenshot()
}
}
private func updateSharedPreferencesState(_ screenshotData: String) {
let map: [String: Any] = [
"is_screenshot_on": IOSNoScreenshotPlugin.preventScreenShot,
"screenshot_path": screenshotData,
"was_screenshot_taken": !screenshotData.isEmpty
]
let jsonString = convertMapToJsonString(map)
if lastSharedPreferencesState != jsonString {
hasSharedPreferencesChanged = true
lastSharedPreferencesState = jsonString
}
}
private func convertMapToJsonString(_ map: [String: Any]) -> String {
if let jsonData = try? JSONSerialization.data(withJSONObject: map, options: .prettyPrinted) {
return String(data: jsonData, encoding: .utf8) ?? ""
}
return ""
}
public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
eventSink = events
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.screenshotStream()
}
return nil
}
public func onCancel(withArguments arguments: Any?) -> FlutterError? {
eventSink = nil
return nil
}
private func screenshotStream() {
if hasSharedPreferencesChanged {
eventSink?(lastSharedPreferencesState)
hasSharedPreferencesChanged = false
}
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.screenshotStream()
}
}
deinit {
screenProtectorKit?.removeAllObserver()
}
}