Open settings URL from user notification? - ios

Opening settings URLs works for me from a UIAlertController but not from a UNUserNotificationCenter notification. Both approaches use the same URLs and the same code, namely this function:
func open() {
if let url = self.url {
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, completionHandler: { (success) in
Log.log("Opened settings url: \(url), \(success)", true)
})
}
}
}
My logging line shows the completionHandler gets called with true from the alert and false from the notification. At first I thought it might be an issue with the phone being locked, but I also got false through a notification interacted with on the home screen.
What do I need to do to get this to work from notifications?

Try it with ".foreground" in options while declaring UNNotificationAction.
(this action should cause the application to launch in the foreground.)

Related

iOS - Control over "${App} wants to open ${Another App}" dialog

In my app, I have functionality where the user could open another app lets call it as 'App2'. If App2 is not present on the device, then user will be present with an app not available alert that I created, lets call this as Alert1.
However if App2 is present on the device and user tries to open it, Apple's "${App} wants to open App2" dialog is presented. If user clicks 'Cancel' on this, the callback executes my code to present Alert1.
I don't want my app to display Alert1 when user clicks 'Cancel' on Apple's dialog. Is there a way to control Apple's dialog?
Below is my code:
if let url = urlComponents.url {
UIApplication.shared.open(url, completionHandler: { success in
if !success {
showAppNotAvailableAlert(url.absoluteString, actionLabel: action.label)
}
})
return
}
try
if let url = urlComponents.url {
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, completionHandler: { didURLOpen in
if !didURLOpen {
debugPrint("User pressed cancel button")
}
})
}
else {
showAppNotAvailableAlert(url.absoluteString, actionLabel: action.label)
}
return
}
idea is to check if app exists by using canOpenURL, if it exists then try to open the app and handle error in completion block

blank page after recaptcha verification Authenticate with Firebase on iOS using a Phone Number Swift

After recaptcha verification, page only returned blank. It did nothing to do next step.
Screen Shot
In your app delegate's application(_:open:options:) method, call Auth.auth().canHandle(url).
For the blank re-captcha page issue I was able to resolve it by doing these 3 things:
1st thing-
Inside the GoogleSerivce-Info.plist file make sure the REVERSED_CLIENT_ID is added to your project via the URL types using this. Follow the first part of the second step there: Add custom URL schemes to your Xcode project (look at the screenshot).
2nd thing-
In the project navigator select the blue project icon
Select Capabilities
Open Background Modes
Select Background fetch
3rd thing-
Before verifying the phone number call PhoneAuthProvider.provider(auth: Auth.auth())
#IBAction func phoneButton(sender: UIButton) {
// ***step 5***
PhoneAuthProvider.provider(auth: Auth.auth())
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumberTextField.text!, uiDelegate: nil) {
(verificationID, error) in
if let error = error {
print(error.localizedDescription)
return
}
guard let verificationId = verificationID else { return }
// do something with verificationID
}
}
On iOS, the appVerificationDisabledForTesting setting has to be set to TRUE before calling verifyPhoneNumber. This is processed without requiring any APNs token or sending silent push notifications in the background, making it easier to test in a simulator. This also disables the reCAPTCHA fallback flow.
Firebase Docs
I face this issue and fix it by adding this code into my AppDelegate.m
- (BOOL) application: (UIApplication *) app
openURL: (NSURL *) url
options: (NSDictionary <UIApplicationOpenURLOptionsKey, id> *)
options {
if ([[FIRAuth auth] canHandleURL: url]) {
return YES;
} else {
// URL not auth related, developer should handle it.
return NO;
}
}

Will my app be rejected if I use CallKit framework to check status of ongoing call even if my app does not have any VOIP functionality?

I am working on an app that has one section from where user can tap on a mobile number to make cellular calls. To make call, I am using following code.
if let phoneCallURL = URL(string: "tel://\(9999999999)") {
let application:UIApplication = UIApplication.shared
if (application.canOpenURL(phoneCallURL)) {
if #available(iOS 10.0, *) {
application.open(phoneCallURL, options: [:], completionHandler: nil)
} else {
// Fallback on earlier versions
application.openURL(phoneCallURL)
}
}
}
This shows an alert with option to Call or Cancel. Now when I select Call option, I need to check the state of the ongoing call.
To do this I am making use of CallKit framework.
var callObserver = CXCallObserver()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
callObserver.setDelegate(self, queue: nil)
}
func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {
if call.hasConnected {
}
if call.isOutgoing {
}
if call.hasEnded {
}
if call.isOnHold {
}
}
This delegate methods receives callback when an outgoing call starts or ends.
Now since my app does not have any functionality related to VOIP, I just want to know if it is OK to use CallKit framework like this to know the call status.
Will my app be rejected for Appstore upload if I use CallKit like this and not have a VOIP functionality in the app?
Any help on this will be much appreciated.
In general, CallKit.framework's CXCallObserver API may be used by any app, regardless of whether that app provides VoIP calling functionality itself or not.
Note however that it's not guaranteed that any particular call that your app observes are the result of the user deciding to call based on your app's opening of a tel: URL. It is possible that the user declined to open the tel: URL that your app offered to open, and instead dialed a call separately or received an incoming call around the same time period, and your app would receive similar-looking CXCallObserver delegate callbacks regardless. It's not possible to reliably distinguish between calls initiated outside your app from those started from your app.

Add function for cancel in UIAlert of Phone Call function

I have a function that places a phone call when a button is pressed.
private func callNumber(phoneNumber:String) {
if let phoneCallURL = URL(string: "tel://\(phoneNumber)") {
let application:UIApplication = UIApplication.shared
if (application.canOpenURL(phoneCallURL)) {
application.open(phoneCallURL, options: [:], completionHandler: nil)
}
}
}
I want to add some functionality if the users hit cancel when the alert pops up to confirm the call. How would I do that?
According to this question: Prompt when trying to dial a phone number using tel:// scheme on iOS 10.3
This alert is actually a bug in iOS 10.3 and should be removed at some point in the future. It isn't supposed to come up for "tel:" links in native apps.
That said, I don't believe there is a way to detect the alert and how the user interacts with it.

Send button click event from iOS Today Widget without launching the host app

I am writing a Today Widget for an iOS app. The widget has a few action buttons. I want to receive the click event when someone clicks on it. However, it should not launch the app.
I've already tried this but to no avail.
My current implementation is to define a URL Scheme, and call openURL on those button presses like so:
Button 1 links to myApp://button1
Button 2 links to myApp://button2
Button 3 links to myApp://button3
I am receiving these events in the AppDelegate's
application(_:open:options:)
Here's the Code in TodayWodgetController
#IBAction func widgetClicked(sender: UIButton){
if sender == button1 {
let u = NSURL(string: "myApp://button1")
self.extensionContext?.open(u! as URL, completionHandler: nil)
}
...
}
and here is the code I'm using in the host app's AppDelegate
func application(_ app: UIApplication,
open url: URL,
options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
if url.absoluteString.range(of: "button1") != nil{
print ("Button 1 Pressed")
}
....
return true
}
However, like I said, it also launches the host App. I want it to just send me the click event without launching the App.
Any help would be appreciated.
I don't think there is a way to do that from an app extension.
Definition of open(_ URL: URL, completionHandler: ((Bool) -> Void)? = nil) as described by Apple:
Asks the system open a URL on behalf of the currently running app
extension.
Each extension point determines whether to support this method, or
under which conditions to support this method. In iOS 8, only the
Today extension point (used for creating widgets) supports this
method.
Important: Apple allows a widget to use the open(_:completionHandler:) method to open the widget’s own containing
app.

Resources