Here's the problem:
There are two UIViewControllers: "WelcomeScreen" and, for example, "FailScreen".
There is a Camera Access Request on the first one.
User taps "Don't allow" and FailScreen opens. ...And crashes.
Code:
AVCaptureDevice.requestAccess(for: .video) { (answer: Bool) in
print("Camera access request.")
if answer {
print("Camera access autorized.")
// Continue to Notifications Request...
}
else {
print("Camera access denied.")
self.present(FailureViewController(), animated: true, completion: nil)
}
Console:
Camera access denied.
libc++abi.dylib: terminating with uncaught exception of type NSException
Transition to other ViewController crashes in the same way after Notifications Request (right next to Camera Access Request).
I'm noob. :)
I tried present(VC), show(VC), push(VC). Result is the same.
I'm not using Storyboards. I do everything programmatically.
Yes, I can show FailScreen on the same ViewController, but what about other options to avoid this error?
Can someone tell me, how to fix it? Thank You.
I hope this will help you.
First you should added value for Privacy - Camera Usage Description key in Info.plist and understand below code
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { (success) in
if success {
print("The user granted permission")
} else {
print("put up an alert telling the user the camera is not available")
DispatchQueue.main.async(execute: { () -> Void in
let ac = UIAlertController(title: "Camera Error", message: "For some reason, the camera in this device is not accepting your authorization. Check with your device supplier.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
self.present(ac, animated: true, completion: nil)
})//back on main queue block
}//if success
})//requestAccessForMediaType block
}//switch
} else {//if device has a camera
let ac = UIAlertController(title: "Source not available.", message: "The camera is not available.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
present(ac, animated: true, completion: nil)
}//if camera is no else
}
Related
After requesting face id permission for an application , we get the apple alert that allow the user to grant or deny the use of this technologie .
My question is :
If the user deny the use of face id , is there any solution to request it again without uninstalling the application .
You can request it again, but not in the same way as the first time. What you can do is when you request for Face ID, you should check on the authorization status, which can either be notDetermined, authorized, denied or restricted.
In the case that it is notDetermined you can bring up the request access that you are already doing, and if it is denied you can give the user the option to go to Settings -> YourAppName to give FaceID access to your app.
Here is an example taken from the following answer: Reference Question
It is for Camera Access but you should be able to apply it to FaceID pretty simply.
#IBAction func goToCamera()
{
let status = AVCaptureDevice.authorizationStatus(for: AVMediaType.video)
switch (status) {
case .authorized:
self.popCamera()
case .notDetermined:
AVCaptureDevice.requestAccess(for: AVMediaType.video) { (granted) in
if (granted) {
self.popCamera()
} else {
self.camDenied()
}
}
case .denied:
self.camDenied()
case .restricted:
let alert = UIAlertController(title: "Restricted",
message: "You've been restricted from using the camera on this device. Without camera access this feature won't work. Please contact the device owner so they can give you access.",
preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alert.addAction(okAction)
self.present(alert, animated: true, completion: nil)
}
}
Then in the camDenied function:
func camDenied() {
DispatchQueue.main.async {
var alertText = "It looks like your privacy settings are preventing us from accessing your camera to do barcode scanning. You can fix this by doing the following:\n\n1. Close this app.\n\n2. Open the Settings app.\n\n3. Scroll to the bottom and select this app in the list.\n\n4. Turn the Camera on.\n\n5. Open this app and try again."
var alertButton = "OK"
var goAction = UIAlertAction(title: alertButton, style: .default, handler: nil)
if UIApplication.shared.canOpenURL(URL(string: UIApplicationOpenSettingsURLString)!) {
alertText = "It looks like your privacy settings are preventing us from accessing your camera to do barcode scanning. You can fix this by doing the following:\n\n1. Touch the Go button below to open the Settings app.\n\n2. Turn the Camera on.\n\n3. Open this app and try again."
alertButton = "Go"
goAction = UIAlertAction(title: alertButton, style: .default, handler: {(alert: UIAlertAction!) -> Void in
UIApplication.shared.open(URL(string: UIApplicationOpenSettingsURLString)!, options: [:], completionHandler: nil)
})
}
let alert = UIAlertController(title: "Error", message: alertText, preferredStyle: .alert)
alert.addAction(goAction)
self.present(alert, animated: true, completion: nil)
}
}
I have a button that when tap on it I have to check microphone permission.
For this reason I done this:
public func askMicrophoneAuthorization()
{
recordingSession = AVAudioSession.sharedInstance()
recordingSession.requestRecordPermission() { [unowned self] allowed in
DispatchQueue.main.async {
if allowed
{
self.goToNextStep()
} else
{
self.denied()
}
}
}
}
my problem is this: when I tap on button and askMicrophoneAuthorization method is called, if its the first time that I ask the permission, the microphone system alert, with text inserted in plist file, shows and I can denied or not the permission. If I deny the permission and then I re-tap on button method self.denied() is executed and I dont see the microphone system alert.
Is it possibile to re-show the system-alert?
It's not possible to show the system alert if the user has already denied.
The best you can do is to check the permission and if they're denied show an alert with a button that opens the app settings.
func askPermissionIfNeeded() {
switch AVAudioSession.sharedInstance().recordPermission {
case undetermined:
askMicrophoneAuthorization()
case denied:
let alert = UIAlertController(title: "Error", message: "Please allow microphone usage from settings", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Open settings", style: .default, handler: { action in
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
present(alert, animated: true, completion: nil)
case granted:
goToNextStep()
}
}
I am requesting users to accept access to both photo library and camera use. I would like to be able to handle the case for when a user does not accept, but I am having issues doing so. Here is the code for when I check user permission:
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo) { granted in
if granted {
if(!self.captureSession.isRunning){
self.setupCustomCamera()
}
} else {
self.takePhotoButton.alpha = 0.5
self.takePhotoButton.isEnabled = false
self.showNeedAccessMessage()
}
}
And my showNeedAccessMessage() as follows:
func showNeedAccessMessage() {
let alert = UIAlertController(title: "Camera Settings", message: "Please adjust your device settings to grant access to camera use.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: { (action: UIAlertAction) -> Void in
self.dismiss(animated: true, completion: nil)
}))
show(alert, sender: nil)
}
The issue here is that when the granted case is not met, I would like to show an alert. Instead of my alert showing, my application attempts to open the 'Image Settings' page, which shows up as follows:
Is there a default handling for this case? If so, any ideas how I would go about fixing the black 'Image Settings' screen?
Thank you in advance!
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { (granted :Bool) -> Void in
if granted == true
{
// User granted
}
else
{
let alert = UIAlertController(title: "Error", message: "This app is not authorized to use Camera.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Setting", style: .default, handler: { (_) in
DispatchQueue.main.async {
if let settingsURL = URL(string: UIApplicationOpenSettingsURLString) {
UIApplication.shared.openURL(settingsURL)
}
}
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
return
}
});
This iOS app uses the camera for an image to be placed in the detail view of a master detail app. When the app is installed and the take photo action is requested for the first time, the app crashes. As seen in the code, access is requested and the user is presented with an alert requesting access. Once granted the completion handler reports success and the app crashes. If I restart the app (without reinstalling it), the camera performs as expected and continues to do so. Removing the app from the iPhone and reinstalling always produces exactly the same result.
The console output:
AVAuthorizationStatus is NotDetermined.
The user granted permission.
libc++abi.dylib: terminating with uncaught exception of type NSException
Any help would be appreciated. iOS 10, Xcode 8, Swift 3
Edit: It crashes in the AVCaptureRequest. If I comment out the AVCaptureRequest the app does not crash (of course with no photo).
#IBAction func takeDrugPhoto(_ sender: UIButton) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera) {
let authStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo)
switch authStatus {
case AVAuthorizationStatus.authorized:
print("AVAuthorizationStatus is Authorized")
.....bunch of code here......
case AVAuthorizationStatus.denied:
print("AVAuthorizationStatus is Denied")
.....some code here .....
case AVAuthorizationStatus.notDetermined:
print("AVAuthorizationStatus is NotDetermined")
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { (success) in
if success {
print("The user granted permission")
} else {
print("put up an alert telling the user the camera is not available")
DispatchQueue.main.async(execute: { () -> Void in
let ac = UIAlertController(title: "Camera Error", message: "For some reason, the camera in this device is not accepting your authorization. Check with your device supplier.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
self.present(ac, animated: true, completion: nil)
})//back on main queue block
}//if success
})//requestAccessForMediaType block
}//switch
} else {//if device has a camera
let ac = UIAlertController(title: "Source not available.", message: "The camera is not available.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
present(ac, animated: true, completion: nil)
}//if camera is no else
}//takeDrugPhoto
From the trace:
When you seek user permission through an AVCaptureDevice.requestAccess request, iOS presents an alert dialog that incorporates the message you create in the info.plist. When the user grants permission, it appears as thought iOS then treats the app as if it were returning from the background (even though it does not disappear). That was my issue. I had structured a login sequence to activate whenever the app returns from the background as part of the security. I had disabled that interface for testing - hence the failures. I hope others will find this useful.
In my application I used camera implementation in that if the user enter very first means that time they choose allow means they have to access camera and photo library in entire application, if it is chosen denied means the user cannot access the camera so that time we need to change camera and photo library in settings.After that we have to access the camera in my case it is not working properly, anyone helps me, much appreciated.
You can check first whether camera permission is allowed or not. If not then you can navigate to settings screen & ask user for permission.
override func viewDidLoad() {
super.viewDidLoad()
checkCameraPermission()
}
func checkCameraPermission() {
let cameraMediaType = AVMediaTypeVideo
AVCaptureDevice.requestAccess(forMediaType: cameraMediaType) { granted in
if granted {
//Do operation
print("Granted access for camera")
self.setCamera()
} else {
self.noCameraFound()
print("Denied access for camera ")
}
}
}
func noCameraFound(){
let alert = UIAlertController(title: "AppName", message: "Please allow camera access in phone settings", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Back", style: UIAlertActionStyle.cancel, handler: {(action:UIAlertAction) in
}));
alert.addAction(UIAlertAction(title: "Open setting ", style: UIAlertActionStyle.default, handler: {(action:UIAlertAction) in
UIApplication.shared.open(NSURL(string:UIApplicationOpenSettingsURLString)! as URL, options: [:], completionHandler: nil)
}));
self.present(alert, animated: true, completion: nil)
}