iOS-App相互跳转之URL Scheme操作流程

老规矩,站在巨人的肩膀上才能看得更远:
本知识相关简书文章传送门
本知识涉及到APP Url Scheme 前缀,CSDN文章传送门

OK,看过大佬的文章,现在开始我的文章吧!

一、 创建两个工程,并配置URL和白名单

1.0 创建两个项目,发出拉起的App:AppMailing,被拉起的App:AppPulledAim;

2.0 设置AppMailing的URL:一般有两种方式:Info.plist中和 Targets中info下的URL TYPE中,两种方式是一样的,且设置一个后另一个也会生效,如下图:

注:URL和项目名称可以没关系

Info.plist.png
Targets中info下的 URL TYPE.png

3.0 同理设置AppPulledAim的url:


AppPulledAim的url.png

4.0 设置AppMailing的白名单

白名单:以后要跳入App的URL Scheme的集合。这个是放在Info.plist的,所以最好一次性想好所跳的App,否则很容易因为新增一个要跳入的App而重新上架App。

在Info,plist中添加LSApplicationQueriesSchemes的「数组」,然后添加String类型的元素,这个元素就是要跳入App的URL Scheme。


添加白名单.png

如果这一步没有在Info.plist添加要跳App的URL Scheme,代码直接写了跳转(下面有说这部分),会在控制台报下面的错误,下面是把微信的删了出现的错误信息:

-canOpenURL: failed for URL: "weixin://" - error: "This app is not allowed to query for scheme weixin"

二、实现跳转代码

1.0 在AppMailing中编写拉起代码:

a.编写要跳的App URL,并判断手机内是否存在此App,成熟App的URL Scheme网上一搜一大堆,这里就不贴了

NSURL *appUrl = [NSURL URLWithString:@"alipay://"];//要跳转至App的Url Scheme 前缀,注意这个前缀需要添加在Info.plist文件LSApplicationQueriesSchemes下面
BOOL appIsExist = [[UIApplication sharedApplication] canOpenURL:appUrl];//判断该App在手机内是否存在

b.如果有,就进行跳转

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@", appUrl]] options: dic completionHandler:^(BOOL success) {
            NSLog(@"嘿,我打开过了");
        }];

c.如果没有,可以直接弹出一个提示框,但是并不是很友好,最好的做法是链接到下载页面,这里的下载页面分为两种,一种是跳入到AppStore的下载页面,一种是直接在本App打开要下载App的下载页面,说简单点两种方法就是少了一个跳AppStore步骤
第一种方案:调至AppStore

        NSString *str = @"https://apps.apple.com/cn/app/支付宝-生活好-支付宝/id333206289";//如果没有安装就调至该App在AppStore的下载页面中。
        NSString *str1 = [str stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];//将url中的汉字进行Encoding转发,不转发无法跳转
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:str1] options:dic completionHandler:^(BOOL success) {
            NSLog(@"成功到达AppStore");
        }];

第二种方案:直接在本App打开要下载App的下载页面
首先,添加StoreKit.framework


添加StoreKit.framework.png

然后,在要做跳转的VC中引入头文件,遵守<SKStoreProductViewControllerDelegate>代理,

#import <StoreKit/StoreKit.h>

SKStoreProductViewController *storeProductViewContorller = [[SKStoreProductViewController alloc] init];
        //设置代理请求为当前控制器本身
        storeProductViewContorller.delegate = self;
        //加载一个新的视图展示
        [storeProductViewContorller loadProductWithParameters:
         //appId唯一的
         @{SKStoreProductParameterITunesItemIdentifier : @"333206289"} completionBlock:^(BOOL result, NSError *error) {//这个ID就是要下App的ID,可以去AppStore里面查出来,就是把该App在AppStore的下页面分享到浏览器就可以做到了
             //block回调
             if(error){
                 NSLog(@"error %@ with userInfo %@",error,[error userInfo]);
             }else{
                 //模态弹出appstore
                 [self presentViewController:storeProductViewContorller animated:YES completion:^{

                 }
                  ];
             }
        }];

#pragma mark- SKStoreProductViewControllerDelegate的代理方法:当点击下载页面左上角完成时,退出当前下载页面
-(void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController {
    [self dismissViewControllerAnimated:YES completion:nil];
}

获取要跳转App的下载链接和ITunesItemIdentifier.png

d.总结下上面的代码

- (IBAction)mailingFaile:(id)sender {
    NSURL *appUrl = [NSURL URLWithString:@"alipay://"];//要跳转至App的Url Scheme 前缀,注意这个前缀需要添加在Info.plist文件LSApplicationQueriesSchemes下面
    BOOL appIsExist = [[UIApplication sharedApplication] canOpenURL:appUrl];//判断该App在手机内是否存在
    
    NSDictionary *dic = [NSDictionary dictionary];//主要防止下面option传入nil报警告
    if (appIsExist) {//装了
        
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@", appUrl]] options: dic completionHandler:^(BOOL success) {
            NSLog(@"嘿,我打开过了");
        }];
    }else{//没装
        NSLog(@"没安装");
        /*
        //第一种方案:调至AppStore
        NSString *str = @"https://apps.apple.com/cn/app/支付宝-生活好-支付宝/id333206289";//如果没有安装就调至该App在AppStore的下载页面中。
        NSString *str1 = [str stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];//将url中的汉字进行Encoding转发,不转发无法跳转
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:str1] options:dic completionHandler:^(BOOL success) {
            NSLog(@"成功到达AppStore");
        }];
        */
        
         //第二种方案:直接在本App中展示AppStore中的下载页面
        SKStoreProductViewController *storeProductViewContorller = [[SKStoreProductViewController alloc] init];
        //设置代理请求为当前控制器本身
        storeProductViewContorller.delegate = self;
        //加载一个新的视图展示
        [storeProductViewContorller loadProductWithParameters:
         //appId唯一的
         @{SKStoreProductParameterITunesItemIdentifier : @"333206289"} completionBlock:^(BOOL result, NSError *error) {
             //block回调
             if(error){
                 NSLog(@"error %@ with userInfo %@",error,[error userInfo]);
             }else{
                 //模态弹出appstore
                 [self presentViewController:storeProductViewContorller animated:YES completion:^{

                 }
                  ];
             }
        }];
         
    }
}

#pragma mark- SKStoreProductViewControllerDelegate的代理方法:当点击下载页面左上角完成时,退出当前下载页面
-(void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController {
    [self dismissViewControllerAnimated:YES completion:nil];
}

2.0 被拉起的App:AppPulledAim中的代码
这里涉及到兼容iOS13以下的问题,需要在AppDelegate.m和SceneDelegate.m中同时设置接收跳转的代码

AppDelegate.m

-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{
    NSString *openURLOptionsSourceApplicationValue = options[@"UIApplicationOpenURLOptionsSourceApplicationKey"];//得出这是从AppMailing跳过来的
    if ([openURLOptionsSourceApplicationValue isEqualToString:@"cn.people.AppMailing"]) {
        if ([url.host isEqualToString:@"canshu"]) {
            NSLog(@"%@",url.query);
            NSDictionary *dict = @{@"canshu":url.query};
            [[NSNotificationCenter defaultCenter]postNotificationName:@"showAppMailingCanShu" object:nil userInfo:dict];
        }
    }
    return YES;
}
SceneDelegate.m
-(void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts API_AVAILABLE(ios(13.0)){
    NSURL *url = URLContexts.allObjects.firstObject.URL;
    UISceneOpenURLOptions *options = URLContexts.allObjects.firstObject.options;//得出这是从AppMailing跳过来的
    if ([options.sourceApplication isEqualToString:@"cn.people.AppMailing"]) {
        if ([url.host isEqualToString:@"canshu"]) {
            NSLog(@"%@",url.query);
            NSDictionary *dict = @{@"canshu":url.query};
            [[NSNotificationCenter defaultCenter]postNotificationName:@"showAppMailingCanShu" object:nil userInfo:dict];
        }
    }
}

这里处理完接收后,就在相应界面进行接收传值就行了:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showAppMailingMethod:) name:@"showAppMailingCanShu" object:nil];
    
    float viewWidth = [UIScreen mainScreen].bounds.size.width;
    float labelX = (viewWidth-300)*0.5;
    float viewHeight = [UIScreen mainScreen].bounds.size.height;
    float labelY = (viewHeight-50)*0.5;
    
    self.showLabel = [[UILabel alloc] initWithFrame:CGRectMake(labelX, labelY, 300, 50)];
    self.showLabel.text = @"初始值";
    self.showLabel.textAlignment = NSTextAlignmentCenter;
    [self.view addSubview:self.showLabel];
    // Do any additional setup after loading the view.
}

-(void)showAppMailingMethod:(NSNotification *)noti{
    NSString *str = noti.userInfo[@"canshu"];
    NSLog(@"%@",str);
    self.showLabel.text = str;
}

-(void)dealloc{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
}

注:
NO.1 我写Demo的时候出现过拿到链接后跳转显示的成功,但是App并没有跳转的情况,分析过之后发现是因为链接里面中文,需要发之前对中文进行 Encoded ,接收后对数据进行Decoded。
NO.2 关于App跳转时候传值的问题,上面已经写了,就是利用url,比如url.host和url.query,同理也需要Encoded与Decoded。

AppMailingDemo:https://github.com/JerryDJX/AppMailing.git
AppPulledAimDemo: https://github.com/JerryDJX/AppPulledAim.git

另一种使用Universal Link的方式进行跳转:https://www.cnblogs.com/guoshaobin/p/11164000.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容