=============================================

①步骤

把 xxxxxx.p12 转换成   xxxx.cer  和  xxxx.pem

①转换代码

openssl pkcs12 -in my.p12 -out xxx.pem -nodes

<得到:xxx.pem>两个任选一

openssl pkcs12 -clcerts -nokeys -out xxx.pem -in my.p12

<得到:xxx.pem>两个任选一

openssl pkcs12 -in my.p12 -out xxxx.crt -nokeys -clcerts

openssl x509 -inform pem -in xxxx.crt -outform der -out xxxx.cer

<得到:xxxx.cer>

得到文件=保存起来=等会代码签名用===

通过 xxxxx.p12转换

得到 xxxx.pem

得到 xxxx.cer

====目前4个文件 列表=

//自备文件

xxxxx.p12

xxxxx.mobileprovision

//通过xxx.p12转换得到文件

xxxx.pem

xxxx.cer

===============================================

//签名调用(xddSigning signIpaAtPath)

NSString *cachepath=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];

//签名保存文件路径

NSString *outputPath=[cachepath stringByAppendingPathComponent:@“Alook_qqqq_sign.ipa”];

//待签名文件路径<我是放到程序目录>线上可以读取Document

NSString *ipaPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@“Alook.ipa”];

[xddSigning signIpaAtPath:ipaPath outputPath:outputPath withCompletionHandler:^(NSError * error) {

if(error){

[xddCode xddLog:[NSString stringWithFormat:@"签名:%@",@"失败"]];

}else{

[xddCode xddLog:[NSString stringWithFormat:@"签名成功:路径=%@",outputPath]];

}

}];

// signIpaAtPath 签名具体实现

(void)signIpaAtPath:(NSString*)ipaPath outputPath:(NSString*)outputPath withCompletionHandler:(void (^)(NSError *))completionHandler { // 1. Unpack IPA to a temporary directory. NSError *error; NSString *unpackedDirectory; if (![xddCode unpackIpaAtPath:ipaPath outDirectory:&unpackedDirectory error:&error]) { completionHandler(error);

return;

} // 2. Sign its main bundle via above method. // The bundle will be located at //Payload/*.app internally NSString *zipFilename = [ipaPath lastPathComponent]; zipFilename = [zipFilename stringByReplacingOccurrencesOfString:@“.ipa” withString:@“”]; NSString *payloadDirectory = [NSString stringWithFormat:@“%@/Payload”, unpackedDirectory]; NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:payloadDirectory error:&error]; if (error) { completionHandler(error);

return;

} else if (files.count == 0) { NSError *err = [xddCode _errorFromString:@"Payload directory of IPA has no contents"];

completionHandler(err);

return;

} NSString *dotAppDirectory = @“”;//获取程序包 for (NSString *directory in files) { if ([directory containsString:@".app"]) {

dotAppDirectory = directory;

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]);

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

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

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

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

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

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

要如何成为Android架构师?

搭建自己的知识框架,全面提升自己的技术体系,并且往底层源码方向深入钻研。 大多数技术人喜欢用思维脑图来构建自己的知识体系,一目了然。这里给大家分享一份大厂主流的Android架构师技术体系,可以用来搭建自己的知识框架,或者查漏补缺;

对应这份技术大纲,我也整理了一套Android高级架构师完整系列的视频教程,主要针对3-5年Android开发经验以上,需要往高级架构师层次学习提升的同学,希望能帮你突破瓶颈,跳槽进大厂;

最后我必须强调几点:

1.搭建知识框架可不是说你整理好要学习的知识顺序,然后看一遍理解了能复制粘贴就够了,大多都是需要你自己读懂源码和原理,能自己手写出来的。 2.学习的时候你一定要多看多练几遍,把知识才吃透,还要记笔记,这些很重要! 最后你达到什么水平取决你消化了多少知识 3.最终你的知识框架应该是一个完善的,兼顾广度和深度的技术体系。然后经过多次项目实战积累经验,你才能达到高级架构师的层次。

你只需要按照在这个大的框架去填充自己,年薪40W一定不是终点,技术无止境

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

对应这份技术大纲,我也整理了一套Android高级架构师完整系列的视频教程,主要针对3-5年Android开发经验以上,需要往高级架构师层次学习提升的同学,希望能帮你突破瓶颈,跳槽进大厂;

最后我必须强调几点:

1.搭建知识框架可不是说你整理好要学习的知识顺序,然后看一遍理解了能复制粘贴就够了,大多都是需要你自己读懂源码和原理,能自己手写出来的。 2.学习的时候你一定要多看多练几遍,把知识才吃透,还要记笔记,这些很重要! 最后你达到什么水平取决你消化了多少知识 3.最终你的知识框架应该是一个完善的,兼顾广度和深度的技术体系。然后经过多次项目实战积累经验,你才能达到高级架构师的层次。

你只需要按照在这个大的框架去填充自己,年薪40W一定不是终点,技术无止境

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

文章来源

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