欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java語言如何生成plist下載ipa文件

 更新時間:2023年08月23日 15:14:38   作者:永不停歇的火車  
這篇文章主要介紹了java語言如何生成plist下載ipa文件問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

java語言生成plist下載ipa文件

在通過html頁面下載ipa文件安裝,需要通過plist文件下載,并且還要遵循 itms-services協(xié)議。 

也就說我們需要生產(chǎn)plist文件,然后通過html頁面鏈接指向plist文件。

下面是通過java語言生成plist文件:

public static String createPlist(String url,String version,String title) throws IOException{
        log.info("==========開始創(chuàng)建plist文件");
        //這個地址應(yīng)該是創(chuàng)建的服務(wù)器地址,在這里用生成到本地磁盤地址
        final String path = GetPropertiesValue.getValues("ios_plists_path");
        File file = new File(path);
        if (!file.exists()) {
            file.setWritable(true);//賦予文件權(quán)限
            file.mkdirs();
        }
        String plistFile = GetPropertiesValue.getValues("plists_name");//文件名稱
        final String PLIST_PATH = path + plistFile;
        file = new File(PLIST_PATH);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        String sub_title = GetPropertiesValue.getValues("plists_sub_title");
        String plist = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
                 + "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
                 + "<plist version=\"1.0\">\n" + "<dict>\n"
                 + "<key>items</key>\n" 
                 + "<array>\n" 
                 + "<dict>\n"
                 + "<key>assets</key>\n" 
                 + "<array>\n" 
                 + "<dict>\n"
                 + "<key>kind</key>\n"
                 + "<string>software-package</string>\n"
                 + "<key>url</key>\n"
                 //你之前所上傳的ipa文件路徑
                 + "<string>"+url+"</string>\n" 
                 + "</dict>\n" 
                 + "</array>\n"
                 + "<key>metadata</key>\n"
                 + "<dict>\n"
                 + "<key>bundle-identifier</key>\n"
                 //這個是開發(fā)者賬號用戶名,也可以為空,為空安裝時看不到圖標(biāo),完成之后可以看到
                 + "<string></string>\n"
                 + "<key>bundle-version</key>\n"
                 + "<string>"+version+"</string>\n"
                 + "<key>kind</key>\n"
                 + "<string>software</string>\n"
                 + "<key>subtitle</key>\n"
                 + "<string>"+sub_title+"</string>\n"
                 + "<key>title</key>\n"

上面重要的地方有兩點

  • url:這個參數(shù)是為了找到你自己上傳的ipa文件;
  • bundle-identifier:這個參數(shù)是開發(fā)者賬號用戶名,可以為空或任意,區(qū)別在于安裝的過程中有無圖標(biāo)和進(jìn)度

下面是生成html文件,通過html的方式下載這個ipa文件。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>下載</title>
<script type="text/javascript">
var url = 'https://127.0.0.1:8080//upload/plists/20160606143426371_63551_1.plist';
window.location.href = "itms-services://?action=download-manifest&url=" + url;
</script>
</head>
<body></body>
</html>

注意:訪問這個plist文件的時候必須是基于HTTPS的,所以這就需要有一臺https服務(wù)器 。

這樣只要我們只要訪問這個html地址,就可以自動下載ipa文件了。 

解析ipa生成plist文件

1.引入工具類jar

?? ??? ?<dependency>
? ? ? ? ? ? <groupId>ant</groupId>
? ? ? ? ? ? <artifactId>ant</artifactId>
? ? ? ? ? ? <version>1.6.5</version>
? ? ? ? </dependency>
? ? ? ? <dependency>
? ? ? ? ? ? <groupId>com.googlecode.plist</groupId>
? ? ? ? ? ? <artifactId>dd-plist</artifactId>
? ? ? ? ? ? <version>1.8</version>
? ? ? ? </dependency>

2.解析代碼

package com.ouyeel.ssx.admin.utils;
import com.dd.plist.NSDictionary;
import com.dd.plist.NSString;
import com.dd.plist.PropertyListParser;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
public class AnalysisIpa {
? ? private static Logger logger = LoggerFactory.getLogger(AnalysisIpa.class);
?? ?/**
? ? ?* 解壓IPA文件,只獲取IPA文件的Info.plist文件存儲指定位置
? ? ?* @param file
? ? ?* zip文件
? ? ?* @param unzipDirectory
? ? ?* 解壓到的目錄
? ? ?* @throws Exception
? ? ?*/
? ? private static File getZipInfo(File file, String unzipDirectory)
? ? ? ? ? ? throws Exception {
? ? ? ? // 定義輸入輸出流對象
? ? ? ? InputStream input = null;
? ? ? ? OutputStream output = null;
? ? ? ? File result = null;
? ? ? ? File unzipFile = null;
? ? ? ? ZipFile zipFile = null;
? ? ? ? try {
? ? ? ? ? ? // 創(chuàng)建zip文件對象
? ? ? ? ? ? zipFile = new ZipFile(file);
? ? ? ? ? ? // 創(chuàng)建本zip文件解壓目錄
? ? ? ? ? ? String name = file.getName().substring(0,file.getName().lastIndexOf("."));
? ? ? ? ? ? unzipFile = new File(unzipDirectory + "/" + name);
? ? ? ? ? ? if (unzipFile.exists()){
? ? ? ? ? ? ? ? unzipFile.delete();
? ? ? ? ? ? }
? ? ? ? ? ? unzipFile.mkdir();
? ? ? ? ? ? // 得到zip文件條目枚舉對象
? ? ? ? ? ? Enumeration<ZipEntry> zipEnum = zipFile.getEntries();
? ? ? ? ? ? // 定義對象
? ? ? ? ? ? ZipEntry entry = null;
? ? ? ? ? ? String entryName = null;
? ? ? ? ? ? String names[] = null;
? ? ? ? ? ? int length;
? ? ? ? ? ? // 循環(huán)讀取條目
? ? ? ? ? ? while (zipEnum.hasMoreElements()) {
? ? ? ? ? ? ? ? // 得到當(dāng)前條目
? ? ? ? ? ? ? ? entry = zipEnum.nextElement();
? ? ? ? ? ? ? ? entryName = new String(entry.getName());
? ? ? ? ? ? ? ? // 用/分隔條目名稱
? ? ? ? ? ? ? ? names = entryName.split("\\/");
? ? ? ? ? ? ? ? length = names.length;
? ? ? ? ? ? ? ? for (int v = 0; v < length; v++) {
? ? ? ? ? ? ? ? ? ? if(entryName.endsWith(".app/Info.plist")){ // 為Info.plist文件,則輸出到文件
? ? ? ? ? ? ? ? ? ? ? ? input = zipFile.getInputStream(entry);
? ? ? ? ? ? ? ? ? ? ? ? result = new File(unzipFile.getAbsolutePath()+ "/Info.plist");
? ? ? ? ? ? ? ? ? ? ? ? output = new FileOutputStream(result);
? ? ? ? ? ? ? ? ? ? ? ? byte[] buffer = new byte[1024 * 8];
? ? ? ? ? ? ? ? ? ? ? ? int readLen = 0;
? ? ? ? ? ? ? ? ? ? ? ? while ((readLen = input.read(buffer, 0, 1024 * 8)) != -1){
? ? ? ? ? ? ? ? ? ? ? ? ? ? output.write(buffer, 0, readLen);
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? } catch (Exception ex) {
? ? ? ? ? ? ex.printStackTrace();
? ? ? ? } finally {
? ? ? ? ? ? if (input != null)
? ? ? ? ? ? ? ? input.close();
? ? ? ? ? ? if (output != null) {
? ? ? ? ? ? ? ? output.flush();
? ? ? ? ? ? ? ? output.close();
? ? ? ? ? ? }
? ? ? ? ? ? // 必須關(guān)流,否則文件無法刪除
? ? ? ? ? ? if(zipFile != null){
? ? ? ? ? ? ? ? zipFile.close();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? // 如果有必要刪除多余的文件
? ? ? ? if(file.exists()){
? ? ? ? ? ? file.delete();
? ? ? ? }
? ? ? ? return result;
? ? }
/**
? ? ?* IPA文件的拷貝,把一個IPA文件復(fù)制為Zip文件,同時返回Info.plist文件
? ? ?* 參數(shù) oldfile 為 IPA文件
? ? ?*/
? ? private static File getIpaInfo(File oldfile) throws IOException {
? ? ? ? try{
? ? ? ? ? ? int byteread = 0;
? ? ? ? ? ? String filename = oldfile.getAbsolutePath().replaceAll(".ipa", ".zip");
? ? ? ? ? ? File newfile = new File(filename);
? ? ? ? ? ? if (oldfile.exists()){
? ? ? ? ? ? ? ? // 創(chuàng)建一個Zip文件
? ? ? ? ? ? ? ? InputStream inStream = new FileInputStream(oldfile);
? ? ? ? ? ? ? ? FileOutputStream fs = new FileOutputStream(newfile); ? ??
? ? ? ? ? ? ? ? byte[] buffer = new byte[1444]; ? ? ? ? ? ?
? ? ? ? ? ? ? ? while ((byteread = inStream.read(buffer)) != -1){
? ? ? ? ? ? ? ? ? ? fs.write(buffer,0,byteread); ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if(inStream != null){
? ? ? ? ? ? ? ? ? ? inStream.close();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if(fs != null){
? ? ? ? ? ? ? ? ? ? fs.close();?
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? // 解析Zip文件
? ? ? ? ? ? ? ? return getZipInfo(newfile,newfile.getParent());
? ? ? ? ? ? } ? ? ? ? ??
? ? ? ? }catch(Exception e){ ? ? ??
? ? ? ? ? ? e.printStackTrace(); ? ?
? ? ? ? }
? ? ? ? return null;
? ? }
? ? /**
? ? ?* 通過IPA文件獲取Info信息
? ? ?* 這個方法可以重構(gòu),原因是指獲取了部分重要信息,如果想要獲取全部,那么應(yīng)該返回一個Map<String,Object>
? ? ?* 對于plist文件中的數(shù)組信息應(yīng)該序列化存儲在Map中,那么只需要第三發(fā)jar提供的NSArray可以做到!
? ? ?*/
? ? public static Map<String,String> getIpaInfoMap(File ipa) throws Exception{
? ? ? ? Map<String,String> map = new HashMap<String,String>();
? ? ? ? File file = getIpaInfo(ipa);
? ? ? ? // 第三方j(luò)ar包提供
? ? ? ? NSDictionary rootDict = (NSDictionary) PropertyListParser.parse(file);
? ? ? ? // 應(yīng)用包名
? ? ? ? NSString parameters = (NSString)rootDict.objectForKey("CFBundleIdentifier");
? ? ? ? map.put("CFBundleIdentifier", parameters.toString());
? ? ? ? // 應(yīng)用名稱
? ? ? ? parameters = (NSString) rootDict.objectForKey("CFBundleName");
? ? ? ? map.put("CFBundleName", parameters.toString());
? ? ? ? // 應(yīng)用版本
? ? ? ? parameters = (NSString) rootDict.objectForKey("CFBundleShortVersionString");
? ? ? ? map.put("CFBundleShortVersionString", parameters.toString());
? ? ? ? // 應(yīng)用展示的名稱
? ? ? ? parameters = (NSString) rootDict.objectForKey("CFBundleDisplayName");
? ? ? ? map.put("CFBundleDisplayName", parameters!=null?parameters.toString():null);
? ? ? ? // 應(yīng)用所需IOS最低版本
? ? ? ? parameters = (NSString) rootDict.objectForKey("MinimumOSVersion");
? ? ? ? map.put("MinimumOSVersion", parameters.toString());
? ? ? ? //文件大小
? ? ? ? map.put("FileSize",String.valueOf(file.length()));
? ? ? ? // 如果有必要,應(yīng)該刪除解壓的結(jié)果文件
? ? ? ? file.delete();
? ? ? ? file.getParentFile().delete();
? ? ? ? return map;
? ? }
? ? /**
? ? ?* 生成plist文件,返回
? ? ?* @param map:ipa解析信息
? ? ?* @param downloadIpaPath:下載ipa文件路徑(https://xxx/xxx/x.ipa)
? ? ?* @param ipaFilePath:ipa文件存放路徑(/home/tomcat/xxx/x.ipa)
? ? ?* @return plist下載地址
? ? ?*/
? ? public static String createPlistXml(Map<String,String> map,String downloadIpaPath,String ipaFilePath){
? ? ? ? logger.info("==========開始創(chuàng)建plist文件");
? ? ? ? //將.ipa文件變?yōu)?plist文件后綴
? ? ? ? ipaFilePath = ipaFilePath.replace(".ipa",".plist");
? ? ? ? File file = new File(ipaFilePath);
? ? ? ? if (!file.exists()) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? file.createNewFile();
? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? String icon = "http://xxx.oss-cn-beijing.aliyuncs.com/chemcn-ec-web/resources/chemcn-app/testApp/5d0b57f2b1696b03c1ca22ab/icon/com.ouyeel.nbapp_1.0.0_100_i.png";
? ? ? ? String plist = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
? ? ? ? ? ? ? ? +"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
? ? ? ? ? ? ? ? +"<plist version=\"1.0\">\n"
? ? ? ? ? ? ? ? +"<dict>\n"
? ? ? ? ? ? ? ? +"<key>items</key>\n"
? ? ? ? ? ? ? ? +"<array>\n"
? ? ? ? ? ? ? ? +"<dict>\n"
? ? ? ? ? ? ? ? +"<key>assets</key>\n"
? ? ? ? ? ? ? ? +"<array>\n"
? ? ? ? ? ? ? ? +"<dict>\n"
? ? ? ? ? ? ? ? +"<key>kind</key>\n"
? ? ? ? ? ? ? ? +"<string>software-package</string>\n"
? ? ? ? ? ? ? ? +"<key>url</key>\n"
? ? ? ? ? ? ? ? +"<string>"+downloadIpaPath+"</string>\n"
? ? ? ? ? ? ? ? +"<key>md5-size</key>\n"
? ? ? ? ? ? ? ? +"<integer>"+map.get("FileSize")+"</integer>\n"
? ? ? ? ? ? ? ? +"</dict>\n"
? ? ? ? ? ? ? ? +"<dict>\n"
? ? ? ? ? ? ? ? +"<key>kind</key>\n"
? ? ? ? ? ? ? ? +"<string>display-image</string>\n"
? ? ? ? ? ? ? ? +"<key>needs-shine</key>\n"
? ? ? ? ? ? ? ? +"<true/>\n"
? ? ? ? ? ? ? ? +"<key>url</key>\n"
? ? ? ? ? ? ? ? +"<string>"+icon+"</string>\n"
? ? ? ? ? ? ? ? +"</dict>\n"
? ? ? ? ? ? ? ? +"</array>\n"
? ? ? ? ? ? ? ? +"<key>metadata</key>\n"
? ? ? ? ? ? ? ? +"<dict>\n"
? ? ? ? ? ? ? ? +"<key>bundle-identifier</key>\n"
? ? ? ? ? ? ? ? +"<string>"+map.get("CFBundleIdentifier")+"</string>\n"
? ? ? ? ? ? ? ? +"<key>bundle-version</key>\n"
? ? ? ? ? ? ? ? +"<string>"+map.get("CFBundleShortVersionString")+"</string>\n"
? ? ? ? ? ? ? ? +"<key>kind</key>\n"
? ? ? ? ? ? ? ? +"<string>software</string>\n"
? ? ? ? ? ? ? ? +"<key>title</key>\n"
? ? ? ? ? ? ? ? +"<string>"+map.get("CFBundleName")+"</string>\n"
? ? ? ? ? ? ? ? +"</dict>\n"
? ? ? ? ? ? ? ? +"</dict>\n"
? ? ? ? ? ? ? ? +"</array>\n"
? ? ? ? ? ? ? ? +"</dict>\n"
? ? ? ? ? ? ? ? +"</plist>";
? ? ? ? FileOutputStream output = null;
? ? ? ? OutputStreamWriter writer = null;
? ? ? ? try {
? ? ? ? ? ? output = new FileOutputStream(file);
? ? ? ? ? ? writer = new OutputStreamWriter(output, "UTF-8");
? ? ? ? ? ? writer.write(plist);
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? logger.error("==========創(chuàng)建plist文件異常:" + e.getMessage());
? ? ? ? }finally {
? ? ? ? ? ? if(writer != null){
? ? ? ? ? ? ? ? writer.close();
? ? ? ? ? ? }
? ? ? ? ? ? if(output != null){
? ? ? ? ? ? ? ? output.close();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? logger.info("==========成功創(chuàng)建plist文件");
? ? ? ? return downloadIpaPath.replaceAll(".ipa",".plist");
? ? }
? ? public static void main(String[] args) throws Exception {
? ? ? ? File file = new File("/Users/xuchuanjiang/Documents/temp/xxx-xxx-ios.ipa");
? ? ? ? Map<String,String> map = getIpaInfoMap(file);
? ? ? ? for(String key : map.keySet()){
? ? ? ? ? ? System.out.println(key+" : "+map.get(key));
? ? ? ? }
? ? ? ? createPlistXml(map,"https://xxx.xxx.com/ssx/static/xxx-xxx-ios.ipa","/Users/xuchuanjiang/Documents/temp/xxx-app-ios.ipa");
? ? }
}

3.提供下載的plist鏈接需要是https

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java之HashMap.values()方法的誤用解讀

    Java之HashMap.values()方法的誤用解讀

    這篇文章主要介紹了Java之HashMap.values()方法的誤用解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • redisson分布式限流RRateLimiter源碼解析

    redisson分布式限流RRateLimiter源碼解析

    這篇文章主要為大家介紹了redisson分布式限流RRateLimiter源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • @Value如何設(shè)置默認(rèn)值

    @Value如何設(shè)置默認(rèn)值

    這篇文章主要介紹了@Value如何設(shè)置默認(rèn)值問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • 若依 MyBatis改為MyBatis-Plus的實現(xiàn)步驟

    若依 MyBatis改為MyBatis-Plus的實現(xiàn)步驟

    本文主要介紹了若依 MyBatis改為MyBatis-Plus的實現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-08-08
  • Java開發(fā)到底為什么要用 IoC 和 AOP

    Java開發(fā)到底為什么要用 IoC 和 AOP

    這篇文章主要介紹了Java開發(fā)到底為什么要用 IoC 和 AOP,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-02-02
  • MyBatisPlus中@TableField注解的基本使用

    MyBatisPlus中@TableField注解的基本使用

    這篇文章主要介紹了MyBatisPlus中@TableField注解的基本使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • 單機redis分布式鎖實現(xiàn)原理解析

    單機redis分布式鎖實現(xiàn)原理解析

    這篇文章主要介紹了單機redis分布式鎖實現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • Spring Boot 集成 Sharding-JDBC + Mybatis-Plus 實現(xiàn)分庫分表功能

    Spring Boot 集成 Sharding-JDBC + Mybatis-Plus 實現(xiàn)分庫分表功能

    這篇文章主要介紹了Spring Boot 集成 Sharding-JDBC + Mybatis-Plus 實現(xiàn)分庫分表功能,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • Spring @RestController注解組合實現(xiàn)方法解析

    Spring @RestController注解組合實現(xiàn)方法解析

    這篇文章主要介紹了Spring @RestController注解組合實現(xiàn)方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-06-06
  • SpringBoot結(jié)合Maven項目依賴版本沖突問題解決

    SpringBoot結(jié)合Maven項目依賴版本沖突問題解決

    本文主要介紹了SpringBoot結(jié)合Maven項目依賴版本沖突問題解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06

最新評論