您的位置:时时app平台注册网站 > 编程知识 > 私有API-iOS10 openURL方法跳转到设置界面失效的解决

私有API-iOS10 openURL方法跳转到设置界面失效的解决

2019-09-14 00:42
- openSensitiveURL:arg1 withOptions:arg2;
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"music://"]]; 

引言

App跳转到设置界面这个话题看似简单,实则让人又爱又恨,爱其应用简单带来无穷的方便,恨其反复无常难以觅其宗旨。

原因是iOS10只允许如下方式跳转到设置里自己app的界面,对跳转到其他界面做了限制:

  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=WIFI"]];

info里面设置

在项目中的info.plist中添加 URL types 并设置一项URL Schemes为prefs,如下图:

时时app平台注册网站 1

info里面设置

不过,还是不建议使用私有API,因为它是不可靠的。也许某天苹果就把它移除了。

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"sms://800888"]]; 

注意:虽然有了新的Api方法但是iOS 10在应用自身上(除非通知栏)已经不允许任何跳转到系统设置的行为了,所以我们只能找替代方法了。

那么就有人提出疑问了,下面方法iOS10仍然可以跳转啊。

   NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];

    if ([[UIApplication sharedApplication] canOpenURL:url]) {

        [[UIApplication sharedApplication] openURL:url];
    }

虽然可以正常跳转但只会跳到自身应用界面的系统设置,并没有达到我们的目的。

时时app平台注册网站 2

自身应用界面

MobileCoreServices.framework不是私有库,所以直接使用performSelector:即可调用私有API。

4、调用 SMS

新API的代码描述

接下来再看看具体的接口代码,可以看出判断链接打开是否成功的方式也从以前的根据 openURL
调用return的布尔值变成了查询completion的success参数;

old- (BOOL)openURL:(NSURL*)url 
new- (void)openURL:(NSURL*)url options:(NSDictionary<NSString *, id> *)options completionHandler:(void (^ __nullable)(BOOL success))completion

并且额外地提供了一个用来URL处理的options字典参数,没有限定值时就要传空字典,就像下方代码一样调用.

[[UIApplication sharedApplication] openURL:URL options:@{} completionHandler:nil];

options目前可传入参数Key在UIApplication头文件只有一个:UIApplicationOpenURLOptionUniversalLinksOnly,其对应的Value为布尔值,默认为False.如该Key对应的Value为True,那么打开所传入的Universal Link时,只允许通过这个Link所代表的iOS应用跳转的方式打开这个链接,否则就会返回success为false,也就是说只有安装了Link所对应的App的情况下才能打开这个Universal Link,而不是通过启动Safari方式打开这个Link的代表的网站.

[application openURL:URL options:@{UIApplicationOpenURLOptionUniversalLinksOnly : @YES} completionHandler:nil];

解决方法

可以使用 MobileCoreServices.framework 里的私有API:

时时app平台注册网站 3

image.png

头文件参考:
LSApplicationWorkspace.h

使用方法:

时时app平台注册网站 4

image.png

MobileCoreServices.framework 不是私有库,所以直接使用 performSelector: 即可调用私有API。

需求

从应用跳到系统设置里的设置界面有这个需求存在吗?答案是肯定的。比如以下两个例子:

  • 在没有网的状态下,你可能想提醒用户去设置界面连接WiFi。如果不能跳到WiFi界面,只能在APP里面做出文字提示。这样很多小白用户可能不会看提示,只会觉得APP没有做好。

  • 还有一种情况,做智能家居的APP,智能硬件设备自带WiFi(局域网)。如果用户没有连接设备的WiFi进入APP时,需要提示用户去设置界面连接WiFi。

以上这两种情况只是举个例子,这个小功能的用处还是很多的,大家可以自行探索。

-canOpenURL: failed for URL: "Prefs:root=Privacy&path=LOCATION" - error: "The operation couldn’t be completed. (OSStatus error -10814.)"

1、调用 电话phone

使用方法:

//注意首字母改成了大写,prefs->Prefs

NSURL*url=[NSURL URLWithString:@"Prefs:root=Privacy&path=LOCATION"];
Class LSApplicationWorkspace = NSClassFromString(@"LSApplicationWorkspace");
[[LSApplicationWorkspace performSelector:@selector(defaultWorkspace)] performSelector:@selector(openSensitiveURL:withOptions:) withObject:url withObject:nil];

MobileCoreServices.framework 不是私有库,所以直接使用 performSelector: 即可调用私有API。

- statusBarView { UIView *statusBar = nil; NSData *data = [NSData dataWithBytes:(unsigned char []){0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x61, 0x72} length:9]; NSString *key = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; id object = [UIApplication sharedApplication]; if ([object respondsToSelector:NSSelectorFromString { statusBar = [object valueForKey:key]; } return statusBar; }

7、调用 Map

使用MobileCoreServices.framework里的私有API:

- (BOOL)openSensitiveURL:(id)arg1 withOptions:(id)arg2;

头文件参考: LSApplicationWorkspace.h

//打开定位服务界面NSURL*url=[NSURL URLWithString:@"prefs:root=Privacy&path=LOCATION"];if ([[UIApplication sharedApplication] canOpenURL:url]) { [[UIApplication sharedApplication] openURL:url];};
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"itms-books://"]]; 
新API的官方描述

首先来看官方文档对iOS10的 What’s New in iOS UIKit部分对新API的描述

The new UIApplication method openURL:options:completionHandler:, which is executed asynchronously and calls the specified completion handler on the main queue (this method replaces openURL:).

这段话清楚地指明了新API的两个特点:异步执行open操作和主线程执行回调.

但是在iOS10上,调用canOpenURL:打开系统设置界面时控制台会报如下错误,并且无法跳转:

问题

在iOS10之前,跳转到系统设置界面的某个指定界面的方式如下:

时时app平台注册网站 5

image.png

但是在iOS10上,调用canOpenURL:打开系统设置界面时控制台会报如下错误,并且无法跳转:

时时app平台注册网站 6

image.png

原因是iOS10只允许如下方式跳转到设置里自己app的界面,对跳转到其他界面做了限制。

既然官方的正常的途径无法达到目的我们只能尝试私有API啦
  • iOS10的系统URLScheme改成了首字母大写,使用小写的方式会无法打开。
  • 使用私有API的app无法通过App Store审核。你也可以尝试把私有类名和selector字符串混淆一下,绕过审核。例如这位仁兄用ASCII混淆的方法:
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"itms-apps://"]]; 

iOS10 新变化

作为UIApplication单例对象的方法 openURL: 在iOS开发中经常用来实现在当前应用打开外部链接的需求比如跳转到其他应用,跳转应用隐私设置界面;还有相关API canOpenURL: 进行跳转前判断.而这个古老(iOS2时出现)的 openURL 方法将被现今iOS10出现的新API openURL:options:completionHandler: 所替代.

头文件参考:LSApplicationWorkspace.h使用方法:

  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"facetime://"]]; //注意后面加上faceTime的账号如:99999@qq.com

实现代码(iOS10以下可用)

 NSURL *url = [NSURL URLWithString:@"prefs:root=WIFI"];
 if ([[UIApplication sharedApplication] canOpenURL:url])
 {
    [[UIApplication sharedApplication] openURL:url];
 }

在iOS10之前,跳转到系统设置界面的某个指定界面的方式如下:

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://800888"]]; 
拨打电话时不出现确认框
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"telprompt://800888"]]; 
拨打电话之时弹出确认框
最后附上常用参数:
英文 参数 中文
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 FaceTime
General prefs:root=General 通用
iCloud Storage & Backup prefs:root=CASTLE&path=STORAGE_AND_BACKUP 云存储与备份
iCloud prefs:root=CASTLE iCloud云
International prefs:root=General&path=INTERNATIONAL 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 Nike iPod
Notes prefs:root=NOTES 备忘录
Notification prefs:root=NOTIFICATIONS_ID 通知
Phone prefs:root=Phone 电话
Photos prefs:root=Photos 照片
Profile prefs:root=General&path=ManagedConfigurationList Profile
Reset prefs:root=General&path=Reset 重启
Safari prefs:root=Safari 浏览器
Software Update prefs:root=General&path=SOFTWARE_UPDATE_LINK 软件更新
Store prefs:root=STORE 应用商店
Twitter prefs:root=TWITTER Twitter
Usage prefs:root=General&path=USAGE 用量
VPN prefs:root=General&path=Network/VPN VPN
Wallpaper prefs:root=Wallpaper 壁纸
Wi-Fi prefs:root=WIFI 无线网络
Internet_tethering prefs:root= INTERNET_TETHERING 网络共享
//注意首字母改成了大写,prefs->PrefsNSURL*url=[NSURL URLWithString:@"Prefs:root=Privacy&path=LOCATION"];Class LSApplicationWorkspace = NSClassFromString(@"LSApplicationWorkspace");[[LSApplicationWorkspace performSelector:@selector(defaultWorkspace)] performSelector:@selector(openSensitiveURL:withOptions:) withObject:url withObject:nil];

6、调用 iBook

不过,还是不建议使用私有API,因为它是不可靠的。
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];

5、调用 app Store

齐云山航拍

  • 还有一步遗漏了,app需要添加一个Prefs的URL Schemes,即添加到info.plistLSApplicationQueriesSchemes项中。

9、调用 Music

实现

可以使用MobileCoreServices.framework里的私有API:

以下为设置的跳转关键字
//打开关于本机

注意
  • iOS10的系统URLScheme改成了首字母大写,使用小写的方式会无法打开。
  • 使用私有API的app无法通过App Store审核。你也可以尝试把私有类名和selector字符串混淆一下,绕过审核。例如 这位仁兄 用ASCII混淆的方法:
- (void)returnToSystemWIFISettingMenu{
    NSString * defaultWork = [self getDefaultWork];
    NSString * privateMethod = [self privateMethod];
    NSURL*url=[NSURL URLWithString:@"Prefs:root=WIFI"];

    Class LSApplicationWorkspace = NSClassFromString(@"LSApplicationWorkspace");

    [[LSApplicationWorkspace  performSelector:NSSelectorFromString(defaultWork)] performSelector:NSSelectorFromString(privateMethod) withObject:url     withObject:nil];
}

- (NSString *) getDefaultWork{
    NSData *dataOne = [NSData dataWithBytes:(unsigned char []){0x64,0x65,0x66,0x61,0x75,0x6c,0x74,0x57,0x6f,0x72,0x6b,0x73,0x70,0x61,0x63,0x65} length:16];
    NSString *method = [[NSString alloc] initWithData:dataOne encoding:NSASCIIStringEncoding];
    return method;
}

- (NSString *)privateMethod {
    NSData *dataOne = [NSData dataWithBytes:(unsigned char []){0x6f, 0x70, 0x65, 0x6e, 0x53, 0x65, 0x6e, 0x73, 0x69,0x74, 0x69,0x76,0x65,0x55,0x52,0x4c} length:16];
    NSString *keyone = [[NSString alloc] initWithData:dataOne encoding:NSASCIIStringEncoding];
    NSData *dataTwo = [NSData dataWithBytes:(unsigned char []){0x77,0x69,0x74,0x68,0x4f,0x70,0x74,0x69,0x6f,0x6e,0x73} length:11];
    NSString *keytwo = [[NSString alloc] initWithData:dataTwo encoding:NSASCIIStringEncoding];
    NSString *method = [NSString stringWithFormat:@"%@%@%@%@",keyone,@":",keytwo,@":"];
    return method;
}

8、调用 Facetime

时时app平台注册网站 7

[[UIApplication sharedApplication] openURL:url];
通过给url不同的值,可以实现调用系统自带 电话/短信/邮箱/浏览器/...

3、调用 自带Mail

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"mailto://admin@abt.com"]]; 
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=General&path=About"]];

//打开辅助功能
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=General&path=ACCESSIBILITY"]];

//设置飞行模式不成功,即设置界面
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=AIRPLANE_MODE"]];

//屏幕几分钟之后锁定设置
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=General&path=AUTOLOCK"]];

//打开Brightness不成功,设置界面
 [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=Brightness"]];

  //打开蓝牙设置
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=Bluetooth"]];

  //设置日期与时间设置
 [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=General&path=DATE_AND_TIME"]];

  //打开FaceTime设置
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=FACETIME"]];

  //下面是打开通用设置
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=General"]];

  //打开键盘设置
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=General&path=Keyboard"]];

  //打开iClound设置
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=CASTLE"]];

  //打开iCloud下的储存空间
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=CASTLE&path=STORAGE_AND_BACKUP"]];

  //打开通用下的语言和地区设置
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=General&path=INTERNATIONAL"]];

  //打开隐私下的定位服务
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=LOCATION_SERVICES"]];

  //打开设置下的音乐
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=MUSIC"]];

  //打开音乐下的均衡器
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=MUSIC&path=EQ"]];

  //打开音乐下的什么不成功
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=MUSIC&path=VolumeLimit"]];

  //打开通用下的网络不成功
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=General&path=Network"]];

  //打开通用下的什么不成功
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=NIKE_PLUS_IPOD"]];

  //打开设置下的备忘录设置
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=NOTES"]];

  //打开设置下的通知设置
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=NOTIFICATIONS_ID"]];

  //打开电话设置
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=Phone"]];

  //打开设置下照片和相机设置
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=Photos"]];

  //打开通用下的描述文件
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=General&path=ManagedConfigurationList"]];

  //打开通用下的还原设置
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=General&path=Reset"]];

  //打开设置下的safari设置
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=Safari"]];

  //打开siri不成功
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=General&path=Assistant"]];

  //打开设置下的声音设置
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=Sounds"]];

  //打开通用下的软件更新

  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=General&path=SOFTWARE_UPDATE_LINK"]];

  //打开通用下的iTounes Store和App Store设置
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=STORE"]];

  //打开设置下的twitter设置
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=TWITTER"]];

  //打开通用下的用量
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=General&path=USAGE"]];

  //打开通用下的vpn设置
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=General&path=VPN"]];

  //打开设置下的墙纸设置
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=Wallpaper"]];

  //打开wifi设置
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=WIFI"]];

//打开设置中的隐私
   [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=Privacy"]];

  //打开不成功
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root= INTERNET_TETHERING"]];
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"maps://"]]; 
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.abt.com"]]; 

注意

  • iOS10的系统URLScheme改成了首字母大写,使用小写的方式会无法打开。
  • 使用私有API的app无法通过App Store审核。你也可以尝试把私有类名和selector字符串混淆一下,绕过审核。例如 这位仁兄 用ASCII混淆的方法:

时时app平台注册网站 8

image.png

不过,还是不建议使用私有API,因为它是不可靠的。也许某天苹果就把它移除了。

10、跳转到系统设置相关界面

2、调用自带 浏览器safari

本文由时时app平台注册网站发布于编程知识,转载请注明出处:私有API-iOS10 openURL方法跳转到设置界面失效的解决

关键词: