APP調(diào)用本機第三方APP

什么是URL Schemes?

URL Schemes是蘋果給出的用來跳轉(zhuǎn)到系統(tǒng)應(yīng)用或者跳轉(zhuǎn)到別人的應(yīng)用的一種機制。同時還可以在應(yīng)用之間傳數(shù)據(jù)。

通過對比網(wǎng)頁鏈接來理解 iOS 上的 URL Schemes,應(yīng)該就容易多了。URL Schemes 有兩個單詞:
URL,我們都很清楚,http://www.apple.com就是個 URL,我們也叫它鏈接或網(wǎng)址;
Schemes,表示的是一個 URL 中的一個位置——最初始的位置,即 ://之前的那段字符。比如 http://www.apple.com這個網(wǎng)址的 Schemes是 http。根據(jù)我們上面對 URL Schemes 的使用,
我們可以很輕易地理解,在以本地應(yīng)用為主的 iOS 上,我們可以像定位一個網(wǎng)頁一樣,用一種特殊的 URL 來定位一個應(yīng)用甚至應(yīng)用里某個具體的功能。而定位這個應(yīng)用的,就應(yīng)該是這個應(yīng)用的 URL 的 Schemes 部分,也就是開頭兒那部分。

調(diào)用方法

1.注冊APP URL Schemes

2.打開APP方法:

調(diào)用APP

URL Schemes://

OC調(diào)用方法:

簡單調(diào)用:

NSURL *url  = [NSURL URLWithString:@"myurltest:"];
[[UIApplication sharedApplication] openURL:url];

考慮到交互友好可以使用下面這種方法:


NSURL *url = [NSURL URLWithString:@"weixin://"];
 //先判斷是否能打開該url 
if ([[UIApplication sharedApplication] canOpenURL:url]) { //打開url
    [[UIApplication sharedApplication] openURL:url];
 }else { //給個提示或者做點別的事情 
NSLog(@"U四不四灑,沒安裝WXApp,怎么打開啊!");
}

先判斷本機是否安裝,若果安裝就打開APP,否則提示沒有安裝。這里你也可以做成沒有安裝的話就直接跳轉(zhuǎn)到APPStore.
更重要的是,假如點擊之后沒效果,很有可能被蘋果拒絕哦。

除了OC代碼打開的方式,平時測試過程你也可以直接通過safari 地址欄上輸入

URL Schemes://

來打開應(yīng)用。

這里給出一個操作DEMO

20141028105711041.gif

3.APP 回調(diào)處理

蘋果一共給了3個openURL的回調(diào)。

- (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個回調(diào)又有什么區(qū)別?(為方面講解,分別設(shè)置ABC3個回調(diào))
3個回調(diào)的功能基本一樣,都是在別人通過URL Schemes打開應(yīng)用的時候會執(zhí)行的。不同之處:

 A回調(diào)是在iOS2.0的時候推出的,參數(shù)只有url。
 B回到是在iOS4.2的時候推出的,參數(shù)有url sourceApplication annotation.
 C回調(diào)是iOS9.0的時候推出的,參數(shù)有url  options。

這幾個回調(diào)是有優(yōu)先級的。C>B>A。也就是說,如果你3個回調(diào)都實現(xiàn)了,那么程序只會執(zhí)行C回調(diào)。其他回調(diào)是不會執(zhí)行的。(當然,iOS9以下只會執(zhí)行B回調(diào))。

所以只要在被打開的App 的 appdelegate這個類里面實現(xiàn):

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

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options 

這兩個方法即可。

使用URL Schems傳遞數(shù)據(jù)

URL Schemes除了可以用來打開APP之外,還可以用來在兩個App之間傳遞少量的數(shù)據(jù)。

這里寫一個demo來說明URL的組成結(jié)構(gòu)

NSURL *url = [NSURL URLWithString:@"http://www.baidu.com/s?tn=baiduhome_pg&bs=NSRUL&f=8&rsv_bp=1&rsv_spt=1&wd=NSurl&inputT=2709"];  
      
    NSLog(@"Scheme: %@", [url scheme]);  
      
    NSLog(@"Host: %@", [url host]);  
      
    NSLog(@"Port: %@", [url port]);  
      
    NSLog(@"Path: %@", [url path]);  
      
    NSLog(@"Relative path: %@", [url relativePath]);  
      
    NSLog(@"Path components as array: %@", [url pathComponents]);  
      
    NSLog(@"Parameter string: %@", [url parameterString]);  
      
    NSLog(@"Query: %@", [url query]);  
      
    NSLog(@"Fragment: %@", [url fragment]);  
      
    NSLog(@"User: %@", [url user]);  
      
    NSLog(@"Password: %@", [url password]);  

輸出結(jié)果:

2012-08-29 15:52:23.781 NSurl[3560:f803] Scheme: http  
2012-08-29 15:52:32.793 NSurl[3560:f803] Host: www.baidu.com  
2012-08-29 15:52:39.102 NSurl[3560:f803] Port: (null)  
2012-08-29 15:52:42.590 NSurl[3560:f803] Path: /s  
2012-08-29 15:52:52.516 NSurl[3560:f803] Relative path: /s  
2012-08-29 15:53:05.576 NSurl[3560:f803] Path components as array: (  
    "/",  
    s  
)  
2012-08-29 15:53:32.861 NSurl[3560:f803] Parameter string: (null)  
2012-08-29 15:53:37.528 NSurl[3560:f803] Query: tn=baiduhome_pg&bs=NSRUL&f=8&rsv_bp=1&rsv_spt=1&wd=NSurl&inputT=2709  
2012-08-29 15:53:52.942 NSurl[3560:f803] Fragment: (null)  
2012-08-29 15:53:54.539 NSurl[3560:f803] User: (null)  
2012-08-29 15:53:57.808 NSurl[3560:f803] Password: (null)  

我們需要的是query 里面的參數(shù)內(nèi)容,可以用[url query]方法取出,取出的內(nèi)容為NSstring 類型需要做字符串處理才能拿到對應(yīng)的數(shù)據(jù)。

為了讓程序結(jié)構(gòu)更加清晰我們這時更希望取出來的為字典類型。這樣就少了字符串處理過程,同時也增加了我們程序的可讀性。

這里貼上處理函數(shù):

//
//  NSMutableDictionary+URLParams.m
//  TrainStaff
//
//  Created by 逸信Mac on 2016/12/3.
//  Copyright ? 2016年 eshine-ios. All rights reserved.
//

#import "NSMutableDictionary+URLParams.h"

@implementation NSMutableDictionary (URLParams)

/**
 *  截取URL中的參數(shù)
 *
 *  @return NSMutableDictionary parameters
 */
+(NSMutableDictionary *)getURLParameters:(NSString *)urlStr
{
    
    // 查找參數(shù)
    NSRange range = [urlStr rangeOfString:@"?"];
    if (range.location == NSNotFound) {
        return nil;
    }
    
    // 以字典形式將參數(shù)返回
    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    
    // 截取參數(shù)
    NSString *parametersString = [urlStr substringFromIndex:range.location + 1];
    
    // 判斷參數(shù)是單個參數(shù)還是多個參數(shù)
    if ([parametersString containsString:@"&"]) {
        
        // 多個參數(shù),分割參數(shù)
        NSArray *urlComponents = [parametersString componentsSeparatedByString:@"&"];
        
        for (NSString *keyValuePair in urlComponents) {
            // 生成Key/Value
            NSArray *pairComponents = [keyValuePair componentsSeparatedByString:@"="];
            NSString *key = [pairComponents.firstObject stringByRemovingPercentEncoding];
            NSString *value = [pairComponents.lastObject stringByRemovingPercentEncoding];
            
            // Key不能為nil
            if (key == nil || value == nil) {
                continue;
            }
            
            id existValue = [params valueForKey:key];
            
            if (existValue != nil) {
                
                // 已存在的值,生成數(shù)組
                if ([existValue isKindOfClass:[NSArray class]]) {
                    // 已存在的值生成數(shù)組
                    NSMutableArray *items = [NSMutableArray arrayWithArray:existValue];
                    [items addObject:value];
                    
                    [params setValue:items forKey:key];
                } else {
                    
                    // 非數(shù)組
                    [params setValue:@[existValue, value] forKey:key];
                }
                
            } else {
                
                // 設(shè)置值
                [params setValue:value forKey:key];
            }
        }
    } else {
        // 單個參數(shù)
        
        // 生成Key/Value
        NSArray *pairComponents = [parametersString componentsSeparatedByString:@"="];
        
        // 只有一個參數(shù),沒有值
        if (pairComponents.count == 1) {
            return nil;
        }
        
        // 分隔值
        NSString *key = [pairComponents.firstObject stringByRemovingPercentEncoding];
        NSString *value = [pairComponents.lastObject stringByRemovingPercentEncoding];
        
        // Key不能為nil
        if (key == nil || value == nil) {
            return nil;
        }
        
        // 設(shè)置值
        [params setValue:value forKey:key];
    }
    
    return params;
}

@end

使用DEMO:

-(BOOL)application:(UIApplication *)application openURL:(nonnull NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(nonnull id)annotation
{
    NSString *schemeVal = [url scheme];
    if([schemeVal  isEqualToString:@"xyjtrain"]){
        NSMutableDictionary *dic = [NSMutableDictionary getURLParameters:[url absoluteString]];
        NSString *cookieVal = dic[@"cookie"];
        
        if(NotNilAndNull(cookieVal)){
         
        }
    }
    return NO;
}

iOS9中的適配

配置URL Schemes白名單

iOS9的時候蘋果加強了權(quán)限,只有在info.plist文件中加入了URL Schemes白名單才能使用canOpenURL:方法來判斷是否能打開該url。該白名單的上限是50個。也就是說,你最多只能使用canOpenURL:方法判斷50個URL Schemes。當然,平常我們都用不了那么多,就算是集成分享功能,50個肯定夠了。

備注:只是對canOpenURL:方法有限制,openURL:方法是沒有限制的。

我們需要在MyApp的info.plist里面將weixin
設(shè)置為白名單。
步驟:

點擊info.plist->右鍵->Open As->Source Code->添加下面的代碼

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

問題

多個應(yīng)用設(shè)置相同的URL Scheme 會怎么樣?

這個URL Schemes并不是唯一的。也就是說,多個應(yīng)用之間設(shè)置的URL Schemes是可以相同的。
那么問題來了,假如兩個應(yīng)用的URL Schemes相同的話,使用openURL:方法會打開哪個應(yīng)用呢?
樓主親自用手機試了一下。
步驟是:
將MyApp安裝到手機上,點擊“打開微信”button,微信打開了。
然后將WXApp也安裝到手機上。再次點擊MyApp的“打開微信”button,結(jié)果打開的是WXApp。

結(jié)論:如果兩個應(yīng)用有URL Schemes是相同的,后安裝的應(yīng)用的URL Schemes會把早安裝的應(yīng)用的URL Schems覆蓋掉。

附上常用的URL Schemes:

QQ的url是 mqq:// 
微信是weixin:// 
淘寶taobao:// 
點評dianping:// dianping://search 
微博 sinaweibo:// 
weico微博weico:// 
支付寶alipay:// 
美團 imeituan:// 
京冬openapp.jdmoble:// 
人人renren:// 
1號店wccbyihaodian:// 
有道詞典yddictproapp:// 
優(yōu)酷 youku://

/****6月2日更新****/
最近蘋果剛更新了IOS10.3,無意中發(fā)現(xiàn)了一個關(guān)于URL Scheme調(diào)整的問題,準確的說是URL Scheme命名的問題。官方對URL Scheme的命名做了規(guī)范限制:命名要小寫!但是到目前來看大寫小寫都是可以成功喚起的,也就是說無論大寫還是小寫跳轉(zhuǎn)都是沒有任何影響的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容