I want to stop the ongoing screen recording in iOS which user has started using the Control Center. For stopping the recording, the user would click on a button inside Flutter app. Tried using ReplayKit to stop screen recording, as below code:
Environment: Flutter v2.10.5
Challenges faced:
Tested on Simulator and an iPhone, the isScreenRecording bool works, but the stop recording doesn't seem to work.
Any thing wrong here? Or can ReplayKit stop ongoing global recording started from Control Center.
AppDelegate.swift
import UIKit
import Flutter
import MoEngage
import moengage_flutter
import flutter_downloader
import AVFoundation
import Foundation
import ReplayKit
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self
}
var moSDKConfig : MOSDKConfig
let moAppId = ""
if let config = MoEngage.sharedInstance().getDefaultSDKConfiguration() {
moSDKConfig = config
moSDKConfig.moeAppID = moAppId
} else {
moSDKConfig = MOSDKConfig.init(appID: moAppId)
}
moSDKConfig.appGroupID = "group.com.package-name.shared"
moSDKConfig.moeDataCenter = DATA_CENTER_01
MOFlutterInitializer.sharedInstance.initializeWithSDKConfig(
moSDKConfig,
andLaunchOptions: launchOptions
)
FlutterDownloaderPlugin.setPluginRegistrantCallback(registerPlugins)
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let isMicrophoneAvailable = FlutterMethodChannel(name: "package-name/audio_recorder",
binaryMessenger: controller.binaryMessenger)
isMicrophoneAvailable.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in
guard call.method == "isMicrophoneAvailable" else {
result(FlutterMethodNotImplemented)
return
}
self?.isMicrophoneAvailable(result: result)
})
let screenRecording = FlutterMethodChannel(name: "package-name/screen_recording",
binaryMessenger: controller.binaryMessenger)
screenRecording.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
switch call.method {
case "stop_screen_share", "is_screen_share_active":
self?.screenRecordActions(call, result)
default:
result(FlutterMethodNotImplemented)
}
})
GeneratedPluginRegistrant.register(with: self)
// Set your desired minimumBackgroundFetchInterval
let backgroundIntervalInMinutes = 60
UIApplication.shared.setMinimumBackgroundFetchInterval(TimeInterval(60*backgroundIntervalInMinutes))
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func isMicrophoneAvailable(result: FlutterResult) {
if AVAudioSession.sharedInstance().isOtherAudioPlaying == false {
result(Bool(true))
} else {
result(Bool(false))
}
}
// MARK: - Screen Record
private func screenRecordActions(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
switch call.method {
case "stop_screen_share":
RPScreenRecorder.shared().stopCapture( handler: { (error) in
print("stopping recording");
})
case "is_screen_share_active":
let isRecording = RPScreenRecorder.shared().isRecording;
result(isRecording)
default:
print("Not Valid")
}
}
}
private func registerPlugins(registry: FlutterPluginRegistry) {
if (!registry.hasPlugin("FlutterDownloaderPlugin")) {
FlutterDownloaderPlugin.register(with: registry.registrar(forPlugin: "FlutterDownloaderPlugin")!)
}
}
content_protection.dart
part of '../app_extension.dart';
class QContentProtection {
QContentProtection._();
static const platform = MethodChannel('package-name/screen_recording');
final SecureContent _secureContent = SecureContent();
void preventScreenshotAndroid(bool prevent) {
_secureContent.preventScreenshotAndroid(prevent);
}
// Future<void> startRecording() async {
// try {
// await platform.invokeMethod('start_screen_share');
// } catch (e, s) {
// log('[QContentProtection.startRecording] error : $e, $s');
// QAppX.extendedRouter.showNotificationsShade(
// message: e.toString(),
// type: QInAppNotificationType.failure,
// );
// }
// }
Future<void> stopRecording() async {
try {
await platform.invokeMethod('stop_screen_share');
} catch (e, s) {
log('[QContentProtection.stopRecording] error : $e, $s');
QAppX.extendedRouter.showNotificationsShade(
message: e.toString(),
type: QInAppNotificationType.failure,
);
}
}
Future<bool> isScreenRecordingOn() async {
try {
final isScreenRecordingOn = await platform.invokeMethod<bool>('is_screen_share_active');
log('[QContentProtection.isScreenRecordingOn] isScreenRecordingOn : $isScreenRecordingOn');
return isScreenRecordingOn ?? false;
} catch (e, s) {
log('[QContentProtection.isScreenRecordingOn] error : $e, $s');
QAppX.extendedRouter.showNotificationsShade(
message: e.toString(),
type: QInAppNotificationType.failure,
);
return false;
}
}
}
main.dart
onPressed: () {
final isScreenRecordingOn = await QAppX.contentProtection.isScreenRecordingOn();
if (isScreenRecordingOn) {
QAppX.contentProtection.stopRecording();
}
}