URL Schemes深度剖析(上)

杭城小劉發表於2017-12-21

自定義URL Schemes

1、引言

URL Schemes 應用在 iOS 上已經很久了。對於使用者來說,在沙盒機制下的 iOS 中,如果想做到一定程度上的自動化就不可避免地要用到 URL Schemes。但因為 URL Schemes 的使用方式不像傳統 iOS 使用者接觸到的圖形介面那樣可以直觀地點來點去,造成了對它有興趣的人(尤其是對英文有恐懼的人)一定程度上理解的困難。

2、簡介蘋果的沙盒機制

蘋果選擇沙盒來保障使用者的隱私和安全,但沙盒也阻礙了應用間合理的資訊共享,於是有了 URL Schemes 這個解決辦法。

一般來說,我們使用的智慧裝置上有許多我們的個人資訊。比如:聯絡方式、銀行卡/信用卡資訊、支付寶/Paypal/各大商城的賬戶密碼、照片甚至行程與位置資訊等。

如果說,你裝置上的每一個應用,不管是官方的還是你從任何商城安裝的應用都可以隨意地獲取這些資訊,那麼你輕則收到騷擾資訊和郵件、重則後果不堪設想。如何讓這些資訊不被其它應用隨意使用,或者說,如何讓這些資訊僅在裝置所有者本人知情並允許的情況下被使用,是所有智慧裝置與作業系統所要在乎的核心安全問題。

在 iOS 這個作業系統中,針對這個問題,蘋果使用了名為「沙盒」的機制:應用只能訪問它宣告可能訪問的資源。一切提交到 App Store 的應用都必須遵守這個機制。

在安全方面沙盒是個很好的解決辦法,但是有些矯枉過正。敏感的個人資訊我們不願意透露,卻不代表所有的資訊我們都不想與其它應用共享。

比如說我們要一次性地(沒錯,只按一次)把多個事件放到日曆中,這些事件包含日期時間以及持續時間等資訊,如果 App 之間資訊不能溝通,就無法做到這點。(在下文中的 x-callback-URL 的部分會詳述整個過程)

類似於一次性新增多個日曆事件這樣的,我們在使用智慧裝置的過程中會遇到很多不必要的重複的步驟。大多數人對這些重複的步驟是不自覺的,就像當自己電腦裡有一批檔案需要批量重新命名的時候,他們機械地重複著重新命名的過程。但是當我們掌握了這些裝置執行的模式,或者有了一些工具,我們就能將這些重複的步驟全部節省下來。在 iOS 上,我們可以利用的工具就是 URL Schemes。

3、URL Schemes 是什麼

Custom URL scheme 的好處就是,你可以在其它程式中通過這個url開啟應用程式。如A應用程式註冊了一個url scheme:myApp, 那麼就在mobile瀏覽器中就可以通過<href=’myApp://’>開啟你的應用程式A。

對比網頁url就比較好理解url scheme。給出一個url “http://bxu2359670321.my3w.com/view/login.php”,它的格式:protocol :// hostname[:port] / path / [;parameters][?query]#fragment。 因此這個url的protocol就是http。對比URL Scheme,給出例子“weixin://dl/moments“,前面的weixin:就代表微信的scheme。你可以完全按照理解一個網頁的 URL ——也就是它的網址——的方式來理解一個 iOS 應用的 URL。即Scheme是**://**之前的那段字元

###注意###

1、所有的網頁都有url;但未必所有的應用都有自己的 URL Schemes,更不是每個應用的每個功能都有相應的 URL Schemes

2、一個網址只對應一個網頁,但並非每個 URL Schemes 都只對應一款應用。這點是因為蘋果沒有對 URL Schemes 有不允許重複的硬性要求

3、一般網頁的 URL 比較好預測,而 iOS 上的 URL Schemes 因為沒有統一標準,所以非常難猜,通過猜來獲取 iOS 應用的 URL Schemes 是不現實的。(我推薦將Bundle identifier反轉)

###上乾貨###

1、註冊自定義 URL Scheme

1)註冊自定義 URL Scheme 的第一步是建立 URL Scheme — 在 Xcode Project Navigator 中找到並點選工程 info.plist 檔案。當該檔案顯示在右邊視窗,在列表上點選滑鼠右鍵,選擇 Add Row:

url scheme1.png

2)點選左邊剪頭開啟列表,可以看到 Item 0,一個字典實體。展開 Item 0,可以看到 URL Identifier,一個字串物件。該字串是你自定義的 URL scheme 的名字。建議採用反轉Bundle idenmtifier的方法保證該名字的唯一性

url scheme2.png

3)點選 Item 0 新增一行,從下拉選單中選擇 URL Schemes,敲擊鍵盤迴車鍵完成插入。(注意 URL Schemes 是一個陣列,允許應用定義多個 URL schemes。)展開該資料並點選 Item 0。你將在這裡定義自定義 URL scheme 的名字。只需要名字,不要在後面追加 ://

url scheme3.png

2、拿瀏覽器坐簡單驗證

在位址列中熟入自定的url scheme。此時必須保證該瀏覽器所在裝置上已經安裝了具有自定義url scheme的App。

IMG_5739.PNG

3、新建Xcode工程,做個App試試看,這裡我就放一個Button,點選開啟url 程式碼。

- (IBAction)open:(id)sender {
    NSString *url = @"zhunaer://?name=lbp&age=22";
    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:url]]) {
           [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
    }else{
        NSLog(@"打不開");
    }
}
複製程式碼

結果打不開,為什麼? 因為在新建App的plist中沒加query schemes

<key>LSApplicationQueriesSchemes</key>
<array>
<string>zhunaer</string>
</array>
複製程式碼

4、如果需要在2個App之間傳值,怎麼辦?可以用URL Scheme解決。

在被開啟的App的Appdelegate.m中實現-(BOOL)application:(UIApplication *)application openURL:(nonnull NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(nonnull id)annotation;

-(BOOL)application:(UIApplication *)application openURL:(nonnull NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(nonnull id)annotation{
    NSLog(@"calling application bundle id: %@",sourceApplication);
    NSLog(@"url shceme:%@",[url scheme]);
    NSLog(@"引數:%@",[url query]);
    if ([sourceApplication isEqualToString:@"com.geek.test1"]) {
        return YES;
    }
    return NO;
    
}

複製程式碼

在需要開啟第三方App的點選事件處的url處後面加上引數,類似NSString *url = @"zhunaer://?name=lbp&age=22";

注意:在URL Scheme後加?然後跟網頁的url的引數一樣寫法。

5、如何判斷是指定App開啟,或者某些App不讓開啟我們的App? 做了實驗。

A:在需要開啟第三方App的工程中將Bundle identifier改為“com.geek.test2”,其餘不變

B:在被開啟的App的AppDelegate.m中

-(BOOL)application:(UIApplication *)application openURL:(nonnull NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(nonnull id)annotation{
    NSLog(@"calling application bundle id: %@",sourceApplication);
    NSLog(@"url shceme:%@",[url scheme]);
    NSLog(@"引數:%@",[url query]);
    if ([sourceApplication isEqualToString:@"com.geek.test1"]) {
        return YES;
    }
    return NO;
}
複製程式碼

Simulator Screen Shot 2017年5月1日 下午2.48.21.png

###實驗結果###

依舊可以開啟App,即使斷點走入Return NO

結論:如果你想阻止其它應用呼叫你的應用,建立一個與眾不同的 URL scheme。儘管這不能保證你的應用不會被呼叫,但至少大大降低了這種可能性。

參考:https://sspai.com/post/31500#01

相關文章