实现colorful widget主题图标下载安装效果,其实是一个快捷启动入口
1、依赖 CocoaHTTPServer 搭建一个本地服务器,提供mobileconfig下载,https://img.ibestfanli.com/CocoaHTTPServer.zip
2、使用到 SFSafariViewController,SFSafariViewController需要下载实时打包的图标mobileconfig文件,下载完系统弹窗提示跳转安装页面
一、启动本地服务器
// 端口
static NSInteger const LocalServerPort = 8090;
// host
static NSString * const LocalHost = @"127.0.0.1";
_localHttpServer = [[HTTPServer alloc] init];
[_localHttpServer setType:@"_http.tcp"];
[_localHttpServer setPort:LocalServerPort];
[_localHttpServer setInterface:LocalHost];
NSString *rootPath = [SystemUtil appDocumentPathAppendingFolder:@"local"];
// 创建并指定服务器根目录,也是存储下载mobileconfig文件的目录
NSString *originPath = [NSString stringWithFormat:@"%@/local",[[NSBundle mainBundle] bundlePath]];
// 把工程内的Web拷贝到document/local/
[SystemUtil copyFilesWithOldFolder:originPath toPath:rootPath];
[_localHttpServer setDocumentRoot:rootPath];
二、打包创建mobileconfig文件
手动创建需要用Apple Configurator配置一个WebClip,
但我们示例使用代码创建:
/// 配置一个PayloadContent
/// - Parameters:
/// - icon: 图标data数据
/// - label: 图标展示标题
/// - url: 跳转的app scheme
+ (NSMutableDictionary *)initWithIcon:(NSData *)icon label:(NSString *)label url:(NSString *)url {
PayloadContent *content = [[PayloadContent alloc] init];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
NSString *uuid = [FCUUID uuid];
content.FullScree = YES;
content.IgnoreManifestScope = NO;
content.IsRemovable = YES;
content.Label = label;
content.PayloadDescription = @"Configures settings for a web clip";
content.PayloadDisplayName = [NSString stringWithFormat:@"%@ Icon",label];
content.PayloadIdentifier = [NSString stringWithFormat:@"com.apple.webClip.managed.%@",uuid];
content.PayloadType = @"com.apple.webClip.managed";
content.PayloadUUID = uuid;
content.PayloadVersion = 1;
content.Precomposed = NO;
content.TargetApplicationBundleIdentifier = [DataCenter shareCenter].appInfo.bundleId;
content.URL = url;
dict = [content modelToJSONObject];
dict[@"Icon"] = icon;
return dict;
}
@end
@implementation WebClip
/// 生成一个mobileconfig文件的配置字典
/// - Parameters:
/// - name: 文件名字
/// - array: PayloadContent数组
+ (NSMutableDictionary *)initWithName:(NSString *)name contents:(NSArray *)array {
WebClip *clip = [[WebClip alloc] init];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
NSString *uuid = [FCUUID uuid];
clip.PayloadDisplayName = name;
clip.PayloadIdentifier = uuid;
clip.PayloadRemovalDisallowed = NO;
clip.PayloadType = @"Configuration";
clip.PayloadUUID = uuid;
clip.PayloadVersion = 1;
dict = [clip modelToJSONObject];
dict[@"PayloadContent"] = array;
return dict;
}
@end
// 保存sige.mobileconfig到本地服务器的根目录
- (BOOL)saveMobileconfigFile {
NSMutableDictionary *dict = [WebClip initWithName:@"图标描述文件" contents:[self testMakeMobileconfig]];
// 保存sige.mobileconfig到本地服务器的根目录
NSString *filePath = [SystemUtil appDocumentPathAppendingFile:@"local/sige.mobileconfig" replace:YES];
BOOL write = [dict writeToURL:[NSURL fileURLWithPath:filePath] atomically:YES];
return write;
}
/// 生成PayloadContent数据
- (NSMutableArray*)testMakeMobileconfig {
NSMutableArray *payloadArray = [[NSMutableArray alloc] init];
for (int i=0; i<10; i++) {
NSData *imgData = UIImageJPEGRepresentation([UIImage imageNamed:@"ic_vip_tick"], 0.8);
NSMutableDictionary *dict = [PayloadContent initWithIcon:imgData label:[NSString stringWithFormat:@"标题 %@",@(i)] url:@"mqq://"];
[payloadArray addObject:dict];
}
return payloadArray;
}
三、SFSafariViewController访问一个本地H5,http://127.0.0.1:8090/web.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>教程</title>
</head>
<body>
<div class="panel">
<p class="titleText">下载文件,然后点击「允许」</p>
<a href="http://127.0.0.1:8090/sige.mobileconfig"><p class="btn">下载</p></a>
<p class="titleText2">
进入「设置」页面,点击进入已下载的描述文件,点击右上方「安装」
</p>
</div>
</style>
</body>
</html>
点击下载后,文件就会保存到VPN与设备管理页,点击安装即可;
此时安装的描述文件,是未签名的,可以使用服务端签名或者本地签名;
ios 描述文件 本地签名看这里