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中,两种方式是一样的,且设置一个后另一个也会生效,如下图:
Info.plist.png Targets中info下的 URL TYPE.png注:URL和项目名称可以没关系
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