【Java】自建IOS应用(IPA)发布服务器

2023-11-16

       简单描述一下总的过程:在某个后台上(版本发布平台)上传原始的ipa文件,解析ipa(主要是解析info.plist,从中获取软件名、版本、icons等;解析embedded.mobileprovision,获取证书过期时间),生成一个新的plist文件,最终将ipa、新的plist、图标上传至发布服务器。这个plist文件里面会指向这个ipa的地址,最终在Safari上访问 itms-services://?action=download-manifest&url=plist文件 就可以下载IOS应用了。

下面先来看看最重要的plist文件.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>items</key>
        <array>
            <dict>
                <key>assets</key>
                <array>
                    <dict>
                        <key>kind</key>
                        <string>software-package</string>
                        <key>url</key>
                        <string>https://uc-download.xxx.com/api/v1/file/download/5194c4cfcb3d4c128c51b9e3138ca8e8</string>
                    </dict>
                    <dict>
                        <key>kind</key>
                        <string>full-size-image</string>
                        <key>needs-shine</key>
                        <true/>
                        <key>url</key>
                        <string>https://uc-download.xxx.com/api/v1/file/download/d11184a8a9184c00836f86e14ed11d10</string>
                    </dict>
                    <dict>
                        <key>kind</key>
                        <string>display-image</string>
                        <key>needs-shine</key>
                        <true/>
                        <key>url</key>
                        <string>https://uc-download.xxx.com/api/v1/file/download/d11184a8a9184c00836f86e14ed11d10</string>
                    </dict>
                </array>
                <key>metadata</key>
                <dict>
                    <key>bundle-identifier</key>
                    <string>enterprise.xxx.Odin-UC</string>
                    <key>bundle-version</key>
                    <string>2.0.0.66</string>
                    <key>kind</key>
                    <string>software</string>
                    <key>title</key>
                    <string>UME</string>
                </dict>
            </dict>
        </array>
    </dict>
</plist>

一、服务器

首先,我们需要一台服务器,并且有SSL证书。这是因为最终在Safari上访问plist文件需要。

二、解析IPA

FileService这里主要用到就是在本地构造临时文件,ClientVersionRecord是数据库存储的版本实体对象,比较简单,不再赘述。

controller入口可以见:https://blog.csdn.net/Mr_EvanChen/article/details/106937688

/**
 * 解析ios安装包,后缀名为ipa
 */
@Service
public class IOSPacketParser extends InstallPacketParser {

    private static final Logger logger = LoggerFactory.getLogger(IOSPacketParser.class);

    @Autowired
    private FileService fileService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private IosIntranetService iosIntranetService;

    @Override
    public ClientType getClientType() {
        return ClientType.IOS;
    }

    @Override
    public ClientVersionRecord parse(File ipaFile, ClientVersionRecord version) throws Exception {

        String intranetIpaUrl = version.getIpaDownloadUrl();
        String intranetUrl = intranetIpaUrl.substring(0, intranetIpaUrl.lastIndexOf("/") + 1);
        IPA ipa = iosIntranetService.transFile2IPA(ipaFile);
        String ipaFileName = ipaFile.getName();
        ipaFileName = ipaFileName.substring(0, ipaFileName.lastIndexOf("."));

        //生成icon
        String iconUrl = buildIcon(ipaFile, ipa, intranetUrl + ipaFileName);

        //生成plist

        File plistFile = iosIntranetService.createPlistFile(ipa, intranetIpaUrl, iconUrl, ipaFileName);
        String plistUrl = iosIntranetService.uploadPlistAsFile(plistFile, intranetUrl + plistFile.getName());

        version.setMd5(FileUtil.md5(ipaFile))
                .setFileSize(ipaFile.length())
                .setClientVersion(ipa.getCFBundleVersion())
                .setIconUrl(iconUrl)
                .setIntranetDownloadUrl("itms-services://?action=download-manifest&url=" + plistUrl);

        logger.info("parse [ipa] file, version: {}", JSONUtil.serialize(version));
        return version;
    }

    //----------------------------------private-----------------------------------------

    private String buildIcon(File ipaFile, IPA ipa, String intranetIconUrl) {
        String iconName = getMaxIcon(ipa);
        File oriIcon = null;
        File tmpDecodedIcon = null;

        try {
            oriIcon = readIcons(ipaFile, iconName);
            tmpDecodedIcon = new File(fileService.getTempDir() + "decoded-" + oriIcon.getName());
            new IPngConverter(oriIcon, tmpDecodedIcon).convert();

            String oriIconName = oriIcon.getName();
            intranetIconUrl = intranetIconUrl + StringPool.DOT + oriIconName.substring(oriIconName.lastIndexOf(StringPool.DOT) + 1);
            restTemplate.put(intranetIconUrl, new FileSystemResource(tmpDecodedIcon));

        } catch (Exception e) {
            logger.info("上传icon至内网失败,结果:{}", intranetIconUrl);
        } finally {
            if (oriIcon != null) {
                logger.info("删除临时文件,结果:{}", oriIcon.delete());
                logger.info("删除临时文件,结果:{}", oriIcon.getParentFile().delete());
            }

            if (tmpDecodedIcon != null) {
                logger.info("删除临时文件,结果:{}",tmpDecodedIcon.delete());
                logger.info("删除临时文件,结果:{}",tmpDecodedIcon.getParentFile().delete());
            }
        }

        return intranetIconUrl;
    }

    private File readIcons(File ipaFile, String icon
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Java】自建IOS应用(IPA)发布服务器 的相关文章

随机推荐