IOS的软件之间的调用(URL Schemes)

在ios中,软件的调用是通过项目设置中的URL Schemes来调用的。

一、比较常用的调用

这几个是比较常用的调用,是系统方法支持的

//调用 自带mail?
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"mailto://[email protected]"]];

//调用 电话phone?
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://10086"]];?

//调用 SMS
?[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"sms://10086"]];?

//调用自带 浏览器 safari
?[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.baidu.com"]];

//调用 Remote
?[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"remote://fff"]];

这些是系统基础的,不需要修改什么,只要调用对应的内容即可

1、测试demo,要真机调试才可以

static int i =0;
- (void)viewDidLoad {
    [super viewDidLoad];
    UIButton * button = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    ;
     forState:UIControlStateNormal];
    ;
    [self.view addSubview:button];
}
-(void)test{
    if (i == 0) {
         [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"mailto://[email protected]"]];
    }
    if (i == 1) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://10086"]];
    }
    if (i == 2) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"sms://10086"]];
    }
    if (i == 3) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.baidu.com"]];
    }
    if (i == 4) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"remote://fff"]];
    }
    i++;
}

二、用户软件之间的调用

软件的调用这里用Demo说明。

Demo下载地址:

github:https://github.com/DamonHu/shemedemon

gitosc:http://git.oschina.net/DamonHoo/shemedemon

这里app1是被唤醒的,app2是去调用app1的

首先在app1的项目设置里面info选项的URL types里面填写一个自定义的schemes,这个schemes是用来被调用的时候系统知道需要调用哪个软件的,所以要有唯一性。

点击查看原图

这里我设置成了damon,你们可以自定义

点击查看原图

然后在app1中的AppDelegate.m文件里面增加这个函数

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(id)annotation

这个函数只有在其他软件调用它的时候才会被调用,所以我这里代码设置下,让其他软件调用的时候显示出来调用的内容,如果实用运用中,只要判断url的正确性,然后return yes就行了。我这里是为了实验,首先获取当前显示的viewcontroller,然后再加上一个label显示调用的内容

- (UIViewController *)getCurrentVC
{
    UIViewController *result = nil;
    
    UIWindow * window = [[UIApplication sharedApplication] keyWindow];
    if (window.windowLevel != UIWindowLevelNormal)
    {
        NSArray *windows = [[UIApplication sharedApplication] windows];
        for(UIWindow * tmpWin in windows)
        {
            if (tmpWin.windowLevel == UIWindowLevelNormal)
            {
                window = tmpWin;
                break;
            }
        }
    }
    
    UIView *frontView = [[window subviews] objectAtIndex:0];
    id nextResponder = [frontView nextResponder];
    
    if ([nextResponder isKindOfClass:[UIViewController class]])
        result = nextResponder;
    else
        result = window.rootViewController;
    
    return result;
}

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(id)annotation
{
//    NSLog(@"application bundle id:%@",sourceApplication);
//    NSLog(@"url scheme:%@",[url scheme]);
//    NSLog(@"url query:%@",[url query]);
    UILabel *sssslable = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 460, 260)];
    [sssslable setNumberOfLines:3];
    [sssslable setTextColor:[UIColor redColor]];
    [sssslable setText:[NSString stringWithFormat:@"bundle id:%@,url scheme:%@,urlpar:%@,",sourceApplication,[url scheme],url]];
    [[self getCurrentVC].view addSubview:sssslable];
    return YES;
}

这样app1就已经设置完毕了,现在再建立一个app2的工程。

因为现在ios9对软件的安全性提高了,所以需要先设置app2的info.plist文件,加上一个LSApplicationQueriesSchemes的array字段,下面加上app1中设置的damon,

屏幕快照 2016-07-18 07.52.00.png

否则在使用的时候会报错

-canOpenURL: failed for URL: "OpenAppTest://mark?id=007" - error: "This app is not allowed to query for scheme

这就是为什么接微信和新浪的时候也需要设置的原因。

2016.10.8增加对OpenURL和canOpenURL说明start

在info.plist文件里面添加LSApplicationQueriesSchemes字段,是在需要调用canOpenURL这个函数的话需要加上,如果仅仅是直接调用OpenURL的话,可以不用加,如果调用canOpenURL这个函数,而info.plist文件里面没有加上对应的url,那么即使用户手机上安装了那个软件,canOpenURL依然返回的为false。

如这个文章http://awkwardhare.com/post/121196006730/quick-take-on-ios-9-url-scheme-changes所说:

If you call the “canOpenURL” method on a URL that is not in your whitelist, it will return “NO”, even if there is an app installed that has registered to handle this scheme. A “This app is not allowed to query for scheme xxx” syslog entry will appear.

原因是因为canOpenURL和OpenURL的区别在于canOpenURL是在静默状态下判断对应的软件是否安装,而OpenURL则是直接去调用该软件,也许出于安全性原因,如果不对canOpenURL做限制,那么就可能会有软件不是去调用其他软件,而是专门的扫描用户手机里面是否安装了其他对应的app但是用户却没有察觉,而openURL就不同了,只要调用了,就会去打开对应的app软件,这样用户就知道了某个软件在后台干嘛,所以对于canOpenURL必须要在info.plist加列表,而OpenURL可以不用加,并且info.plist不能动态修改,并且白名单的上限是50个。

正如在《ios9适配 跳转白名单设置?》中的回答

LSApplicationQueriesSchemes 这个东西你搞错了一个概念,他不是决定 openURL 的,是决定 canOpenURL 的。

所以说你要跳转的 app 完全不用加到 LSApplicationQueriesSchemes 里面去,如果你要判断一个 app 是否安装,才需要加进去。

Bundle 里面的 Plist 是不可能改的。

但是测试了下,程序在后台运行的话,canOpenUrl在满足条件时会立马变为true,而openURL只有在这个app是当前运行状态下,才可以去调用其他的app

end

设置好之后,就可以调用了,在app2的view中写一个调用函数,这样就可以直接调用app1了。

- (void)viewDidLoad {
    [super viewDidLoad];
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 30, 70, 70)];
    ;
     forState:UIControlStateNormal];
    ;
    [self.view addSubview:button];
}

-(void)awakeother
{
    NSLog(@"唤醒app");
    NSString * url = @"damon://ssss";
    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:url]]) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
    }
}

设置好之后,先运行app1,确保app1安装在模拟器上,然后再安装app2,确保两个是安装在同一个模拟器上面

屏幕快照 2016-07-18 07.52.14.png

然后运行app2即可看到效果如下

点击查看原图点击查看原图

这就是app2调用app1的过程。

三、用户软件之间的回调

除了app2调用app1,调用之后想回去app2中,就是app1返回去再调用app2可以这么做:

因为只要是以damon://开头的,都可以调用起app1,所以这里可以在app2调用app1的时候传入app2自己的url schemes当参数,这样就可以在app1的回调函数中得到app2的schemes了,然后同样的方法调用app2的即可。这个参数的说明看下面这个url的说明。

四、URL的说明

上面输出的是整个url的,没有截取,所以说一下url的格式

调用函数

NSString *ll = @"damon://sdf?mmmm?ss";
NSURL * uu = [NSURL URLWithString:ll];
NSLog(@"uu:%@\n",uu);
NSLog(@"scheme:%@\n",[uu scheme]);
NSLog(@"host:%@\n",[uu host]);
NSLog(@"query:%@\n",[uu query]);
NSLog(@"%@\n",[uu relativeString]);

输出内容

点击查看原图

所以可以看出

scheme就是前面写的damon

host就是直接跟着damon://后面的,截至到第一个?的内容

query则是第一个?之后的内容

这里根据需要截取即可。

五、参考文章

最后感谢下面几个文章:

  1. iOS App 唤醒另一个App

  2. IOS-应用之间调用

  3. 【Launcher 教程】从 URL Schemes 入门到用 Launcher 调用各效率软件

  4. iOS9适配 之 关于info.plist 第三方登录 添加URL Schemes白名单

  5. https://github.com/ChenYilong/iOS9AdaptationTips

Last modification:January 1st, 1970 at 08:00 am
如果看了这个文章可以让你少加会班,可以请我喝杯可乐
已打赏名单
微信公众号

Leave a Comment