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中引入头文件,遵守代理,

#import 

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 *)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 *)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操作流程)