目标

平常我们做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开发】仿微信分享功能

谦言万语

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

from:http://www.jianshu.com/p/0811ccd6a65d

【转】【iOS开发】打开另一个APP(URL Scheme与openURL)的更多相关文章

  1. android一个app打开另一个app的指定页面

    一个app打开另一个app的指定页面方法 有以下几种 1.通过包名.类名 2.通过intent的 action 3.通过Url 方案1. ComponentName componentName = n ...

  2. iOS app url scheme跳转到淘宝商品详情页 唤醒app

    最近涉及的一个业务,在app内的一个广告,点击打开webView,加载的是一个淘宝商品详情页,效果是打开该webView自动跳转至淘宝对应的页面,同时在自己的app仍然加载页面,点击评论等也同样能跳转 ...

  3. 成都app开发:架构一个App需要学会哪些技术呢?

    成都亿合科技小编为您分享: 随着APP应用的流行,越来越多的人想自己学习怎么开发APP应用,那架构一个APP需要学些什么技术呢?首先要了解App都有哪些类型,不同的类型适用于哪些需求,用户可以根据自己 ...

  4. 微信小程序开发——打开另一个小程序

    微信小程序打开另一个小程序,有两种方法:1.超链接:2.点击按钮. 全局配置: 跳转到其他小程序,需要在当前小程序全局配置中配置需要跳转的小程序列表,代码如下: App.json { ... &quo ...

  5. 打开另外一个App

    /** * 打开一个app * * @param packageName * @param data * @return */ public static boolean lanuchApp(Cont ...

  6. 为什么可以通过URL来调起APP - URL Scheme和Intent

    在手机浏览器中可以通过URL调起APP是不是很神奇?这篇文章就告诉你为什么. URL Scheme 先从前端能接触到的URL Scheme分析一下 丢wiki:https://en.wikipedia ...

  7. URL Scheme与openURL

    URL Schemes URL Schemes是苹果给出的用来跳转到系统应用或者跳转到别人的应用的一种机制.同时还可以在应用之间传数据. 设置一个URL Schemes:选中App工程->Inf ...

  8. 【转】使用Xcode中的iOS SDK给iphone开发出第一个App程序

    之前已经折腾过用Xcode开发OS X的程序了,现在继续折腾,用iOS SDK开发移动设备(iphone/ipad/ipod touch)的程序. 1.从iOS Developer Library中找 ...

  9. 李洪强iOS开发之最全App上架流程

    在上架App之前想要 真机测试的同学 请查看 iOS- 最全的真机测试教程 里面包含怎么让多台电脑同时 上架App和同时真机调试.P12文件的使用详解 准备 开发者账号 完工的项目 上架步骤 一.创建 ...

随机推荐

  1. Linux下socket通信和epoll

    上一篇博客用多线程实现服务端和多个客户端的通信,但是在实际应用中如果服务端有高并发的需求,多线程并不是一个好选择. 实现高并发的一种方法是IO多路复用,也就是select,poll,epoll等等. ...

  2. 南阳nyoj 56 阶乘因式分解(一)

    阶乘因式分解(一) 时间限制:3000 ms  |  内存限制:65535 KB 难度:2   描述 给定两个数m,n,其中m是一个素数. 将n(0<=n<=10000)的阶乘分解质因数, ...

  3. 解决:oracle+myBatis ResultMap 类型为 map 时返回结果中存在 timestamp 时使用 jackson 转 json 报错

    前言:最近在做一个通用查询单表的组件,所以 sql 的写法就是 select *,然后 resultType="map" ,然后使用 jackson @ResponseBody 返 ...

  4. JS实现继承的几种方式以及优缺点(转载)

    前言 JS作为面向对象的弱类型语言,继承也是其非常强大的特性之一.那么如何在JS中实现继承呢?让我们拭目以待. JS继承的实现方式 既然要实现继承,那么首先我们得有一个父类,代码如下: // 定义一个 ...

  5. 慕课网 深入浅出javascript 笔记

    javascript 数据类型 5种简单数据类型:Number.String.Boolean.Undefined.Null 1种复杂数据类型:Object =    表示赋值: ==  表示比较,但是 ...

  6. ArcGIS10.3+Oracle12C+ArcGIS Server10.3安装布署(之二)

    1.创建PDB 输入 dbca 命令 2.安装完成后,连接PDBSDE的容器数据库 3.环境变量 从Oracle的官方网站下载   instantclient-basic-nt-12.1.0.2.0. ...

  7. Java 之常用API(二)

    Object类 & System类 日期相关类 包装类 & 正则表达式 Object类 & System类 1.1 Object类 1.1.1 概述 Object类是Java语 ...

  8. Linux(CentOS)之-性能监控

    这篇主要讲一下Linux(CentOS)上性能性能监控的操作. 1.监控cpu使用情况--uptime 该命令将会打印出当前时间  系统运行了多久 当前登陆用户数  系统平均负载 这里的负载是单位时间 ...

  9. Python 3从入门到精通02-python的简单使用

    Python 3中的打印语句和字符串使用: Python中的常见数学运算: 这样的简单基础知识,你需要花5分钟就可以了,很基础的东西.

  10. leetCode题解之Contains Duplicate

    1.题目描述 2.题目分析 直接使用hashTable 计数,超过1 则返回true,最后返回 false即可. 3.代码 bool containsDuplicate(vector<int&g ...