break;

}

}

//...../Payload/xxxx.app

NSString *bundleDirectory = [NSString stringWithFormat:@"%@/%@", payloadDirectory, dotAppDirectory];

NSLog(@"Signing bundle at path '%@'", bundleDirectory);

[xddCode xddLog:[NSString stringWithFormat:@"正在签名:%@",bundleDirectory]];

//开始签名

[self signBundleAtPath:bundleDirectory withCompletionHandler:^(NSError *err) {

if (err) {

completionHandler(err);

return;

}

// 3. Repack IPA to output path

NSError *error2;

if (![xddCode repackIpaAtPath:[NSString stringWithFormat:@"%@/%@", [xddCode applicationTemporaryDirectory], zipFilename] toPath:outputPath error:&error2]) {

completionHandler(error2);

} else {

// Success!

completionHandler(nil);

[xddCode xddLog:[NSString stringWithFormat:@"签名完毕:paAtPath=%@",[NSString stringWithFormat:@"%@/%@", [xddCode applicationTemporaryDirectory], zipFilename]]];

[xddCode xddLog:[NSString stringWithFormat:@"签名完毕:toPath=%@",outputPath]];

}

}];

}

(void)signBundleAtPath:(NSString*)path withCompletionHandler:(void (^)(NSError *error))completionHandler { // We need to handle application extensions, e.g. watchOS applications and VPN plugins etc. // These are stored in the bundle’s root directory at the following locations: // - /Plugins // - /Watch // Therefore, recurse through those directories as required before continuing for the root directory. dispatch_group_t dispatch_group = dispatch_group_create(); NSMutableArray * __block subBundleErrors = [NSMutableArray array]; if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@“%@/PlugIns”, path]]) { // Recurse through the plugins.

for (NSString *subBundle in [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[NSString stringWithFormat:@"%@/PlugIns", path] error:nil]) {

NSString *__block subBundlePath = [NSString stringWithFormat:@"%@/PlugIns/%@", path, subBundle];

// Enter the dispatch group

dispatch_group_enter(dispatch_group);

NSLog(@"Handling sub-bundle: %@", subBundlePath);

// Sign the bundle

[self signBundleAtPath:subBundlePath withCompletionHandler:^(NSError *error) {

if (error)

[subBundleErrors addObject:error];

NSLog(@"Finished sub-bundle: %@", subBundlePath);

dispatch_group_leave(dispatch_group);

}];

}

} if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@“%@/Watch”, path]]) { // Recurse through the watchOS stuff.

for (NSString *subBundle in [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[NSString stringWithFormat:@"%@/Watch", path] error:nil]) {

NSString * __block subBundlePath = [NSString stringWithFormat:@"%@/Watch/%@", path, subBundle];

// Enter the dispatch group

dispatch_group_enter(dispatch_group);

NSLog(@"Handling sub-bundle: %@", subBundlePath);

// Sign the bundle

[self signBundleAtPath:subBundlePath withCompletionHandler:^(NSError *error) {

if (error)

[subBundleErrors addObject:error];

NSLog(@"Handled sub-bundle: %@", subBundlePath);

dispatch_group_leave(dispatch_group);

}];

}

} // Wait on sub-bundles to finish, if needed. dispatch_group_wait(dispatch_group, DISPATCH_TIME_FOREVER); if (subBundleErrors.count > 0) { // Errors when handling sub-bundles!

for (NSError *err in subBundleErrors) {

NSLog(@"Error: %@", err.localizedDescription);

}

completionHandler([subBundleErrors lastObject]);

return;

} // 1. Read Info.plist to gain the applicationId and binaryLocation. // 2. Get provisioning profile and certificate info // 3. Sign bundle NSDictionary *infoplist = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@“%@/Info.plist”, path]]; if (!infoplist || [infoplist allKeys].count == 0) { NSError *error = [xddCode _errorFromString:@"Failed to open Info.plist!"];

completionHandler(error);

return;

} // Find the systemType for this bundle. NSString *platformName = [infoplist objectForKey:@“DTPlatformName”]; EESystemType systemType = -1; if ([platformName isEqualToString:@“iphoneos”]) { systemType = EESystemTypeiOS;

} else if ([platformName isEqualToString:@“watchos”]) { systemType = EESystemTypewatchOS;

} else if ([platformName isEqualToString:@“tvos”]) { systemType = EESystemTypetvOS;

} else { // Base case, assume iOS.

systemType = EESystemTypeiOS;

} NSLog(@“Platform: %@ for bundle: %@”, platformName, [path lastPathComponent]); NSString *applicationId = [infoplist objectForKey:@“CFBundleIdentifier”]; NSString *binaryLocation = [path stringByAppendingFormat:@“/%@”, [infoplist objectForKey:@“CFBundleExecutable”]]; NSLog(@“applicationId: %@ for bundle: %@”, applicationId, [path lastPathComponent]); NSLog(@“binaryLocation: %@ for bundle: %@”, binaryLocation, [path lastPathComponent]); // We get entitlements from the binary using ldid::Analyze() during provisioning, updating them as needed // for the current Team ID. { // We now have a valid provisioning profile for this application!

// And, we also have a valid development codesigning certificate, with its private key!

// Add embedded.mobileprovision to the bundle, overwriting if needed.

NSError *fileIOError;

NSString *embeddedPath = [NSString stringWithFormat:@"%@/embedded.mobileprovision", path];

NSLog(@"embeddedPath=%@", embeddedPath);

//删除旧签名文件

if ([[NSFileManager defaultManager] fileExistsAtPath:embeddedPath]) {

[[NSFileManager defaultManager] removeItemAtPath:embeddedPath error:&fileIOError];

if (fileIOError) {

NSLog(@"removeItemAtPath%@", fileIOError);

return;

}

}

//写入新的

NSString *mobileprovisionFileName = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Web/qqqq.mobileprovision"];

//最后:从文件中读出 xxxx.mobileprovision

NSData *embeddedMobileProvision = [NSData dataWithContentsOfFile:mobileprovisionFileName options:0 error:NULL];

if (![(NSData*)embeddedMobileProvision writeToFile:embeddedPath options:NSDataWritingAtomic error:&fileIOError]) {

if (fileIOError) {

NSLog(@"writeToFile err:%@", fileIOError);

} else {

NSLog(@"writeToFile Failed to write '%@'.", embeddedPath);

}

return;

}

// Next step: signing. To do this, we use EESigner with these four results.

NSString *p12FileName = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Web/qqqq.cer"];

//从文件中读出 配置文件 xxxx.cer

NSData *p12Provision = [NSData dataWithContentsOfFile:p12FileName options:0 error:NULL];//从FileName中读取出数据

//从文件中读出 秘钥 xxxx.pem

NSString *ProvisionFileName = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Web/qqqq.pem"];

NSData *ProvisionNsData = [[NSData alloc] initWithContentsOfFile:ProvisionFileName];

NSString *privateKey = [[NSString alloc] initWithData:ProvisionNsData encoding:NSUTF8StringEncoding];

//获取 Entitlements

NSDictionary* entitlements = [xddCode getEntitlements:mobileprovisionFileName];

//创建签名类signer

EESigning *signer = [EESigning signerWithCertificate:p12Provision privateKey:privateKey];

//EESigning *signer = [NSClassFromString(@"EESigning") signerWithCertificate:p12Provision privateKey:privateKey];

//调用签名开始

[signer signBundleAtPath:path entitlements:entitlements identifier:applicationId withCallback:^(BOOL success, NSString *result) {

NSLog(@"signBundleAtPath.result=%@", result);

NSString*title = @"成功";

NSError *error = nil;

if (!success) {

title = @"失败";

}

[xddCode xddLog:[NSString stringWithFormat:@"signBundleAtPath title=%@,result=%@",title,result]];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

// We will now pause so that ldid can cleanup after itself.

[NSThread sleepForTimeInterval:1];

NSError *error = nil;

if (!success) {

error = [xddCode _errorFromString:result];

}

// We're done.

completionHandler(error);

});

}];

}

}

本文转自 [https://ccccc.blog.csdn.net/article/details/104836346](https://ccccc.blog.csdn.net/article/details/104836346),如有侵权,请联系删除。

**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

**因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

![img](https://img-blog.csdnimg.cn/img_convert/48c4d91fb2e32818e4dfd2efcff5719a.png)

![img](https://img-blog.csdnimg.cn/img_convert/74dc284888837e43e8ad4de74a97ad1d.png)

![img](https://img-blog.csdnimg.cn/img_convert/6d8ff150b3a9a511529810f0c905ef0c.png)

![img](https://img-blog.csdnimg.cn/img_convert/b3939a0f4650c8b9ac83f349a27c10d2.png)

![img](https://img-blog.csdnimg.cn/img_convert/2c56953839aa1aa0636369c933143025.png)

![img](https://img-blog.csdnimg.cn/img_convert/0b4988fde1f42a81a45bb48afe0aa858.png)

![img](https://img-blog.csdnimg.cn/13f2cb2e05a14868a3f0fd6ac81d625c.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!**

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)**

![img](https://img-blog.csdnimg.cn/img_convert/cb38d47352d714d84622fa262df09e44.png)

### 最后

文章所有资料全部已经打包整理好,另外小编手头上整理了大量Android架构师全套学习资料,**Android核心高级技术PDF文档+全套高级学习资料+视频+2021 BAT 大厂面试真题解析**

**资料展示:**

![image](https://img-blog.csdnimg.cn/img_convert/5930134124b8f385b56d5b0525c62500.webp?x-oss-process=image/format,png)

![image](https://img-blog.csdnimg.cn/img_convert/97c3451c5c060c9b2ad52ba911aecd2a.webp?x-oss-process=image/format,png)

![image](https://img-blog.csdnimg.cn/img_convert/a9d231600a1c7df12df4a42076c10735.webp?x-oss-process=image/format,png)

![image](https://img-blog.csdnimg.cn/img_convert/4596f7ea9be3d73d1a580a8c45d26025.webp?x-oss-process=image/format,png)

**一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

![img](https://img-blog.csdnimg.cn/img_convert/e1776fdd83471524d10c03ed58ee694e.png)

droid)**

[外链图片转存中...(img-Qgpmkk2I-1712847883153)]

### 最后

文章所有资料全部已经打包整理好,另外小编手头上整理了大量Android架构师全套学习资料,**Android核心高级技术PDF文档+全套高级学习资料+视频+2021 BAT 大厂面试真题解析**

**资料展示:**

[外链图片转存中...(img-bukQ3UjK-1712847883153)]

[外链图片转存中...(img-29tTLcRQ-1712847883154)]

[外链图片转存中...(img-0lkde0SZ-1712847883154)]

[外链图片转存中...(img-5meszpL8-1712847883154)]

**一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

[外链图片转存中...(img-d2IoaXuf-1712847883155)]

相关阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。

大家都在找:

ios:ios软件下载

objective-c:critical

iphone:iphone16值得等吗