Currently I have the following code, which is essentially asking the user for permission to send notifications, and then checking to see if notifications are enabled:
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound], completionHandler: { (granted, error) in
if granted {
} else {
}
})
let notifType = UIApplication.shared.currentUserNotificationSettings?.types
if notifType?.rawValue == 0 {
print("being called")
let alert = UIAlertController(title: "Notifications are disabled for this app.", message: "Please enable notifications for the app to work properly. This can be done by going to Settings > Notifications > NAME HERE and allow notifications.", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.cancel, handler: nil))
show(alert, sender: self)
} else {
//enabled
}
The code works, however, it checks if notifications are enabled before the user can select "yes" or "no". Thus, no matter what is selected, the dialog box pops up. Is there a way I can wait to check for authorization status until the user selects "yes" or "no"?
You can move the check into the callback, so authorization is checked first:
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound], completionHandler: { (granted, error) in
if (granted) {
// Alert here
} else {
// Or here
}
})
Related
I want to make a phone verification with Firebase, but I get a failure to send a notification. I'm sharing AppDelegate code. I couldn't figure out what I had to do? I performed certificate insertion. FirebaseAppDelegateProxyEnabled is value no
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate {
func applicationReceivedRemoteMessage(_ remoteMessage: MessagingRemoteMessage) {
print(remoteMessage.appData)
}
func registerForPushNotifications() {
UNUserNotificationCenter.current()
.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
print("Permission granted: \(granted)") // 3
}
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: authOptions, completionHandler: {_, _ in })
// For iOS 10 data message (sent via FCM
Messaging.messaging().delegate = self
} else {
let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
FirebaseApp.configure()
}
Code send function
func sendCode(_ sender: Any) {
let alert = UIAlertController(title: "Phone number", message: "Is this your phone number? \n \(emailField.text!)", preferredStyle: .alert)
let action = UIAlertAction(title: "Yes", style: .default) { (UIAlertAction) in
PhoneAuthProvider.provider().verifyPhoneNumber(self.emailField.text!, uiDelegate: nil) { (verificationID, error) in
if error != nil {
print("eror: \(String(describing: error?.localizedDescription))")
} else {
let defaults = UserDefaults.standard
defaults.set(verificationID, forKey: "authVID")
}
}
}
let cancel = UIAlertAction(title: "No", style: .cancel, handler: nil)
alert.addAction(action)
alert.addAction(cancel)
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)
I am working on an app and try to figure out whether my app is registered for Push Notifications or not. I mean user allow Push notifications or not. But when i want to check in code it always return true. i don't know why is it behaving like this.
My code for checking push notifications registration.
let isRegistered = UIApplication.shared.isRegisteredForRemoteNotifications
if isRegistered == false {
let alertController = UIAlertController(title: "Notification Alert", message: "Kindly enable push notifications", preferredStyle: .alert)
let settingsAction = UIAlertAction(title: "Settings", style: .default) { (_) -> Void in
guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
return
}
if UIApplication.shared.canOpenURL(settingsUrl) {
UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
})
}
}
let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
alertController.addAction(cancelAction)
alertController.addAction(settingsAction)
DispatchQueue.main.async {
self.present(alertController, animated: true, completion: nil)
}
}
What I understood is that if "isRegistered" is false you will ask the user to allow notifications in that case you should be asking for authorization like this :
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
if granted {
DispatchQueue.main.async(execute: {
UIApplication.shared.registerForRemoteNotifications()
})
}
}
I have sample app with a button. On click button should be taking the user to push notification service for my app to be able to disable them or enable.
I know how to get to the general setting with this sample code but I think for notification probably you need some additional parameters like bundleId.
My question is more about URL for push notification for my app not only get to general setup as this is shown on code sample below
Sample code:
#IBAction func pushNotificationSettings(button: UIButton) {
guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
return
}
if UIApplication.shared.canOpenURL(settingsUrl) {
if #available(iOS 10.0, *) {
UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
print("Settings opened: \(success)") // Prints true
})
} else {
// Fallback on earlier versions
}
}
}
For IOS 10 or above
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
if settings.authorizationStatus == .authorized {
// Notifications are allowed
}
else {
// Either denied or notDetermined
let alertController = UIAlertController(title: nil, message: "Do you want to change notifications settings?", preferredStyle: .alert)
let action1 = UIAlertAction(title: "Settings", style: .default) { (action:UIAlertAction) in
if let appSettings = NSURL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.open(appSettings as URL, options: [:], completionHandler: nil)
}
}
let action2 = UIAlertAction(title: "Cancel", style: .cancel) { (action:UIAlertAction) in
}
alertController.addAction(action1)
alertController.addAction(action2)
self.present(alertController, animated: true, completion: nil)
}
}
For ios 10 i used this for registering the push notifications :
Registering for Push Notifications in Xcode 8/Swift 3.0?
Is there a way to ask for the requestAuthorization(options:[.badge, .alert, .sound]) outside the appdelegate and the func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
The reason i ask is because i don't want to present the pop up for push notifications after the user has used the app for a bit. Any ideas?
Like #dan said it isn't necessary to request the notifications permission in the AppDelegate. You can do it wherever you want to. This is what you probably be doing for that.
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .badge, .sound]) { (success, error) in
if error == nil {
if success {
print("Permission granted")
// In case you want to register for the remote notifications
let application = UIApplication.shared
application.registerForRemoteNotifications()
} else {
print("Permission denied")
}
} else {
print(error)
}
}
And Remember
to import the UserNotifications framework where you use this code.
if you register for remote notifications you need to implement the didRegisterForRemoteNotificationsWithDeviceToken method in your AppDelegate
The question for me is the pop up won't show again once user agreed or denied it.
So we have to redirect users to Settings after that manually.
Here comes the code in Swift:
#IBAction func userDidClickButton(_ sender: Any) {
// initialise a pop up for using later
let alertController = UIAlertController(title: "TITLE", message: "Please go to Settings and turn on the permissions", preferredStyle: .alert)
let settingsAction = UIAlertAction(title: "Settings", style: .default) { (_) -> Void in
guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
return
}
if UIApplication.shared.canOpenURL(settingsUrl) {
UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
// do something
}
}
}
let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
alertController.addAction(cancelAction)
alertController.addAction(settingsAction)
// check the permission status
UNUserNotificationCenter.current().getNotificationSettings () { settings in
switch settings.authorizationStatus {
case .denied, .notDetermined:
self.present(alertController, animated: true, completion: nil)
case .authorized:
// continue the stuff
DispatchQueue.main.sync {
// Update UI
}
}
}
}