文档章节

【iOS开发】打开另一个APP(URL Scheme与openURL)

hejunbinlan
 hejunbinlan
发布于 2016/11/01 17:10
字数 2692
阅读 305
收藏 0

目标

平常我们做iOS开发,会经常遇到打开其他的APP的功能。本篇文章讲的就是打开别人的APP的一些知识。我们的目标是:

  • 打开别人的APP
  • 让别人打开我们的APP
  • iOS9的适配问题
  • 使用URL Schemes传递数据

准备工作

  • 建立一个名为OpenApp的工作空间,用来存放我们的两个工程
    建立这个工作空间主要是为了让我们后面建立的两个工程能在一个Xcode页面上管理,方便讲解和管理。挺简单的,不清楚的可以看我之前的文章【iOS开发】在一个Xcode页面建立多个工程

建立一个workspace来存放我们的工程

  • 建立一个名为MyApp的iOS工程。这个MyApp是“我的app”,用来打开另一个APP的。
    添加工程到我们刚才创建的OpenApp.xcworkspace。并且在工程的Main.storyboard添加一个button,待会儿我们会用来写方法。

    MyApp工程

  • 建立一个名为WXApp的iOS工程。这个工程是我们模拟的“微信APP”,是被人打开的那个APP。
    为了区分两个应用,我们在Main.storyboard上加一个label,“我是微信App”。

    在workspace建立WXApp工程

WXApp

好了,准备工作就这么简单。

打开别人的APP与让别人打开我们的APP

想要打开别人的APP或者让别人打开我们的APP,那就需要通过URL Schemes了。

什么是URL Schemes?

URL Schemes是苹果给出的用来跳转到系统应用或者跳转到别人的应用的一种机制。同时还可以在应用之间传数据。

通过对比网页链接来理解 iOS 上的 URL Schemes,应该就容易多了。
URL Schemes 有两个单词:

  • URL,我们都很清楚,http://www.apple.com
    就是个 URL,我们也叫它链接或网址;
  • Schemes,表示的是一个 URL 中的一个位置——最初始的位置,即 ://
    之前的那段字符。比如 http://www.apple.com
    这个网址的 Schemes是 http
    根据我们上面对 URL Schemes 的使用,我们可以很轻易地理解,在以本地应用为主的 iOS 上,我们可以像定位一个网页一样,用一种特殊的 URL 来定位一个应用甚至应用里某个具体的功能。而定位这个应用的,就应该是这个应用的 URL 的 Schemes 部分,也就是开头儿那部分。

在WXApp上设置一个URL Schemes

为了能让别的App(包括我们刚才创建的MyApp)能够打开WXApp,我们需要为WXApp添加一个URL Schemes。
步骤:选中WXApp工程->Info->URL Types->点击“+”->在URL Schemes栏填上 weixin

添加一个URL Schemes

备注:一个应用是可以有多个URL Schemes的。你可以再次点击“+”来添加一个URL Schemes

我们看看info.plist文件里面是怎样的。

info.plist文件里面的URL Schemes

然后我们run一下WXApp。(注意一下你run的target是哪个)

在模拟器run一下WXApp

这样,WXApp就向系统“注册”了一个URL Schemes,其他的应用可以通过openurl:方法来打开WXApp了。

MyApp打开WXApp

现在我们在MyApp里面打开WXApp。方法非常简单。
在ViewController里面添加一个方法

- (IBAction)openWXApp:(UIButton *)sender {
    [self demo1];
}
- (void)demo1 {
    //创建一个url,这个url就是WXApp的url,记得加上://
    NSURL *url = [NSURL URLWithString:@"weixin://"];

    //打开url
    [[UIApplication sharedApplication] openURL:url];
}

然后run一下MyApp

run MyApp

运行了之后点击“打开微信”button,会弹出“MyApp”想要打开“WXApp”提示框,点确认之后就可以跳转到WXApp了。

点击“打开微信”button

打开了WXApp


iOS9之后,在一个应用跳转到了另一个应用之后,左上角会有个返回到上一个应用的按钮。这样,我们在MyApp里面点击“打开微信”按钮,跳转到WXApp之后,再点击“Back to MyApp”,又回到MyApp了。闲着无聊就可以反复点击这两个按钮来两个应用间跳转了,哈哈。

值得一说的是,这个URL Schemes并不是唯一的。也就是说,多个应用之间设置的URL Schemes是可以相同的。
那么问题来了,假如两个应用的URL Schemes相同的话,使用openURL:方法会打开哪个应用呢?
楼主亲自用手机试了一下。
步骤是:

  • 将MyApp安装到手机上,点击“打开微信”button,微信打开了。
  • 然后将WXApp也安装到手机上。再次点击MyApp的“打开微信”button,结果打开的是WXApp。
    结论:如果两个应用有URL Schemes是相同的,后安装的应用的URL Schemes会把早安装的应用的URL Schems覆盖掉。

在safari打开WXApp

没错,注册了URL Schemes的应用,用safari浏览器也是可以打开的。我就经常用这个来验证应用是否设置了我想要的URL Schemes
在safari打开WXApp,直接在safari的地址栏输入weixin://,enter就可以打开了

用safari打开WXApp

用safari打开WXApp

iOS9中的适配

  • 配置URL Schemes白名单
    其实在打开WXApp的时候,正常情况下,我们应该是先用canOpenURL:方法先判断能否打开这个url,然后再用openURL方法打开该URL的。这样可以带来更好的用户体验。因为用户不一定安装了WXApp。假如用户没有安装的话点击“打开微信”button是没有任何反应的。这时候我们应该先判断是否能够打开这个url(也就是判断用户有没有安装WXApp),没有安装的话就给个温馨提示,比如:“U四不四洒,没安装WXApp,怎么打开啊!”。
    更重要的是,假如点击之后没效果,很有可能被苹果拒绝哦。
- (IBAction)openWXApp:(UIButton *)sender {
//    [self demo1];
    [self demo2];
}
//先判断再打开WXApp
- (void)demo2 {
    //创建一个url,这个url就是WXApp的url,记得加上://
    NSURL *url = [NSURL URLWithString:@"weixin://"];

    //先判断是否能打开该url
    if ([[UIApplication sharedApplication] canOpenURL:url]) {
        //打开url
        [[UIApplication sharedApplication] openURL:url];
    }else {
        //给个提示或者做点别的事情
        NSLog(@"U四不四洒,没安装WXApp,怎么打开啊!");
}

但是我们发现用了canOpenURL:方法之后,并没有如我们想像中打开了WXApp。一看,Xcode控制台提示:

Xcode控制台错误提示

为什么会这样呢?
因为iOS9的时候苹果加强了权限,只有在info.plist文件中加入了URL Schemes白名单才能使用canOpenURL:方法来判断是否能打开该url。该白名单的上限是50个。也就是说,你最多只能使用canOpenURL:方法判断50个URL Schemes。当然,平常我们都用不了那么多,就算是集成分享功能,50个肯定够了。

备注:只是对canOpenURL:方法有限制,openURL:方法是没有限制的。

言归正传,我们需要在MyApp的info.plist里面将weixin设置为白名单。
步骤:点击info.plist->右键->Open As->Source Code->添加下面的代码

    <key>LSApplicationQueriesSchemes</key>
    <array>
        <string>weixin</string>
    </array>

这样就可以了。

使用URL Schems传递数据

URL Schemes除了可以用来打开APP之外,还可以用来在两个App之间传递少量的数据。
在百度上搜索“ios”,会生成一个url,下面来以这个url来大概介绍url的组成。

url为:https://www.baidu.com/s?ie=UTF-8&wd=ios

  • https就是协议,也就是scheme
  • www.baidu.com 是域名
  • /s是路径
  • ?后面的是query,也就是查询参数。这个url有两个参数,分别是ie=UTF-8wd=ios

我们iOS的URL Schemes中也是差不多的。
而且,在openURL的时候,如果url中带有参数,只要URL Schemes是正确的,那同样可以打开App,而且,后面的参数也会带到我们打开的App那里。
咱们做个Demo就一目了然了。
在MyApp中,写个demo3方法,url为weixin://www.shixueqian.com/abc?title=hello&content=helloworld

- (IBAction)openWXApp:(UIButton *)sender {
//    [self demo1];
//    [self demo2];
    [self demo3];
}
//使用URL Schemes传递数据
- (void)demo3 {
    //创建一个url,这个url就是WXApp的url,记得加上://
    NSURL *url = [NSURL URLWithString:@"weixin://www.shixueqian.com/abc?title=hello&content=helloworld"];
    //打开url
    [[UIApplication sharedApplication] openURL:url];  
}

在WXApp的AppDelegate.m中,实现application: openURL:(NSURL *)url sourceApplication: annotation:回调

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

    NSLog(@"url=====%@ \n  sourceApplication=======%@ \n  annotation======%@", url, sourceApplication, annotation);
    return YES;
}

run了之后,我们发现,我们依旧可以通过点击openURL:方法打开WXApp。而且在WXApp被打开的时候,会执行application: openURL:(NSURL *)url sourceApplication: annotation:回调方法。在这个回调方法中,我们可以得到MyApp传过来的url等信息。
控制台打印如下:

log结果

完整的url信息都传过来了,我们就可以利用这个url里面的路径和参数等信息了,想干嘛就干嘛。这就实现了从MyApp向WXApp传递数据了。

备注:
苹果一共给了3个openURL的回调。
分别是:

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url NS_DEPRECATED_IOS(2_0, 9_0, "Please use application:openURL:options:") __TVOS_PROHIBITED;
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(id)annotation NS_DEPRECATED_IOS(4_2, 9_0, "Please use application:openURL:options:") __TVOS_PROHIBITED;
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options NS_AVAILABLE_IOS(9_0); // no equiv. notification. return NO if the application can't open for some reason

为什么会有3个呢?这3个回调又有什么区别?(为方面讲解,分别设置ABC3个回调)

  • 3个回调的功能基本一样,都是在别人通过URL Schemes打开应用的时候会执行的。
    不同之处:
  • A回调是在iOS2.0的时候推出的,参数只有url
  • B回到是在iOS4.2的时候推出的,参数有url sourceApplication annotation.
  • C回调是iOS9.0的时候推出的,参数有url optionsoptions有下面几个key
    // Keys for application:openURL:options:
    UIKIT_EXTERN NSString *const UIApplicationOpenURLOptionsSourceApplicationKey NS_AVAILABLE_IOS(9_0);   // value is an NSString containing the bundle ID of the originating application
    UIKIT_EXTERN NSString *const UIApplicationOpenURLOptionsAnnotationKey NS_AVAILABLE_IOS(9_0);   // value is a property-list typed object corresponding to what the originating application passed in UIDocumentInteractionController's annotation property
    UIKIT_EXTERN NSString *const UIApplicationOpenURLOptionsOpenInPlaceKey NS_AVAILABLE_IOS(9_0);   // value is a bool NSNumber, set to YES if the file needs to be copied before use
  • 这几个回调是有优先级的。C>B>A。也就是说,如果你3个回调都实现了,那么程序只会执行C回调。其他回调是不会执行的。(当然,iOS9以下只会执行B回调)。

参考

本篇文章的Demo已经上传到GitHub上了https://github.com/shixueqian/OpenApp

欢迎观看我的另一篇文章,是这篇文章的进阶版。
【iOS开发】仿微信分享功能

谦言万语

用通俗的语言,讲述动人的代码故事。


 

文/谦言忘语(简书作者)
原文链接:http://www.jianshu.com/p/0811ccd6a65d
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

本文转载自:http://www.jianshu.com/p/0811ccd6a65d

hejunbinlan
粉丝 41
博文 596
码字总数 21569
作品 0
浦东
高级程序员
私信 提问
加载中

评论(1)

小码爱大牛
小码爱大牛
你好,我是深圳一家以家居安防为核心的智能家居公司的HR在招聘一位iOS开发架构师兼leader。不知道您自己或者身边同事朋友有没有在看工作机会的呢?如果感兴趣可以发简历到3288771685@qq.com或者加QQ。
注册URL Scheme

我们都知道苹果手机中的APP都有一个沙盒,APP就是一个信息孤岛,相互是不可以进行通信的。但是iOS的APP可以注册自己的URL Scheme,URL Scheme是为方便app之间互相调用而设计的。我们可以通过...

北方人在上海
2016/11/22
44
0
自定义 URL Scheme - 用于从浏览器或其他应用中启动本应用。

注册自定义 URL Scheme 注册自定义 URL Scheme 的第一步是创建 URL Scheme — 在 Xcode Project Navigator 中找到并点击工程 info.plist 文件。当该文件显示在右边窗口,在列表上点击鼠标右键...

FTD_SL
2016/10/10
66
0
转载:应用程序间通信 openURL:用法总结

转载:应用程序间通信 openURL:用法总结 管iPhone不允许同时运行两个应用程序,我们可以从自己的应用程序中启动另一个应用程序,并且可以在应用程序之间共享数据。我们可以使用UIApplication...

HillYoung
2014/03/11
60
0
Swift:在Safari中打开App

Swift:在Safari中打开App 打开之前会发生什么呢,先看看这个图: 我这里只是简单模拟了一下。当你输入一个特殊的“url”之后,Safari弹出一个提示,问你是否继续打开这个App。如果你这个时候...

微笑的江豚
2016/08/08
32
0
iphone程序启动互相调用, 打开其他程序

在iphone程序打开其它程序(Launching Other Apps within an iPhone Application) 你可以使用openUrl打开一些程序,不只是浏览器,我们将在下面的例子中演示这些这些应用: 打开浏览器 打开...

长平狐
2012/08/13
569
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring使用ThreadPoolTaskExecutor自定义线程池及实现异步调用

多线程一直是工作或面试过程中的高频知识点,今天给大家分享一下使用 ThreadPoolTaskExecutor 来自定义线程池和实现异步调用多线程。 一、ThreadPoolTaskExecutor 本文采用 Executors 的工厂...

CREATE_17
今天
5
0
CSS盒子模型

CSS盒子模型 组成: content --> padding --> border --> margin 像现实生活中的快递: 物品 --> 填充物 --> 包装盒 --> 盒子与盒子之间的间距 content :width、height组成的 内容区域 padd......

studywin
今天
7
0
修复Win10下开始菜单、设置等系统软件无法打开的问题

因为各种各样的原因导致系统文件丢失、损坏、被修改,而造成win10的开始菜单、设置等系统软件无法打开的情况,可以尝试如下方法解决 此方法只在部分情况下有效,但值得一试 用Windows键+R打开...

locbytes
昨天
8
0
jquery 添加和删除节点

本文转载于:专业的前端网站➺jquery 添加和删除节点 // 增加一个三和一节点function addPanel() { // var newPanel = $('.my-panel').clone(true) var newPanel = $(".triple-panel-con......

前端老手
昨天
8
0
一、Django基础

一、web框架分类和wsgiref模块使用介绍 web框架的本质 socket服务端 与 浏览器的通信 socket服务端功能划分: 负责与浏览器收发消息(socket通信) --> wsgiref/uWsgi/gunicorn... 根据用户访问...

ZeroBit
昨天
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部