Java 解析 IPA 文件,读取 Info.plist 信息

在做移动MDM功能的时候,就遇到了这样一个问题,当用户上传IPA文件时,我如何知道这个IPA文件的相关信息呢?IPA文件有一个很重要的文件Info.plist 就类似于Android程序的Manifest.xml,只要能够从IPA文件中提取出来Info.plist,然后在进行解析提起相关信息,那就马到成功了。那么,按照上面步骤开始了。

1、Java解压IPA文件,只获取 Info.plist

/**
	 * 解压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 unzip(newfile, newfile.getParent());
			}           
		}catch(Exception e){       
			e.printStackTrace();    
		}
		return null;
	}

2、Java读取Info.plist文件,获取需要的信息

/**
	 * 通过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("CFBundleVersion");
		map.put("CFBundleVersion", parameters.toString());
		// 应用展示的名称
		parameters = (NSString) rootDict.objectForKey("CFBundleDisplayName");
		map.put("CFBundleDisplayName", parameters.toString());
		// 应用所需IOS最低版本
		parameters = (NSString) rootDict.objectForKey("MinimumOSVersion");
		map.put("MinimumOSVersion", parameters.toString());

		// 如果有必要,应该删除解压的结果文件
		file.delete();
		file.getParentFile().delete();

		return map;
	}

3、程序测试

public static void main(String[] args) throws Exception {

		File file = new File("d:/UniAccess.ipa");
		Map<String,String> map = getIpaInfoMap(file);
		for(String key : map.keySet()){
			System.out.println(key+" : "+map.get(key));
		}

	}

4、测试结果

CFBundleIdentifier : com.qihoo.installSafety
CFBundleDisplayName : 360手机卫士
CFBundleName : 360MobileSafe
CFBundleVersion : 4.2.0.2
MinimumOSVersion : 5.0

5、相关jar包,以及IPA文件,可以到如下指定地址下载

1)http://download.csdn.net/detail/wp562846864/8474481

2)http://m1.app111.org/2014/09/19/20140919142959.ipa

时间: 2024-08-20 06:19:27

Java 解析 IPA 文件,读取 Info.plist 信息的相关文章

Java解析XML文件的四种方法

[摘要] 可扩展标志语言(XML)在实现信息标准化.信息的交流与共享上有其独特的技术优势,因此受到了广泛的重视.本文先简单的介绍了XML基本知识,然后从XML应用入手总结了四种现今最常见的XML的解析方法,介绍了这四种方法的特点,其中包括优点与不足之处.最后给出了一个简单的案例来对这四种解析进行代码介绍. [关键字] XML文件,DOM,SAX,JDOM,DOM4J [引言] XML即可扩展标记语言(EXtensible Markup Language),是标准通用标记语言的子集,是一种用于标记

java解析xml文件四种方式介绍、性能比较和基本使用方法

一.介绍: 1)DOM(JAXP Crimson解析器) DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准.DOM是以层次结构组织的节点或信息片断的集合.这个层次结构允许开发人员在树中寻找特定信息.分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作.由于它是基于信息层次的,因而DOM被认为是基于树或基于对象的.DOM以及广义的基于树的处理具有几个优点.首先,由于树在内存中是持久的,因此可以修改它以便应用程序能对数据和结构作出更改.它还可以在任何时候在树中上下导航,而不

java解析dbf文件

dbf文件, 不能直接另存为excel文件, 会丢数据! 需要将dbf数据存储到数据库中, 在从数据库中将数据导出成excel. import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Connection; import java.sql.PreparedStatement; import java.util.ArrayList; import java.u

Java学习-019-Properties 文件读取实例源代码

在这几天的学习过程中,有开发的朋友告知我,每个编程语言基本都有相应的配置文件支持类,像 Python 编程语言中支持的 ini 文件及其对应的配置文件读取类 ConfigParse,通过这个类,用户可以方便的修改 ini 配置文件.在 Java 中对应的配置文件为 properties 格式的文本文件,其对应的内容格式为 “键=值” ,文本注释信息可以用 “#” 注释.同时 Java 语言中对应的类为 Properties(java.util.Properties),即为读取 propertie

Java 解析chm文件实战(原创)

需求:java解析chm文件,并将内容插入数据库和redis. Java解析chm文件,网上除了github上有个家伙只言片语了一下,没有啥资料参考,包括chm4j这东西,没啥介绍,本着服务大众的精神,整理了下流程, 时间仓促,错误之处在所难免,望指正. 第一步:下载chm4j.jar以及依赖 http://sourceforge.net/projects/chm4j/ 第二步:新建java工程,建一个解析ParseChm类,建一个解析测试类,类似: ParseChm类: //下面的包,请导入c

Java学习-017-EXCEL 文件读取实例源代码

众所周知,EXCEL 也是软件测试开发过程中,常用的数据文件导入导出时的类型文件之一,此文主要讲述如何通过 EXCEL 文件中 Sheet 的索引(index)或者 Sheet 名称获取文件中对应 Sheet 页中的数据.敬请各位小主参阅,若有不足之处,敬请大神指正,不胜感激! 不多言,小二上码咯... 通过 sheet_index 读取 EXCEL 数据源代码如下所示,敬请参阅! 1 /** 2 * @function 文件读取: EXCEL文件 3 * @description 通过EXCE

java解析xml文件并输出

使用java解析xml文件,通过dom4j,代码运行前需先导入dom4j架包. ParseXml类代码如下: import java.io.File; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class

前端解析ipa、apk安装包信息 —— app-info-parser

安装包只需要经过一次传输,另一次则是可以忽略不计的请求 安装 npm install app-info-parser # or yarn yarn add app-info-parser 使用 NPM引入: const AppInfoParser = require('app-info-parser') const parser = new AppInfoParser('../packages/xxx.apk') // or xxx.ipa parser.parse().then(result

java实现xml文件读取并保存到对象

首先浅聊一下解析xml的四种方式: 1.DOM方式:有缺点但是这个缺点却也是他的优点.下面详细介绍: 以树形的层次结构组织节点或信息片断集合,可以获得同一个文档中的多处不同数据.使用起来简单. 优点是:可以获得同一个文档中的多处不同数据,使用起来简单. 缺点是:需要加载整个xml文件,这对内存和资源有一定的消耗,如果是小型的xml文件可以尝试用 DOM方式解析. 经测试当用DOM方式读取大小为10M的文件时, 将会产生内存溢出异常. 2.SAX方式:在读取数据时检查数据,不用解析整个文档,因此不