一、应用场景
我们的APP有时候想直接去到设置页面,程序退到后台进入设置页面然后又重新打开,这样子总是感觉多做了很多事情。有一个比较常见的例子就是一开始的时候用户关闭了APP的通知功能,APP就需要加个直接去到自己APP打开通知开关的页面。APP之前的跳转也是很常见的。以此知道这个知识点还是比较需要的。
二、URL Schemes 配置
说明:
-
prefs
“实现跳转至苹果内置程序的url scheme,不可改变 -
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
三、代码解释
我们用到的是UIApplication
的openURL
方法
跳转到内置程序:prefs:root=General。重点是root的值,具体的可以看下后面提供的一些值,如果有不能用的替换成正确的就ok了
跳转到对应app的某个系统位置:比如定位、通知位置等.
prefs:root=NOTIFICATIONS_ID&&path=com.tencent.mqq
后面的path就是需要打开的APP的bundle id (程序的后面有给出获取bundle id的代码),root的值跟第一点提到的是一致的跳转到某个app里面:需要用到的就是上面提到的
phzAppJumpDemo
,如果发现有两个相同的url scheme,会打开最近一次启动过的app-
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、一个跳转到淘宝的示例
+ (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
一篇很专业的分析文章
JailbreakHum的http://sspai.com/31500
六、重要更新(2018/8/27)
苹果已经全面禁止跳转到对应的设置页了(比如蓝牙,WI-FI...),强行使用很大风险会被拒。也就是说包含prefs:root
以及App-Prefs:root
的代码得全部删除,在info.plist文件中的prefs
和App-Prefs
的URLSchemes
配置也要删掉。统一使用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];
}
}
}