diff --git a/packages/camera/camera_avfoundation/CHANGELOG.md b/packages/camera/camera_avfoundation/CHANGELOG.md index 1f2d8615df1..ec42436d936 100644 --- a/packages/camera/camera_avfoundation/CHANGELOG.md +++ b/packages/camera/camera_avfoundation/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.22+8 + +* Migrates `FLTPermissionServicing` and `FLTCameraPermissionManager` classes to Swift. + ## 0.9.22+7 * Migrates `FLTCaptureConnection`, `FLTCaptureDeviceFormat` and `FLTAssetWriter` classes to Swift. diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/AvailableCamerasTests.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/AvailableCamerasTests.swift index 50eb2f62ab1..13038b6bf48 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/AvailableCamerasTests.swift +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/AvailableCamerasTests.swift @@ -20,7 +20,7 @@ final class AvailableCamerasTest: XCTestCase { messenger: MockFlutterBinaryMessenger(), globalAPI: MockGlobalEventApi(), deviceDiscoverer: deviceDiscoverer, - permissionManager: MockFLTCameraPermissionManager(), + permissionManager: MockCameraPermissionManager(), deviceFactory: { _ in MockCaptureDevice() }, captureSessionFactory: { MockCaptureSession() }, captureDeviceInputFactory: MockCaptureDeviceInputFactory(), diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraInitRaceConditionsTests.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraInitRaceConditionsTests.swift index 3f60374101b..533b385755d 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraInitRaceConditionsTests.swift +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraInitRaceConditionsTests.swift @@ -20,7 +20,7 @@ final class CameraInitRaceConditionsTests: XCTestCase { messenger: MockFlutterBinaryMessenger(), globalAPI: MockGlobalEventApi(), deviceDiscoverer: MockCameraDeviceDiscoverer(), - permissionManager: MockFLTCameraPermissionManager(), + permissionManager: MockCameraPermissionManager(), deviceFactory: { _ in MockCaptureDevice() }, captureSessionFactory: { MockCaptureSession() }, captureDeviceInputFactory: MockCaptureDeviceInputFactory(), diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraMethodChannelTests.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraMethodChannelTests.swift index 3a46585ae3b..d55429a7c42 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraMethodChannelTests.swift +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraMethodChannelTests.swift @@ -19,7 +19,7 @@ final class CameraMethodChannelTests: XCTestCase { messenger: MockFlutterBinaryMessenger(), globalAPI: MockGlobalEventApi(), deviceDiscoverer: MockCameraDeviceDiscoverer(), - permissionManager: MockFLTCameraPermissionManager(), + permissionManager: MockCameraPermissionManager(), deviceFactory: { _ in MockCaptureDevice() }, captureSessionFactory: { session }, captureDeviceInputFactory: MockCaptureDeviceInputFactory(), diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraOrientationTests.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraOrientationTests.swift index 23d00a86e15..528e8caea1f 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraOrientationTests.swift +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraOrientationTests.swift @@ -41,7 +41,7 @@ final class CameraOrientationTests: XCTestCase { messenger: MockFlutterBinaryMessenger(), globalAPI: mockEventAPI, deviceDiscoverer: mockDeviceDiscoverer, - permissionManager: MockFLTCameraPermissionManager(), + permissionManager: MockCameraPermissionManager(), deviceFactory: { _ in mockDevice }, captureSessionFactory: { MockCaptureSession() }, captureDeviceInputFactory: MockCaptureDeviceInputFactory(), @@ -130,7 +130,7 @@ final class CameraOrientationTests: XCTestCase { messenger: MockFlutterBinaryMessenger(), globalAPI: mockEventAPI, deviceDiscoverer: mockDeviceDiscoverer, - permissionManager: MockFLTCameraPermissionManager(), + permissionManager: MockCameraPermissionManager(), deviceFactory: { _ in weakDevice! }, captureSessionFactory: { MockCaptureSession() }, captureDeviceInputFactory: MockCaptureDeviceInputFactory(), diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPermissionTests.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPermissionTests.swift index 0709b8a3c0d..87460e50000 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPermissionTests.swift +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPermissionTests.swift @@ -12,23 +12,23 @@ import XCTest import camera_avfoundation_objc #endif -private final class MockPermissionService: NSObject, FLTPermissionServicing { +private final class MockPermissionService: NSObject, PermissionServicing { var authorizationStatusStub: ((AVMediaType) -> AVAuthorizationStatus)? - var requestAccessStub: ((AVMediaType, @escaping (Bool) -> Void) -> Void)? + var requestAccessStub: ((AVMediaType, @escaping @Sendable (Bool) -> Void) -> Void)? func authorizationStatus(for mediaType: AVMediaType) -> AVAuthorizationStatus { return authorizationStatusStub?(mediaType) ?? .notDetermined } - func requestAccess(for mediaType: AVMediaType, completion: @escaping (Bool) -> Void) { + func requestAccess(for mediaType: AVMediaType, completion: @escaping @Sendable (Bool) -> Void) { requestAccessStub?(mediaType, completion) } } final class CameraPermissionManagerTests: XCTestCase { - private func createSutAndMocks() -> (FLTCameraPermissionManager, MockPermissionService) { + private func createSutAndMocks() -> (CameraPermissionManager, MockPermissionService) { let mockPermissionService = MockPermissionService() - let permissionManager = FLTCameraPermissionManager(permissionService: mockPermissionService) + let permissionManager = CameraPermissionManager(permissionService: mockPermissionService) return (permissionManager, mockPermissionService) } diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPluginCreateCameraTests.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPluginCreateCameraTests.swift index e7f333153db..79abd5ccdbc 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPluginCreateCameraTests.swift +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPluginCreateCameraTests.swift @@ -13,9 +13,9 @@ import XCTest final class CameraPluginCreateCameraTests: XCTestCase { private func createCameraPlugin() -> ( - CameraPlugin, MockFLTCameraPermissionManager, MockCaptureSession + CameraPlugin, MockCameraPermissionManager, MockCaptureSession ) { - let mockPermissionManager = MockFLTCameraPermissionManager() + let mockPermissionManager = MockCameraPermissionManager() let mockCaptureSession = MockCaptureSession() let cameraPlugin = CameraPlugin( @@ -41,13 +41,13 @@ final class CameraPluginCreateCameraTests: XCTestCase { mockPermissionManager.requestCameraPermissionStub = { completion in requestCameraPermissionCalled = true // Permission is granted - completion?(nil) + completion(nil) } var requestAudioPermissionCalled = false mockPermissionManager.requestAudioPermissionStub = { completion in requestAudioPermissionCalled = true // Permission is granted - completion?(nil) + completion(nil) } cameraPlugin.createCamera( @@ -76,13 +76,13 @@ final class CameraPluginCreateCameraTests: XCTestCase { mockPermissionManager.requestCameraPermissionStub = { completion in requestCameraPermissionCalled = true // Permission is granted - completion?(nil) + completion(nil) } var requestAudioPermissionCalled = false mockPermissionManager.requestAudioPermissionStub = { completion in requestAudioPermissionCalled = true // Permission is granted - completion?(nil) + completion(nil) } cameraPlugin.createCamera( @@ -109,11 +109,11 @@ final class CameraPluginCreateCameraTests: XCTestCase { mockPermissionManager.requestCameraPermissionStub = { completion in // Permission is granted - completion?(nil) + completion(nil) } mockPermissionManager.requestAudioPermissionStub = { completion in // Permission is granted - completion?(nil) + completion(nil) } mockCaptureSession.canSetSessionPresetStub = { _ in true } diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPluginDelegatingMethodTests.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPluginDelegatingMethodTests.swift index 31fad0c008a..14db9a7d478 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPluginDelegatingMethodTests.swift +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPluginDelegatingMethodTests.swift @@ -21,7 +21,7 @@ final class CameraPluginDelegatingMethodTests: XCTestCase { messenger: MockFlutterBinaryMessenger(), globalAPI: MockGlobalEventApi(), deviceDiscoverer: MockCameraDeviceDiscoverer(), - permissionManager: MockFLTCameraPermissionManager(), + permissionManager: MockCameraPermissionManager(), deviceFactory: { _ in MockCaptureDevice() }, captureSessionFactory: { MockCaptureSession() }, captureDeviceInputFactory: MockCaptureDeviceInputFactory(), diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPluginInitializeCameraTests.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPluginInitializeCameraTests.swift index 1eca0ec8c69..3006d0375e1 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPluginInitializeCameraTests.swift +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPluginInitializeCameraTests.swift @@ -24,7 +24,7 @@ final class CameraPluginInitializeCameraTests: XCTestCase { messenger: MockFlutterBinaryMessenger(), globalAPI: mockGlobalEventApi, deviceDiscoverer: MockCameraDeviceDiscoverer(), - permissionManager: MockFLTCameraPermissionManager(), + permissionManager: MockCameraPermissionManager(), deviceFactory: { _ in MockCaptureDevice() }, captureSessionFactory: { MockCaptureSession() }, captureDeviceInputFactory: MockCaptureDeviceInputFactory(), diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraSettingsTests.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraSettingsTests.swift index ce2ac065176..9e40743dadd 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraSettingsTests.swift +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraSettingsTests.swift @@ -161,7 +161,7 @@ final class CameraSettingsTests: XCTestCase { messenger: MockFlutterBinaryMessenger(), globalAPI: MockGlobalEventApi(), deviceDiscoverer: MockCameraDeviceDiscoverer(), - permissionManager: MockFLTCameraPermissionManager(), + permissionManager: MockCameraPermissionManager(), deviceFactory: { _ in mockDevice }, captureSessionFactory: { mockSession }, captureDeviceInputFactory: MockCaptureDeviceInputFactory(), diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockFLTCameraPermissionManager.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockFLTCameraPermissionManager.swift index 6288389cd92..c4d213566ae 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockFLTCameraPermissionManager.swift +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockFLTCameraPermissionManager.swift @@ -2,22 +2,34 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import camera_avfoundation +@testable import camera_avfoundation // Import Objective-C part of the implementation when SwiftPM is used. #if canImport(camera_avfoundation_objc) import camera_avfoundation_objc #endif -final class MockFLTCameraPermissionManager: FLTCameraPermissionManager { - var requestCameraPermissionStub: ((((FlutterError?) -> Void)?) -> Void)? - var requestAudioPermissionStub: ((((FlutterError?) -> Void)?) -> Void)? +final class MockCameraPermissionManager: CameraPermissionManager { + var requestCameraPermissionStub: ((@escaping (FlutterError?) -> Void) -> Void)? + var requestAudioPermissionStub: ((@escaping (FlutterError?) -> Void) -> Void)? - override func requestCameraPermission(completionHandler: ((FlutterError?) -> Void)?) { - requestCameraPermissionStub?(completionHandler) + init() { + super.init(permissionService: DefaultPermissionService()) } - override func requestAudioPermission(completionHandler: ((FlutterError?) -> Void)?) { - requestAudioPermissionStub?(completionHandler) + override func requestCameraPermission(completionHandler: @escaping (FlutterError?) -> Void) { + if let stub = requestCameraPermissionStub { + stub(completionHandler) + } else { + super.requestCameraPermission(completionHandler: completionHandler) + } + } + + override func requestAudioPermission(completionHandler: @escaping (FlutterError?) -> Void) { + if let stub = requestAudioPermissionStub { + stub(completionHandler) + } else { + super.requestAudioPermission(completionHandler: completionHandler) + } } } diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/CameraPermissionManager.swift b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/CameraPermissionManager.swift new file mode 100644 index 00000000000..4930c10a27b --- /dev/null +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/CameraPermissionManager.swift @@ -0,0 +1,124 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import AVFoundation +import Flutter + +/// Completion handler for camera permission requests. +typealias CameraPermissionRequestCompletionHandler = (FlutterError?) -> Void + +/// Manages camera and audio permission requests. +class CameraPermissionManager: NSObject { + let permissionService: PermissionServicing + + init(permissionService: PermissionServicing) { + self.permissionService = permissionService + super.init() + } + + /// Requests camera access permission. + /// + /// If it is the first time requesting camera access, a permission dialog will show up on the + /// screen. Otherwise AVFoundation simply returns the user's previous choice, and in this case the + /// user will have to update the choice in Settings app. + /// + /// @param handler if access permission is (or was previously) granted, completion handler will be + /// called without error; Otherwise completion handler will be called with error. Handler can be + /// called on an arbitrary dispatch queue. + func requestCameraPermission( + completionHandler handler: @escaping CameraPermissionRequestCompletionHandler + ) { + requestPermission(forAudio: false, handler: handler) + } + + /// Requests audio access permission. + /// + /// If it is the first time requesting audio access, a permission dialog will show up on the + /// screen. Otherwise AVFoundation simply returns the user's previous choice, and in this case the + /// user will have to update the choice in Settings app. + /// + /// @param handler if access permission is (or was previously) granted, completion handler will be + /// called without error; Otherwise completion handler will be called with error. Handler can be + /// called on an arbitrary dispatch queue. + func requestAudioPermission( + completionHandler handler: @escaping CameraPermissionRequestCompletionHandler + ) { + requestPermission(forAudio: true, handler: handler) + } + + private func requestPermission( + forAudio: Bool, + handler: @escaping CameraPermissionRequestCompletionHandler + ) { + let mediaType: AVMediaType = forAudio ? .audio : .video + + switch permissionService.authorizationStatus(for: mediaType) { + case .authorized: + handler(nil) + + case .denied: + let flutterError: FlutterError + if forAudio { + flutterError = FlutterError( + code: "AudioAccessDeniedWithoutPrompt", + message: + "User has previously denied the audio access request. Go to Settings to enable audio access.", + details: nil + ) + } else { + flutterError = FlutterError( + code: "CameraAccessDeniedWithoutPrompt", + message: + "User has previously denied the camera access request. Go to Settings to enable camera access.", + details: nil + ) + } + handler(flutterError) + + case .restricted: + let flutterError: FlutterError + if forAudio { + flutterError = FlutterError( + code: "AudioAccessRestricted", + message: "Audio access is restricted.", + details: nil + ) + } else { + flutterError = FlutterError( + code: "CameraAccessRestricted", + message: "Camera access is restricted.", + details: nil + ) + } + handler(flutterError) + + case .notDetermined: + permissionService.requestAccess(for: mediaType) { granted in + // handler can be invoked on an arbitrary dispatch queue. + if granted { + handler(nil) + } else { + let flutterError: FlutterError + if forAudio { + flutterError = FlutterError( + code: "AudioAccessDenied", + message: "User denied the audio access request.", + details: nil + ) + } else { + flutterError = FlutterError( + code: "CameraAccessDenied", + message: "User denied the camera access request.", + details: nil + ) + } + handler(flutterError) + } + } + + @unknown default: + assertionFailure("Unknown authorization status") + } + } +} diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/CameraPlugin.swift b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/CameraPlugin.swift index 75687209f9e..de0e78d8222 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/CameraPlugin.swift +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/CameraPlugin.swift @@ -15,7 +15,7 @@ public final class CameraPlugin: NSObject, FlutterPlugin { private let messenger: FlutterBinaryMessenger private let globalEventAPI: FCPCameraGlobalEventApi private let deviceDiscoverer: CameraDeviceDiscoverer - private let permissionManager: FLTCameraPermissionManager + private let permissionManager: CameraPermissionManager private let captureDeviceFactory: VideoCaptureDeviceFactory private let captureSessionFactory: CaptureSessionFactory private let captureDeviceInputFactory: CaptureDeviceInputFactory @@ -32,8 +32,8 @@ public final class CameraPlugin: NSObject, FlutterPlugin { messenger: registrar.messenger(), globalAPI: FCPCameraGlobalEventApi(binaryMessenger: registrar.messenger()), deviceDiscoverer: DefaultCameraDeviceDiscoverer(), - permissionManager: FLTCameraPermissionManager( - permissionService: FLTDefaultPermissionService()), + permissionManager: CameraPermissionManager( + permissionService: DefaultPermissionService()), deviceFactory: { name in // TODO(RobertOdrowaz) Implement better error handling and remove non-null assertion AVCaptureDevice(uniqueID: name)! @@ -51,7 +51,7 @@ public final class CameraPlugin: NSObject, FlutterPlugin { messenger: FlutterBinaryMessenger, globalAPI: FCPCameraGlobalEventApi, deviceDiscoverer: CameraDeviceDiscoverer, - permissionManager: FLTCameraPermissionManager, + permissionManager: CameraPermissionManager, deviceFactory: @escaping VideoCaptureDeviceFactory, captureSessionFactory: @escaping CaptureSessionFactory, captureDeviceInputFactory: CaptureDeviceInputFactory, diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/PermissionServicing.swift b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/PermissionServicing.swift new file mode 100644 index 00000000000..b0c72d9bfea --- /dev/null +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/PermissionServicing.swift @@ -0,0 +1,29 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import AVFoundation + +/// A protocol for permission-related operations on AVCaptureDevice. +/// It exists to allow mocking permission checks in tests. +protocol PermissionServicing: NSObjectProtocol { + func authorizationStatus(for mediaType: AVMediaType) -> AVAuthorizationStatus + func requestAccess( + for mediaType: AVMediaType, + completion handler: @escaping @Sendable (Bool) -> Void + ) +} + +/// Default implementation of PermissionServicing that forwards calls to AVCaptureDevice. +class DefaultPermissionService: NSObject, PermissionServicing { + func authorizationStatus(for mediaType: AVMediaType) -> AVAuthorizationStatus { + return AVCaptureDevice.authorizationStatus(for: mediaType) + } + + func requestAccess( + for mediaType: AVMediaType, + completion handler: @escaping @Sendable (Bool) -> Void + ) { + AVCaptureDevice.requestAccess(for: mediaType, completionHandler: handler) + } +} diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/FLTCameraPermissionManager.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/FLTCameraPermissionManager.m deleted file mode 100644 index 0f60ae2a475..00000000000 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/FLTCameraPermissionManager.m +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import AVFoundation; -#import "./include/camera_avfoundation/FLTCameraPermissionManager.h" -#import "./include/camera_avfoundation/FLTPermissionServicing.h" - -@implementation FLTCameraPermissionManager - -- (instancetype)initWithPermissionService:(id)service { - self = [super init]; - if (self) { - _permissionService = service ?: [[FLTDefaultPermissionService alloc] init]; - } - return self; -} - -- (void)requestAudioPermissionWithCompletionHandler: - (__strong FLTCameraPermissionRequestCompletionHandler)handler { - [self requestPermissionForAudio:YES handler:handler]; -} - -- (void)requestCameraPermissionWithCompletionHandler: - (__strong FLTCameraPermissionRequestCompletionHandler)handler { - [self requestPermissionForAudio:NO handler:handler]; -} - -- (void)requestPermissionForAudio:(BOOL)forAudio - handler:(FLTCameraPermissionRequestCompletionHandler)handler { - AVMediaType mediaType; - if (forAudio) { - mediaType = AVMediaTypeAudio; - } else { - mediaType = AVMediaTypeVideo; - } - - switch ([_permissionService authorizationStatusForMediaType:mediaType]) { - case AVAuthorizationStatusAuthorized: - handler(nil); - break; - case AVAuthorizationStatusDenied: { - FlutterError *flutterError; - if (forAudio) { - flutterError = - [FlutterError errorWithCode:@"AudioAccessDeniedWithoutPrompt" - message:@"User has previously denied the audio access request. " - @"Go to Settings to enable audio access." - details:nil]; - } else { - flutterError = - [FlutterError errorWithCode:@"CameraAccessDeniedWithoutPrompt" - message:@"User has previously denied the camera access request. " - @"Go to Settings to enable camera access." - details:nil]; - } - handler(flutterError); - break; - } - case AVAuthorizationStatusRestricted: { - FlutterError *flutterError; - if (forAudio) { - flutterError = [FlutterError errorWithCode:@"AudioAccessRestricted" - message:@"Audio access is restricted." - details:nil]; - } else { - flutterError = [FlutterError errorWithCode:@"CameraAccessRestricted" - message:@"Camera access is restricted." - details:nil]; - } - handler(flutterError); - break; - } - case AVAuthorizationStatusNotDetermined: { - [_permissionService requestAccessForMediaType:mediaType - completionHandler:^(BOOL granted) { - // handler can be invoked on an arbitrary dispatch queue. - if (granted) { - handler(nil); - } else { - FlutterError *flutterError; - if (forAudio) { - flutterError = [FlutterError - errorWithCode:@"AudioAccessDenied" - message:@"User denied the audio access request." - details:nil]; - } else { - flutterError = [FlutterError - errorWithCode:@"CameraAccessDenied" - message:@"User denied the camera access request." - details:nil]; - } - handler(flutterError); - } - }]; - break; - } - } -} - -@end diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/FLTPermissionServicing.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/FLTPermissionServicing.m deleted file mode 100644 index 83126c204ee..00000000000 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/FLTPermissionServicing.m +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "./include/camera_avfoundation/FLTPermissionServicing.h" - -@implementation FLTDefaultPermissionService -- (AVAuthorizationStatus)authorizationStatusForMediaType:(AVMediaType)mediaType { - return [AVCaptureDevice authorizationStatusForMediaType:mediaType]; -} - -- (void)requestAccessForMediaType:(AVMediaType)mediaType - completionHandler:(void (^)(BOOL granted))handler { - [AVCaptureDevice requestAccessForMediaType:mediaType completionHandler:handler]; -} -@end diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/include/camera_avfoundation/FLTCameraPermissionManager.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/include/camera_avfoundation/FLTCameraPermissionManager.h deleted file mode 100644 index 7728ef9c191..00000000000 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/include/camera_avfoundation/FLTCameraPermissionManager.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import Foundation; -#import - -#import "FLTPermissionServicing.h" - -NS_ASSUME_NONNULL_BEGIN - -typedef void (^FLTCameraPermissionRequestCompletionHandler)(FlutterError *_Nullable); - -@interface FLTCameraPermissionManager : NSObject -@property(nonatomic, strong) id permissionService; - -- (instancetype)initWithPermissionService:(id)service; - -/// Requests camera access permission. -/// -/// If it is the first time requesting camera access, a permission dialog will show up on the -/// screen. Otherwise AVFoundation simply returns the user's previous choice, and in this case the -/// user will have to update the choice in Settings app. -/// -/// @param handler if access permission is (or was previously) granted, completion handler will be -/// called without error; Otherwise completion handler will be called with error. Handler can be -/// called on an arbitrary dispatch queue. -- (void)requestCameraPermissionWithCompletionHandler: - (FLTCameraPermissionRequestCompletionHandler)handler; - -/// Requests audio access permission. -/// -/// If it is the first time requesting audio access, a permission dialog will show up on the -/// screen. Otherwise AVFoundation simply returns the user's previous choice, and in this case the -/// user will have to update the choice in Settings app. -/// -/// @param handler if access permission is (or was previously) granted, completion handler will be -/// called without error; Otherwise completion handler will be called with error. Handler can be -/// called on an arbitrary dispatch queue. -- (void)requestAudioPermissionWithCompletionHandler: - (FLTCameraPermissionRequestCompletionHandler)handler; - -@end - -NS_ASSUME_NONNULL_END diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/include/camera_avfoundation/FLTPermissionServicing.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/include/camera_avfoundation/FLTPermissionServicing.h deleted file mode 100644 index 2a377fa2c02..00000000000 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/include/camera_avfoundation/FLTPermissionServicing.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import AVFoundation; -@import Foundation; - -NS_ASSUME_NONNULL_BEGIN - -@protocol FLTPermissionServicing -- (AVAuthorizationStatus)authorizationStatusForMediaType:(AVMediaType)mediaType - NS_SWIFT_NAME(authorizationStatus(for:)); -- (void)requestAccessForMediaType:(AVMediaType)mediaType - completionHandler:(void (^)(BOOL granted))handler - NS_SWIFT_NAME(requestAccess(for:completion:)); -@end - -@interface FLTDefaultPermissionService : NSObject -@end - -NS_ASSUME_NONNULL_END diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/include/camera_avfoundation/camera_avfoundation.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/include/camera_avfoundation/camera_avfoundation.h index 77fa73867ab..e220dc6bf8b 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/include/camera_avfoundation/camera_avfoundation.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/include/camera_avfoundation/camera_avfoundation.h @@ -2,6 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "FLTCameraPermissionManager.h" #import "QueueUtils.h" #import "messages.g.h" diff --git a/packages/camera/camera_avfoundation/pubspec.yaml b/packages/camera/camera_avfoundation/pubspec.yaml index 136bd30317e..801af16c095 100644 --- a/packages/camera/camera_avfoundation/pubspec.yaml +++ b/packages/camera/camera_avfoundation/pubspec.yaml @@ -2,7 +2,7 @@ name: camera_avfoundation description: iOS implementation of the camera plugin. repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_avfoundation issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.9.22+7 +version: 0.9.22+8 environment: sdk: ^3.9.0