I have an iOS app that need to switch to Safari and open a link using a POST command. Since iOS 10 we are supposed to use 'openScheme', but where do a specify http method POST?
This is where I am so far;
- (void)openScheme:(NSString *)scheme
options:(NSDictionary *)options
{
UIApplication *application = [UIApplication sharedApplication];
NSURL *URL = [NSURL URLWithString:scheme];
[application openURL:URL options:options completionHandler:^(BOOL success) {
if (success) {
NSLog(#"Opened %#",scheme);
}
}];
}
You can achieve it by adding URLSchemes.
Below is the steps.
(i) Open your info tab in targets.
(ii) At the below, you will find URL Types option.
(iii)Fill data as shown in below image.
(iv) Now, open your Safari browser in iPhone/iPad, type YourApp:// and enter. This should open your app.
Hope this helps!
Related
Is there a way to launch safari only? I know in order to send an intent and have ios to handle it we can do [[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"http://"]];, but if user has other browser installed (i.e. chrome), there's no guarantee safari will be used.
Reason I want to use safari is that I'm trying to have safari to handle certificate authentication for me, and according to here, only system app has permission to do so
try this
//initially we need to check safari is installed or not in our device
NSURL *url = [NSURL URLWithString:#"safari://"];
UIApplication *application = [UIApplication sharedApplication];
if ([application canOpenURL:url]) {
// if success again need to validate the our calling URL.
NSURL *linkURL = [NSURL URLWithString:#"https://iostree.wordpress.com/2017/07/29/launch-safari-from-ios-app/"];
if ([application canOpenURL:linkURL]) {
if ([application respondsToSelector:#selector(openURL:options:completionHandler:)]) {
[application openURL:linkURL options:#{}
completionHandler:^(BOOL success) {
NSLog(#"success");
}];
}
}
}else{
NSLog(#"safari is not installed");
}
I am trying to open the Settings app from my own iOS app.
My code is in Objective-C.
UIApplication *app=[UIApplication sharedApplication];
NSURL *url=[NSURL URLWithString:UIApplicationOpenSettingsURLString];
NSDictionary *dict=[[NSDictionary alloc] initWithObjectsAndKeys:[[NSNumber alloc] initWithBool:YES],UIApplicationOpenURLOptionUniversalLinksOnly, nil];
[app openURL:url options:dict completionHandler:^(BOOL success) {
NSLog(#"in open Url");
}];
This open URL method is the new method given by Apple. What should I pass in the options dictionary?
As you can see in iOS SDK:
Options are specified in the section below for openURL options. An empty options dictionary will result in the same behavior as the older openURL call, aside from the fact that this is asynchronous and calls the completion handler rather than returning a result. The completion handler is called on the main queue.
So you can just send nil to get behaviour of old openURL: method.
Try this to open settings app
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]
Apple with iOS 10 has deprecated openURL: for openURL:option:completionHandler
If I have:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"https://www.google.com"]];
How it will become? options:<#(nonnull NSDictionary<NSString *,id> *)#> in detail
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"https://www.google.com"] options:<#(nonnull NSDictionary<NSString *,id> *)#> completionHandler:nil];
Thanks
Update
options:#{} For empty dictionary with no key and value
http://useyourloaf.com/blog/querying-url-schemes-with-canopenurl/
Write like this.
Handle completionHandler
UIApplication *application = [UIApplication sharedApplication];
NSURL *URL = [NSURL URLWithString:#"http://www.google.com"];
[application openURL:URL options:#{} completionHandler:^(BOOL success) {
if (success) {
NSLog(#"Opened url");
}
}];
Without handling completionHandler
[application openURL:URL options:#{} completionHandler:nil];
Swift Equivalent:- open(_:options:completionHandler:)
UIApplication.shared.open(url)
Apple introduced the openURL: method as a way to open external links with iOS 2. The related function canOpenURL: got some privacy controls in iOS 9 to stop you from querying devices for installed apps. Now with iOS 10 Apple has deprecated the plain old openURL for openURL:options:completionHandler:.
Here is my quick guide to what you need to know to open an external link with iOS 10.
The now deprecated method has a single parameter for the URL to open and returns a boolean to report success or failure:
// Objective-C
- (BOOL)openURL:(NSURL*)url
// Swift
open func canOpenURL(_ url: URL) -> Bool
The new method in iOS 10:
// Objective-C
- (void)openURL:(NSURL*)url options:(NSDictionary<NSString *, id> *)options
completionHandler:(void (^ __nullable)(BOOL success))completion
// Swift
open func open(_ url: URL, options: [String : Any] = [:],
completionHandler completion: (#escaping (Bool) -> Swift.Void)? = nil)
There are now three parameters:
The URL to open
An options dictionary (see below for valid
entries). Use an empty dictionary for the same behaviour as
openURL:.
A completion handler called on the main queue with the
success. Nullable if you are not interested in the status.
Opening a URL with iOS 10
What does this mean if you have an iOS 10 only app, don’t care about options and completion status and just want to stop Xcode complaining:
// Objective-C
UIApplication *application = [UIApplication sharedApplication];
[application openURL:URL options:#{} completionHandler:nil];
// Swift
UIApplication.shared.open(url, options: [:], completionHandler: nil)
In practise as long as you are still supporting iOS 9 or earlier you will want to fallback to the plain old openURL method. Let’s look at an example where do that and also use the completion handler to check the status of the open:
First with Objective-C:
- (void)openScheme:(NSString *)scheme {
UIApplication *application = [UIApplication sharedApplication];
NSURL *URL = [NSURL URLWithString:scheme];
if ([application respondsToSelector:#selector(openURL:options:completionHandler:)]) {
[application openURL:URL options:#{}
completionHandler:^(BOOL success) {
NSLog(#"Open %#: %d",scheme,success);
}];
} else {
BOOL success = [application openURL:URL];
NSLog(#"Open %#: %d",scheme,success);
}
}
// Typical usage
[self openScheme:#"tweetbot://timeline"];
I am passing an empty dictionary for the options and I don’t do anything useful in the completion handler other than log the success. The Swift version:
func open(scheme: String) {
if let url = URL(string: scheme) {
if #available(iOS 10, *) {
UIApplication.shared.open(url, options: [:],
completionHandler: {
(success) in
print("Open \(scheme): \(success)")
})
} else {
let success = UIApplication.shared.openURL(url)
print("Open \(scheme): \(success)")
}
}
}
// Typical usage
open(scheme: "tweetbot://timeline")
Options
The UIApplication header file lists a single key for the options dictionary:
UIApplicationOpenURLOptionUniversalLinksOnly: Use a boolean value set to true (YES) to only open the URL if it is a valid universal link with an application configured to open it. If there is no application configured or the user disabled using it to open the link the completion handler is called with false (NO).
To override the default behaviour create a dictionary with the key set to true (YES) and pass it as the options parameter:
// Objective-C
NSDictionary *options = #{UIApplicationOpenURLOptionUniversalLinksOnly : #YES};
[application openURL:URL options:options completionHandler:nil];
// Swift
let options = [UIApplicationOpenURLOptionUniversalLinksOnly : true]
UIApplication.shared.open(url, options: options, completionHandler: nil)
So for example if I set this to true and try to open the URL https://twitter.com/kharrison it will fail if I do not have the Twitter app installed instead of opening the link in Safari.
Refrence : openURL: deprecated in iOS 10
// Objective-C
UIApplication *application = [UIApplication sharedApplication];
[application openURL:URL options:#{} completionHandler:nil];
// Swift
UIApplication.shared.open(url, options: [:], completionHandler: nil)
Swift 5.0.1 and above
UIApplication.shared.open(URL.init(string: UIApplication.openSettingsURLString)!)
// In Xcode 9 and iOS 11
UIApplication *application = [UIApplication sharedApplication];
NSURL *URL = [NSURL URLWithString:#"http://facebook.com"];
[application openURL:URL options:#{} completionHandler:^(BOOL success) {
if (success) {
NSLog(#"Opened url");
}
}];
Open Application Setting (Objective-c)
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]
options:#{}
completionHandler:^(BOOL success) {
}];
Tested in iOS 12
I am facing a strange problem.
I am using xcode 7.2, iOS 9, working on real device iphone 4S (not simulator).
I have 2 apps, app1 and app2. app1 is supposed to send data to app2 using an url scheme.
app2 has well declared the scheme
app1 has referenced the scheme in plist (as it is required in iOS9)
<key>LSApplicationQueriesSchemes</key>
<array>
<array>
<string>OpenLinkMyData</string>
</array>
</array>
Here is the code i use :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0) , ^{
// build the url, using the scheme name, and the data
// note that json is escaped from bad url chars.
NSString * MyJsonDataWellEscaped = [[SomeClass getJSonDataToExport] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL * url = [NSURL URLWithString:[NSString stringWithFormat:#"OpenLinkMyData://%#",MyJsonDataWellEscaped]];
// Next line should allow test if the app able to manage that scheme is installed.
// BUT in our case, this allways returning false.
bool can = [[UIApplication sharedApplication] canOpenURL:url];
NSLog(#"canOpenUrl = %#", can?#"true":#"false");
});
// code of the app that do stuff...
}
I get back the following logs :
-canOpenURL: failed for URL: "OpenLinkMyData://(myJsonSuff)" - error: "This app is not allowed to query for scheme OpenLinkMyData"
canOpenUrl = false
But if i use the following code :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0) , ^{
// build the url, using the scheme name, and the data
// not that json is escaped from bad url chars.
NSString * MyJsonDataWellEscaped = [[Move2MyMHelper getJSonDataToExport] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL * url = [NSURL URLWithString:[NSString stringWithFormat:#"OpenLinkMyData://%#",MyJsonDataWellEscaped]];
if([[UIApplication sharedApplication] openURL:url])
{
NSLog(#"App launched OK");
}
else
{
NSLog(#"App not launched");
}
});
// code of the app that do stuff...
}
If I don't check if scheme is available and I use it directly, App2 is well opened and get all data as required.
(else if the app2 is not installed, i get the "App not launched" log).
here is the App2 source for receiving the data (which works as awaited) :
-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
NSString *prefixToRemove = #"OpenLinkMyData://";
if(url != nil && [[url absoluteString] hasPrefix:prefixToRemove])
{
NSString * urlStr = [url absoluteString];
NSString * json = [urlStr substringFromIndex:[prefixToRemove length]];
json = [json stringByRemovingPercentEncoding];
NSLog(#"OpenLinkMyData with json : %#", json);
}
return YES;
}
What is the problem with canOpenUrl in my case ?
Thanks for any help.
Making LSApplicationQueriesSchemes be an array of strings instead of an array of arrays of strings:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>OpenLinkMyData</string>
</array>
A side note regarding this topic...
There is a 50 request limit for protocols that are not registered.
In this discussion apple mention that for a specific version of an app you can only query the canOpenUrl a limited number of times and will fail after 50 calls for undeclared schemes. I've also seen that if the protocol is added once you have entered this failing state it will still fail.
Be aware of this, could be useful to someone.
I'm writing an App where you can call a person via FaceTime. My problem is, when I click on my button for the FaceTime-call, FaceTime opens but there is always a message "animStartXXXXXXX is not available for FaceTime." (the XXXX are random numbers). If I then call the same person from the normal FaceTime-app it works.
The code for the FaceTime-call:
NSString *facetimeString = #"facetime://";
[facetimeString stringByAppendingString:contactNumber];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:facetimeString]];
I get the contactNumber by selecting it from the Adressbook from within my App and it works fine with normal calls/SMS.
Does anyone have a solution for my problem?
I don't think PAIR is using FaceTime for video chat.
Since FaceTime API is not available to developers, you should consider using OpenTok iOS SDK.
Here is a excerpt from GitHub site:
The OpenTok iOS SDK lets you use OpenTok video sessions in apps you build for iPad, iPhone, and iPod touch devices. This means you can use OpenTok video sessions that connect iOS users with each other and with web clients.
It is official that you can use Native app URL strings for FaceTime video calls:
facetime:// 14085551234
facetime://user#example.com
Please refer to the link: https://developer.apple.com/library/archive/featuredarticles/iPhoneURLScheme_Reference/FacetimeLinks/FacetimeLinks.html
Though this feature is supported on all devices, you have to change the code a little bit for iOS 10.0 and above as openURL(_:) is deprecated.
https://developer.apple.com/documentation/uikit/uiapplication/1622961-openurl?language=objc
Please refer code below for the current and fallback mechanism, so this way it will not get rejected by Appstore.
-(void) callFaceTime : (NSString *) contactNumber
{
NSURL *URL = [NSURL URLWithString:[NSString
stringWithFormat:#"facetime://%#", contactNumber]];
if (#available(iOS 10.0, *)) {
[[UIApplication sharedApplication] openURL:URL options:#{}
completionHandler:^(BOOL success)
{
if (success){
NSLog(#"inside success");
}
else{
NSLog(#"error");
}
}];
}
else {
// Fallback on earlier versions
NSString *faceTimeUrlScheme = [#"facetime://"
stringByAppendingString:contactNumber];
NSURL *facetimeURL = [NSURL URLWithString:faceTimeUrlScheme];
// Facetime is available or not
if ([[UIApplication sharedApplication] canOpenURL:facetimeURL])
{
[[UIApplication sharedApplication] openURL:facetimeURL];
}
else
{
// Facetime not available
NSLog(#"Facetime not available");
}
}
}
in contactNumber either pass phone number or appleid.
NSString *phoneNumber = #"9999999999";
NSString *appleId = #"abc#gmail.com";
[self callFaceTime:appleId];
objective-c ios facetime