iOS开发 Objective-C 免越狱 iPhone手机 无需电脑 七天证书 个人证书 和 企业证书 代码签名 签名ipa 重签ipa

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

①步骤

把 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移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

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

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

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

要如何成为Android架构师?

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

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

最后我必须强调几点:

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

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

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

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

最后我必须强调几点:

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值