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()
}
}
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 want ask permission in the second time in my home controller, can I do it programmatically?
I mean that the user disable it in the first time and I want to allow him another option to get notification.
You´re not allowed to do that. The notification popup will prompt the first time the user opens the application. What you can do is check if the user hasn´t allowed this. Then you could open the settings page (which basically is what you can do in this case):
let isRegisteredForRemoteNotifications = UIApplication.shared.isRegisteredForRemoteNotifications
if !isRegisteredForRemoteNotifications {
UIApplication.shared.open(URL(string: UIApplicationOpenSettingsURLString)!, options: [:], completionHandler: nil)
}
Swift 5.x
let isRegisteredForRemoteNotifications = UIApplication.shared.isRegisteredForRemoteNotifications
if !isRegisteredForRemoteNotifications {
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)
}
This is actually not possible. You only get one shot to prompt them for permissions. This is why most apps will present a custom view to explain why a certain permission is needed. And if the user clicks "yes", then they launch the actual permission alert.
If they have already declined the permission, you'll need to check if app has certain permission and prompt them to go into settings to activate what is needed.
Here's an example of how you can check if they have given permission.
You cannot ask for a permission after the user has chosen to allow it or not. What you can do is check if the permission was not allowed and redirect the user to the app's settings.
How you check for the permission's authorization status depends on the type of service you want to authorize. You can the redirect the user to the settings with the following code:
Swift
UIApplication.shared.open(URL(string: UIApplicationOpenSettingsURLString)!, options: [:], completionHandler: nil)
Objective C
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:#{} completionHandler:nil];
You cannot show the standard popup after the user enabled or refused notifications. In such situation, it is quite common to show an alertController that informs the user about this situation and provide her with a button that navigates to settings:
let alert = UIAlertController(title: "Unable to use notifications",
message: "To enable notifications, go to Settings and enable notifications for this app.",
preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alert.addAction(okAction)
let settingsAction = UIAlertAction(title: "Settings", style: .default, handler: { _ in
// Take the user to Settings app to possibly change permission.
guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else { return }
if UIApplication.shared.canOpenURL(settingsUrl) {
UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
// Finished opening URL
})
}
})
alert.addAction(settingsAction)
self.present(alert, animated: true, completion: nil)
The code is inspired by a similar example for camera access by Apple engineers.
In such scenario, you can show an alert which navigates user to settings
let alert = UIAlertController(title: "Allow notification Access", message: "Allow notification access in your device settings.", preferredStyle: UIAlertController.Style.alert)
// Button to Open Settings
alert.addAction(UIAlertAction(title: "Settings", style: UIAlertAction.Style.default, handler: { action in
guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else {
return
}
if UIApplication.shared.canOpenURL(settingsUrl) {
UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
print("Settings opened: \(success)")
})
}
}))
alert.addAction(UIAlertAction(title: "Close", style: UIAlertAction.Style.default, handler: nil))
self.present(alert, animated: true, completion: nil)
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
}
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
}
});
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)
}