【轉】【iOS開發】打開另外一個APP(URL Scheme與openURL)

目標

日常咱們作iOS開發,會常常遇到打開其餘的APP的功能。本篇文章講的就是打開別人的APP的一些知識。咱們的目標是:ios

  • 打開別人的APP
  • 讓別人打開咱們的APP
  • iOS9的適配問題
  • 使用URL Schemes傳遞數據

準備工做

  • 創建一個名爲OpenApp的工做空間,用來存放咱們的兩個工程
    創建這個工做空間主要是爲了讓咱們後面創建的兩個工程能在一個Xcode頁面上管理,方便講解和管理。挺簡單的,不清楚的能夠看我以前的文章【iOS開發】在一個Xcode頁面創建多個工程

創建一個workspace來存放咱們的工程
  • 創建一個名爲MyApp的iOS工程。這個MyApp是「個人app」,用來打開另外一個APP的。
    添加工程到咱們剛纔建立的OpenApp.xcworkspace。而且在工程的Main.storyboard添加一個button,待會兒咱們會用來寫方法。git


    MyApp工程
  • 創建一個名爲WXApp的iOS工程。這個工程是咱們模擬的「微信APP」,是被人打開的那個APP。
    爲了區分兩個應用,咱們在Main.storyboard上加一個label,「我是微信App」。github


    在workspace創建WXApp工程

WXApp

好了,準備工做就這麼簡單。瀏覽器

打開別人的APP與讓別人打開咱們的APP

想要打開別人的APP或者讓別人打開咱們的APP,那就須要經過URL Schemes了。微信

什麼是URL Schemes?

URL Schemes是蘋果給出的用來跳轉到系統應用或者跳轉到別人的應用的一種機制。同時還能夠在應用之間傳數據。app

經過對比網頁連接來理解 iOS 上的 URL Schemes,應該就容易多了。
URL Schemes 有兩個單詞:ui

  • 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欄填上 weixinurl


添加一個URL Schemes

備註:一個應用是能夠有多個URL Schemes的。你能夠再次點擊「+」來添加一個URL Schemesspa

咱們看看info.plist文件裏面是怎樣的。3d


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

相關文章
相關標籤/搜索