一曲初、URL Scheme 簡介和作用
相信大家都知道 URL酌毡,例如 http://www.reibang.com/ 就是一個URL唾那。
在 ://
之前的部分就稱為 URL Scheme刘离。
也就是說 http://www.reibang.com/ 的 URL Scheme 就是 http 媳瞪。
更多關于 URL參數(shù)介紹:NSURL簡介
由于蘋果的app都是在沙盒中,相互是不能訪問數(shù)據(jù)的仇味。但是蘋果還是給出了一個可以在app之間跳轉的方法:URL Scheme
竹揍。
簡單的說,URL Scheme 就是一個可以讓 app 相互之間可以跳轉的協(xié)議(例如上面的 http)邪铲。
每個app的 URL Scheme 都是不一樣的,如果存在一樣的 URL Scheme无拗,那么系統(tǒng)就會響應先安裝那個app的 URL Scheme带到,因為后安裝的app的 URL Scheme 被覆蓋掉了,是不能被調用的英染。
那么app之間的跳轉有什么作用呢揽惹?我們所使用的每一個app就相當于一個功能,app的跳轉可以使得每個app就像一個功能組件一樣四康,幫助我們完成需要做的事情搪搏,比如三方支付闪金,搜索论颅,導航囱嫩,分享等。
二墨闲、使用URL Scheme 跳轉到系統(tǒng)
要跳轉到別人的app,就要知道別人的app的跳轉協(xié)議是什么鸳碧,需要傳入什么參數(shù),我們常見的跳轉到系統(tǒng)有下面這些:
// 1.打開Mail
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"mailto:frank@wwdcdemo.example.com"]]
// 2.打開電話
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel:1-408-555-5555"]];
// 3.打開SMS
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"sms:1-408-555-1212"]];
有關系統(tǒng)支持的URL Scheme的詳細信息瞻离,請參閱 Apple URL Scheme Reference 和 iOS10如何跳轉到系統(tǒng)設置腾仅。
三、自定義 URL Scheme 進行跳轉
1琐脏、注冊自定義 URL Scheme
如果我們希望別人打開我們的 app(名字叫做 SchemeDemo)攒砖,需要注冊自定義 URL Scheme,通過 info.plist
--> URL Types
--> item0
--> URL Schemes
--> 你的TestScheme
來設置日裙,詳細步驟如下:
-
1吹艇、點擊工程中的
info.plist
文件,當該文件顯示在如下窗口時昂拂,在列表頂部鼠標選中Information Property List
受神,選擇+
,然后向下滾動彈出的列表并選擇URL types
格侯,類型為NSArray
鼻听。
添加 URL types -
2、點擊
URL types
左邊剪頭打開列表联四,可以看到Item 0
撑碴,一個字典實體。展開Item 0
朝墩,可以看到URL Identifier
醉拓,一個字符串對象。該字符串是你自定義的URL scheme
的名字收苏。建議采用反轉域名的方法保證該名字的唯一性亿卤,比如com.yourCompany.yourApp
。
設置 URL Identifier -
3鹿霸、點擊
Item 0
新增一行排吴,從下拉列表中選擇URL Schemes
,敲擊鍵盤回車鍵完成插入懦鼠。注意URL Schemes
是一個數(shù)組钻哩,允許應用定義多個URL schemes
屹堰。
添加 URL Schemes
URL Schemes 是一個數(shù)組 -
4、展開
URL Schemes
該數(shù)據(jù)并點擊Item 0
憋槐。你將在這里定義自定義URL scheme
的名字双藕。只需要名字,不要在后面追加://
阳仔,比如,如果你輸入iOSDevApp
嘶摊,你的自定義 url 就是iOSDevApp://
叶堆。
添加 URL Scheme 名字
此時虱颗,整個定義如下圖:
2忘渔、從 Safari 中調用自定義 URL Scheme
使用模擬器調用應用的步驟:
在 Xcode 中運行應用
一旦應用被安裝畦粮,自定義 URL scheme 就會被注冊
通過模擬器的硬件菜單中選擇 Home 來關閉應用
啟動 Safari
在瀏覽器地址欄輸入之前定義的 URL scheme (如下)
- 點擊回車宣赔,彈出提示框 (如下)
- 點擊
打開
此時 Safari 將會進入后臺儒将,應用會被帶回到前臺钩蚊。
祝賀你剛剛使用自定義 URL scheme 調用了一個 iPhone 應用。
3床估、從另一個應用( NewDemo
)中調用( SchemeDemo
中的 )自定義 URL Scheme
新建一個應用 NewDemo
丐巫,來調用 SchemeDemo
中自定義的 URL scheme
谣拣。
新建應用 NewDemo
只有一個 UIButton
赡茸,點擊這個按鈕則會通過應用(SchemeDemo
)自定義的 URL scheme
來調用應用(SchemeDemo
)占卧。
在按鈕點擊方法 clickBtn
中代碼處理 URL 調用:
- (void)clickBtn {
NSString *urlString = @"iOSDevApp://";
// 若有中文傳輸需要進行轉義
NSString *customURL = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
// 檢查自定義 URL 是否被定義华蜒,如果定義了叭喜,則使用 shared application 實例來打開 URL
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:customURL]]) {
// openURL: 方法啟動應用并將 URL 傳入應用捂蕴,在此過程中啥辨,當前的應用進入后臺
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:customURL]];
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"URL error" message:[NSString stringWithFormat:@"No custom URL defined for %@", customURL] delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
[alert show];
}
}
如果你的系統(tǒng)版本低于 iOS 9委可,那么已經可以進行調用了着倾,但是如果是在 iOS 9及以后的系統(tǒng)版本中仍會出現(xiàn)無法調用燕少,并在控制臺輸出如下錯誤:
-canOpenURL: failed for URL: "iOSDevApp://" - error: "This app is not allowed to query for scheme iosdevapp"
原因:因為從 iOS 9 開始系統(tǒng)引入了 LSApplicationQueriesSchemes
客们,就是白名單。
用意:當前App允許訪問的App有哪些恒傻,需要通信雙方均設置為對方的 scheme盈厘,否則當調用對方App時沸手,系統(tǒng)會告訴你 This app is not allowed to query for scheme
。
調用者和被調用者均需要設置白名單跳仿,一方想調用捐晶,另一方需要也知道將被你調用 租悄,更為安全。
解決辦法:此時需要在 NewDemo 和 SchemeDemo 中的 info.plist 里面相互設置為白名單(LSApplicationQueriesSchemes)胶哲。詳情如下:This app is not allowed to query for scheme
設置好之后重新運行就可以了:點擊打開就可以跳轉到 SchemeDemo
中了鸯屿。
4寄摆、通過自定義 URL Scheme 向應用傳遞參數(shù)
有時你需要通過自定義 URL 向應用中傳遞參數(shù)婶恼。讓我們看看該如何完成這個工作柏副。
NSURL 作為從一個應用調用另一個的基礎割择,遵循 RFC 1808 (Relative Uniform Resource Locators) 標準。 因此你所熟悉的基于網頁內容的 URL 格式在這里也適用蕉饼。
在自定義了 URL scheme 的應用中昧港,AppDelegate 必須實現(xiàn)以下方法:
// iOS 9.0前方法
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation;
// iOS 9.0后方法
- (BOOL)application:(UIApplication *)app openURL:(nonnull NSURL *)url options:(nonnull NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options;
從一個應用傳遞參數(shù)到另一個的訣竅是通過 URL创肥。例如,假設我們使用以下的 URL scheme,想傳遞一個名為 “token”的參數(shù)和一個標識注冊狀態(tài)的標志圈膏,我們可以像這樣創(chuàng)建一個 URL:
// 若有中文傳輸需要進行轉義
NSString *customURL = @"iOSDevTips://?token=123abct®istered=1";
在 web 開發(fā)中稽坤,字符串 ?token=123abct®istered=1
被稱作查詢字符串(query string)糯俗。
在被調用(設置了自定義 URL)的應用的 AppDelegate 中得湘,獲取參數(shù)的代碼如下:
// iOS 9.0前方法
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
NSLog(@"Calling Application Bundle ID: %@", sourceApplication);
NSLog(@"URL scheme: %@", [url scheme]);
NSLog(@"URL query: %@", [url query]);
return YES;
}
// iOS 9.0后方法
- (BOOL)application:(UIApplication *)app openURL:(nonnull NSURL *)url options:(nonnull NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
NSLog(@"options: %@", options);
NSLog(@"Calling Application Bundle ID: %@", [options objectForKey:@"UIApplicationOpenURLOptionsSourceApplicationKey"]);
NSLog(@"URL scheme: %@", [url scheme]);
NSLog(@"URL query: %@", [url query]);
return YES;
}
在 iOS 9.0 之后淘正,以上代碼在應用被調用時的輸出如下:
options: {
UIApplicationOpenURLOptionsOpenInPlaceKey = 0;
UIApplicationOpenURLOptionsSourceApplicationKey = "--.NewDemo";
}
Calling Application Bundle ID: --.NewDemo
URL scheme: iOSDevApp
URL query: token=123abct®istered=1
注意 “Calling Application Bundle ID”鸿吆,你可以用這個來確保只有你定義的應用可以與你的應用直接交互。
讓我們改變一下代碼蕉毯,來驗證發(fā)起調用的應用的 Bundle ID 是否合法:
// iOS 9.0前方法
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
NSLog(@"Calling Application Bundle ID: %@", sourceApplication);
NSLog(@"URL scheme: %@", [url scheme]);
NSLog(@"URL query: %@", [url query]);
// Check the calling application Bundle ID
if ([sourceApplication isEqualToString:@"--.NewDemo"]) {
return YES;
}
return NO;
}
// iOS 9.0后方法
- (BOOL)application:(UIApplication *)app openURL:(nonnull NSURL *)url options:(nonnull NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
NSLog(@"options: %@", options);
NSLog(@"Calling Application Bundle ID: %@", [options objectForKey:@"UIApplicationOpenURLOptionsSourceApplicationKey"]);
NSLog(@"URL scheme: %@", [url scheme]);
NSLog(@"URL query: %@", [url query]);
// Check the calling application Bundle ID
if ([[options objectForKey:@"UIApplicationOpenURLOptionsSourceApplicationKey"] isEqualToString:@"--.NewDemo"]) {
return YES;
}
return NO;
}
有一點要特別注意,你不能阻止其他應用通過自定義 URL scheme 調用你的應用抒倚,然而你可以跳過后續(xù)的操作并返回 NO,就像上面的代碼那樣含蓉。也就是說项郊,如果你想阻止其它應用調用你的應用着降,創(chuàng)建一個與眾不同的 URL scheme。盡管這不能保證你的應用不會被調用蓄喇,但至少大大降低了這種可能性。