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 {
// 創建zip文件對象
zipFile = new ZipFile(file);
// 創建本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;
// 循環讀取條目
while (zipEnum.hasMoreElements()) {
// 得到當前條目
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();
}
// 必須關流,否則文件無法刪除
if(zipFile != null){
zipFile.close();
}
}
// 如果有必要刪除多餘的文件
if(file.exists()){
file.delete();
}
return result;
}
/**
* IPA文件的拷貝,把一個IPA文件複製爲Zip文件,同時返回Info.plist文件
* 參數 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()){
// 創建一個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信息
* 這個方法可以重構,原因是指獲取了部分重要信息,如果想要獲取全部,那麼應該返回一個Map<String,Object>
* 對於plist文件中的數組信息應該序列化存儲在Map中,那麼只需要第三發jar提供的NSArray可以做到!
*/
public static Map<String,String> getIpaInfoMap(File ipa) throws Exception{
Map<String,String> map = new HashMap<String,String>();
File file = getIpaInfo(ipa);
// 第三方jar包提供
NSDictionary rootDict = (NSDictionary) PropertyListParser.parse(file);
// 應用包名
NSString parameters = (NSString)rootDict.objectForKey("CFBundleIdentifier");
map.put("CFBundleIdentifier", parameters.toString());
// 應用名稱
parameters = (NSString) rootDict.objectForKey("CFBundleName");
map.put("CFBundleName", parameters.toString());
// 應用版本
parameters = (NSString) rootDict.objectForKey("CFBundleShortVersionString");
map.put("CFBundleShortVersionString", parameters.toString());
// 應用展示的名稱
parameters = (NSString) rootDict.objectForKey("CFBundleDisplayName");
map.put("CFBundleDisplayName", parameters!=null?parameters.toString():null);
// 應用所需IOS最低版本
parameters = (NSString) rootDict.objectForKey("MinimumOSVersion");
map.put("MinimumOSVersion", parameters.toString());
//文件大小
map.put("FileSize",String.valueOf(file.length()));
// 如果有必要,應該刪除解壓的結果文件
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("==========開始創建plist文件");
//將.ipa文件變爲.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("==========創建plist文件異常:" + e.getMessage());
}finally {
if(writer != null){
writer.close();
}
if(output != null){
output.close();
}
}
logger.info("==========成功創建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