美文网首页
iOS-App相互跳转之URL Scheme操作流程

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

作者: 封丑儿 | 来源:发表于2021-02-24 14:48 被阅读0次

    老规矩,站在巨人的肩膀上才能看得更远:
    本知识相关简书文章传送门
    本知识涉及到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

    相关文章

      网友评论

          本文标题:iOS-App相互跳转之URL Scheme操作流程

          本文链接:https://www.haomeiwen.com/subject/rjpjfltx.html