camera: requestAudioPermission — in-app prompt first, settings on permanent denial
Banner-tap entry point that shows the system mic prompt when the OS will still surface one, and deep-links to Settings only on permanent denial. Fixes the fresh-install trap where the mic entry isn't in the Privacy pane until requestAccess has fired at least once. Android tracks the first-asked state in SharedPreferences because shouldShowRequestPermissionRationale returns false in two observationally identical states (never asked vs permanently denied). The existing initialize() request path writes the flag too, so a banner tap after a record-then-deny correctly routes to Settings. Refactored Android pendingPermission into PendingPermission(primary, kind, cb) so audio-only requests check RECORD_AUDIO results instead of always checking CAMERA.
This commit is contained in:
@@ -272,6 +272,27 @@ public class CameraPlugin: NSObject, NativePlugin, FlutterStreamHandler {
|
||||
let granted = AVCaptureDevice.authorizationStatus(for: .audio) == .authorized
|
||||
result(granted)
|
||||
|
||||
case "requestAudioPermission":
|
||||
// On `.notDetermined` the system can still show the in-app
|
||||
// prompt; on `.denied`/`.restricted` it can't — and on a
|
||||
// fresh install the mic entry isn't in the Privacy pane
|
||||
// until requestAccess has fired at least once, so the
|
||||
// settings fallback only makes sense after first prompt.
|
||||
let status = AVCaptureDevice.authorizationStatus(for: .audio)
|
||||
switch status {
|
||||
case .authorized:
|
||||
result(true)
|
||||
case .notDetermined:
|
||||
AVCaptureDevice.requestAccess(for: .audio) { granted in
|
||||
DispatchQueue.main.async { result(granted) }
|
||||
}
|
||||
default:
|
||||
DispatchQueue.main.async {
|
||||
CameraSettings.openAppSettings()
|
||||
result(false)
|
||||
}
|
||||
}
|
||||
|
||||
case "openSettings":
|
||||
DispatchQueue.main.async {
|
||||
// Per-platform helper: iOS opens app-specific Settings
|
||||
|
||||
Reference in New Issue
Block a user