iOS URL Schemes实现APP之间的跳转

一、应用场景

我们的APP有时候想直接去到设置页面,程序退到后台进入设置页面然后又重新打开,这样子总是感觉多做了很多事情。有一个比较常见的例子就是一开始的时候用户关闭了APP的通知功能,APP就需要加个直接去到自己APP打开通知开关的页面。APP之前的跳转也是很常见的。以此知道这个知识点还是比较需要的。

二、URL Schemes 配置

配置

说明:

  1. prefs“实现跳转至苹果内置程序的url scheme,不可改变
  2. phzAppJumpDemo: 标识该应用程序的url scheme,尽量保持它的唯一性
ios9之后需要添加跳转白名单

Source Code模式打开info.plist文件,添加一下这个LSApplicationQueriesSchemes,里面的数组就是需要跳转的APP

<key>LSApplicationQueriesSchemes</key>
    <array>
        <string>weibosdk</string>
        <string>pcbabybrowserbeta</string>
        <string>pcbabybrowserpub</string>
        <string>tencentopenapi</string>
        <string>mqzone</string>
        <string>wtloginmqq2</string>
        <string>mqqbrowser</string>
        <string>mqqwpa</string>
        <string>mqqapi</string>
        <string>mqq</string>
        <string>mqqopensdkapiV3</string>
        <string>mqqOpensdkSSoLogin</string>
        <string>mqqopensdkapiV2</string>
        <string>qqplugin</string>
        <string>sinaweibo</string>
        <string>weixin</string>
        <string>taobao</string>
        <string>tmall</string>
        <string>openApp.jdMobile</string>
    </array>

另外一种配置 URL types

三、代码解释

我们用到的是UIApplicationopenURL方法

  1. 跳转到内置程序:prefs:root=General。重点是root的值,具体的可以看下后面提供的一些值,如果有不能用的替换成正确的就ok了

  2. 跳转到对应app的某个系统位置:比如定位、通知位置等.prefs:root=NOTIFICATIONS_ID&&path=com.tencent.mqq后面的path就是需要打开的APP的bundle id (程序的后面有给出获取bundle id的代码),root的值跟第一点提到的是一致的

  3. 跳转到某个app里面:需要用到的就是上面提到的phzAppJumpDemo ,如果发现有两个相同的url scheme,会打开最近一次启动过的app

  4. openUrl还可以实现打开mail、电话、sms、Safari等

     调用自带mail:
     [[UIApplicationsharedApplication] openURL [NSURLURLWithString:@"mailto://邮箱"]];
    
     调用电话phone:
     [[UIApplication sharedApplication] openURL:[NSURLURLWithString:@"tel://电话"]];
    
     调用SMS:[[UIApplicationsharedApplication] openURL:[NSURL URLWithString:@"sms://号码"]];
    
     调用自带浏览器safari:
     [[UIApplicationsharedApplication] openURL:[NSURLURLWithString:@"http://www.baidu.com"]];
    
     调用Remote:[[UIApplicationsharedApplication] openURL:[NSURL URLWithString:@"remote://***"]]; 
    

四、代码块

1、跳转到系统应用,ios11之后只能跳转到设置首页以及对应APP的权限详情页

如何检测iOS里安装的其它软件?
iOS 获取手机上已经安装的应用
介绍runtime方法的一个demo

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSArray *nameArr = @[@"setting",@"general",@"location",@"tencentqq",@"safari",@"anApp"];
    for (int i = 0; i < nameArr.count; i ++) {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        button.frame = CGRectMake(100, 60 + 35 * i, 100, 30);
        NSString *nameS = nameArr[i];
        [button setTitle:nameS forState:UIControlStateNormal];
        button.tag = nameS.hash;
        button.backgroundColor = [UIColor cyanColor];
        [button addTarget:self action:@selector(entrePage:) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:button];
    }
    
    [self getAllBundleIdInDevice];
}
/**
 prefs这个前缀是固定的
 */
- (void)entrePage:(UIButton *)button {
    NSInteger tag = button.tag;
    if (tag == @"setting".hash) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
    } else if (tag == @"general".hash) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=General"]];
    } else if (tag == @"location".hash) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=LOCATION_SERVICES"]];
    } else if (tag == @"tencentqq".hash) {
        // 跳转到对应app的某个系统位置:比如定位、通知位置等
        //root的值是可以改变的(参见location_prefs文件中的root值) , path 就是app的bundle id
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=NOTIFICATIONS_ID&&path=com.tencent.mqq"]];
    } else if (tag == @"safari".hash) {
        // 跳转到safari
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://blog.csdn.net/likendsl/article/details/7553605"]];
    } else if (tag == @"anApp".hash) {
        // 跳转到某个app里面:其实是相当于打开推送消息
        // 这样有个问题,跳转过去后设备左上角没有返回到上个页面的按钮?iPhone6s ios9.2.1
        //如果有两个一样的Url Schemes 跳转的最近一次启动的app
        NSURL *myURL = [NSURL URLWithString:@"phzAppJumpDemo://"];
        [[UIApplication sharedApplication] openURL:myURL];
    }
}


//获取设备上的bundle id 需要引入这个类 #import <objc/runtime.h>
- (void)getAllBundleIdInDevice {
    Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
    NSObject* workspace = [LSApplicationWorkspace_class performSelector:@selector(defaultWorkspace)];
    NSLog(@"apps: %@", [workspace performSelector:@selector(allApplications)]);
}
2、一个跳转到淘宝的示例

iOS 跳转淘宝、天猫、京东商品详情页

+ (BOOL)jumpToTaobaoLink:(NSString *)toUri {
    if (0 == toUri.length) {
        return NO;
    }
    
    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"taobao://"]] && ([toUri hasPrefix:@"http://"] || [toUri hasPrefix:@"https://"])) {
        NSURL *oriUrl = [NSURL URLWithString:toUri];
        if ([[oriUrl host] rangeOfString:@"taobao.com"].location != NSNotFound) {
            NSString *openUrl = nil;
            if ([toUri hasPrefix:@"http://"]) {
                openUrl = [toUri stringByReplacingCharactersInRange:NSMakeRange(0, @"http://".length) withString:@"taobao://"];
            } else if ([toUri hasPrefix:@"https://"]) {
                openUrl = [toUri stringByReplacingCharactersInRange:NSMakeRange(0, @"https://".length) withString:@"taobao://"];
            } else {
                openUrl = toUri;
            }
            
            if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:openUrl]]) {
                // 淘宝客户端打开
                [[UIApplication sharedApplication] openURL:[NSURL URLWithString:openUrl]];
                return YES;
            }
        }
    }
    return NO;
}

五、附

一些常见的调用系统应用url

About — prefs:root=General&path=About
Accessibility — prefs:root=General&path=ACCESSIBILITY
Airplane Mode On — prefs:root=AIRPLANE_MODE
Auto-Lock — prefs:root=General&path=AUTOLOCK
Brightness — prefs:root=Brightness
Bluetooth — prefs:root=General&path=Bluetooth
Date & Time — prefs:root=General&path=DATE_AND_TIME
FaceTime — prefs:root=FACETIME
General — prefs:root=General
Keyboard — prefs:root=General&path=Keyboard
iCloud — prefs:root=CASTLE
iCloud Storage & Backup — prefs:root=CASTLE&path=STORAGE_AND_BACKUP
International — prefs:root=General&path=INTERNATIONAL
Location Services — prefs:root=LOCATION_SERVICES
Music — prefs:root=MUSIC
Music Equalizer — prefs:root=MUSIC&path=EQ
Music Volume Limit — prefs:root=MUSIC&path=VolumeLimit
Network — prefs:root=General&path=Network
Nike + iPod — prefs:root=NIKE_PLUS_IPOD
Notes — prefs:root=NOTES
Notification — prefs:root=NOTIFICATIONS_ID
Phone — prefs:root=Phone
Photos — prefs:root=Photos
Profile — prefs:root=General&path=ManagedConfigurationList
Reset — prefs:root=General&path=Reset
Safari — prefs:root=Safari
Siri — prefs:root=General&path=Assistant
Sounds — prefs:root=Sounds
Software Update — prefs:root=General&path=SOFTWARE_UPDATE_LINK
Store — prefs:root=STORE
Twitter — prefs:root=TWITTER
Usage — prefs:root=General&path=USAGE
VPN — prefs:root=General&path=Network/VPN
Wallpaper — prefs:root=Wallpaper
Wi-Fi — prefs:root=WIFI

苹果官方链接:https://developer.apple.com/library/ios/featuredarticles/iPhoneURLScheme_Reference/Introduction/Introduction.html

一篇很专业的分析文章
JailbreakHumhttp://sspai.com/31500

六、重要更新(2018/8/27)

苹果已经全面禁止跳转到对应的设置页了(比如蓝牙,WI-FI...),强行使用很大风险会被拒。也就是说包含prefs:root以及App-Prefs:root的代码得全部删除,在info.plist文件中的prefsApp-PrefsURLSchemes配置也要删掉。统一使用UIApplicationOpenSettingURLString,会跳转到对应app的设置页。

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

推荐阅读更多精彩内容