├── GUITools.png
├── ipaTest
├── target
│ ├── maven-status
│ │ └── maven-compiler-plugin
│ │ │ ├── compile
│ │ │ └── default-compile
│ │ │ │ ├── createdFiles.lst
│ │ │ │ └── inputFiles.lst
│ │ │ └── testCompile
│ │ │ └── default-testCompile
│ │ │ └── inputFiles.lst
│ ├── ipaTest-1.0-SNAPSHOT.jar
│ ├── maven-archiver
│ │ └── pom.properties
│ └── ipaTest-1.0-SNAPSHOT-jar-with-dependencies.jar
├── ipaTest.iml
├── src
│ └── main
│ │ └── java
│ │ ├── utils
│ │ ├── ReUtils.java
│ │ ├── FileUtils.java
│ │ └── IpaUtil.java
│ │ ├── test.java
│ │ ├── vo
│ │ └── ipaInfo.java
│ │ └── MainUI.java
└── pom.xml
├── iOS-checkIPA.jar
├── README.md
├── .gitignore
└── AnalysisRecord
└── ipa文件分析.txt
/GUITools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Github-Benjamin/iOS-checkIPA/HEAD/GUITools.png
--------------------------------------------------------------------------------
/ipaTest/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/iOS-checkIPA.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Github-Benjamin/iOS-checkIPA/HEAD/iOS-checkIPA.jar
--------------------------------------------------------------------------------
/ipaTest/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ipaTest/ipaTest.iml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/ipaTest/target/ipaTest-1.0-SNAPSHOT.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Github-Benjamin/iOS-checkIPA/HEAD/ipaTest/target/ipaTest-1.0-SNAPSHOT.jar
--------------------------------------------------------------------------------
/ipaTest/target/maven-archiver/pom.properties:
--------------------------------------------------------------------------------
1 | #Generated by Maven
2 | #Wed Jan 09 21:18:03 CST 2019
3 | version=1.0-SNAPSHOT
4 | groupId=ipaTest
5 | artifactId=ipaTest
6 |
--------------------------------------------------------------------------------
/ipaTest/target/ipaTest-1.0-SNAPSHOT-jar-with-dependencies.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Github-Benjamin/iOS-checkIPA/HEAD/ipaTest/target/ipaTest-1.0-SNAPSHOT-jar-with-dependencies.jar
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # iOS-checkIPA
2 | Java Scans an IPA file and parses its Info.plist and embedded.mobileprovision files. Performs checks of expected key/value relationships and displays the results.
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.war
15 | *.nar
16 | *.ear
17 | *.zip
18 | *.tar.gz
19 | *.rar
20 |
21 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
22 | hs_err_pid*
23 |
--------------------------------------------------------------------------------
/ipaTest/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst:
--------------------------------------------------------------------------------
1 | C:\Users\xielianshi\Desktop\javas\ipaTest\src\main\java\utils\IpaUtil.java
2 | C:\Users\xielianshi\Desktop\javas\ipaTest\src\main\java\MainUI.java
3 | C:\Users\xielianshi\Desktop\javas\ipaTest\src\main\java\utils\FileUtils.java
4 | C:\Users\xielianshi\Desktop\javas\ipaTest\src\main\java\vo\ipaInfo.java
5 | C:\Users\xielianshi\Desktop\javas\ipaTest\src\main\java\utils\ReUtils.java
6 | C:\Users\xielianshi\Desktop\javas\ipaTest\src\main\java\test.java
7 |
--------------------------------------------------------------------------------
/ipaTest/src/main/java/utils/ReUtils.java:
--------------------------------------------------------------------------------
1 | package utils;
2 |
3 | import java.util.regex.Matcher;
4 | import java.util.regex.Pattern;
5 |
6 | /**
7 | * Created by Benjamin on 2019/1/9.
8 | */
9 | public class ReUtils {
10 |
11 | // 传入正则表达式和字符串匹配指定字符串
12 | public static String findString(String filedata,String re){
13 | // 正则匹配dict字段
14 | Pattern fildDict = Pattern.compile(re);
15 | Matcher fildDictData = fildDict.matcher(filedata);
16 | if ( fildDictData.find( )) {
17 | return fildDictData.group(1);
18 | }
19 | return null;
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/AnalysisRecord/ipa文件分析.txt:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | iOS Info.plist
5 | Android AndroidManifest.xml
6 |
7 | 在线解析:
8 | http://www.atool.org/plist_reader.php
9 |
10 | 扫毒报告:
11 | https://www.virustotal.com/zh-cn/file/fd23a30f2f6d2f1b0b2aae18e4f5be3adbe3a05752937cbcdfd5a362dbe26ae5/analysis/1546943243/
12 |
13 |
14 |
15 | ----------------
16 | 文件基本信息
17 | ----------------
18 |
19 | CFBundleIconFiles icon
20 |
21 | CFBundleName | name
22 | CFBundleIdentifier | packge
23 | CFBundleShortVersionString | versionName
24 | CFBundleVersion | versionCode
25 | MinimumOSVersion | Min.SDK
26 | 证书MD5 | 目前缺失
27 |
28 |
29 | 文件信息:
30 | 文件名路径
31 | MD5
32 | 大小
33 |
34 |
35 |
36 | 签名信息:embedded.mobileprovision
37 |
38 | Name | string | iOS Team Inhouse Provisioning Profile: xxx
39 | AppIDName | string | XC com xxx
40 | UUID | string | xxx
41 | TeamName | string | xxx
42 | CreationDate | date 无需要该信息 | 2018-04-28T06:52:43Z
43 | ExpirationDate | date | 2018-12-15T04:23:56Z
44 |
--------------------------------------------------------------------------------
/ipaTest/src/main/java/test.java:
--------------------------------------------------------------------------------
1 |
2 | import org.apache.commons.codec.digest.DigestUtils;
3 | import utils.IpaUtil;
4 | import vo.ipaInfo;
5 | import java.io.*;
6 | import java.text.DecimalFormat;
7 |
8 |
9 | /**
10 | * Created by Benjamin on 2019/1/8.
11 | */
12 | public class test {
13 |
14 | private static String filename = "C:\\Users\\xielianshi\\Desktop\\iOS测试整理\\test\\aibench.ipa";
15 |
16 | public static void main(String[] args) throws Exception {
17 |
18 |
19 | // System.out.println(DigestUtils.md5Hex(new FileInputStream(filename))); // 获取文件MD5
20 | //
21 | // File file = new File(filename);
22 | // if (file.exists() && file.isFile()) {
23 | // String fileName = file.getName();
24 | // System.out.println(file.length()); // 打印字节
25 | //
26 | // float num= (float)file.length()/1024/1024;
27 | // DecimalFormat df = new DecimalFormat("0.00");//格式化小数
28 | // String s = df.format(num);
29 | // System.out.println(s);
30 | // }
31 |
32 |
33 | // File files = new File(filename);
34 | // IpaUtil.getIpaMobileProvisio(files);
35 | //
36 | // // 获取一条信息
37 | // System.out.println(ipaInfo.getAppName());
38 | // System.out.println(ipaInfo.getPackgeName());
39 | // System.out.println(ipaInfo.getVersionCode());
40 | // System.out.println(ipaInfo.getVersionName());
41 | // System.out.println(ipaInfo.getMinSdk());
42 | //
43 | // System.out.println(ipaInfo.getProvisionName());
44 | // System.out.println(ipaInfo.getAppIDName());
45 | // System.out.println(ipaInfo.getUUID());
46 | // System.out.println(ipaInfo.getTeamName());
47 | // System.out.println(ipaInfo.getExpirationDate());
48 |
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/ipaTest/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | ipaTest
8 | ipaTest
9 | 1.0-SNAPSHOT
10 |
11 |
12 |
13 |
14 |
15 |
16 | commons-codec
17 | commons-codec
18 | 1.11
19 |
20 |
21 | com.googlecode.plist
22 | dd-plist
23 | 1.16
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | org.apache.maven.plugins
36 | maven-assembly-plugin
37 | 2.5.5
38 |
39 |
40 |
41 |
42 | MainUI
43 |
44 |
45 |
46 | jar-with-dependencies
47 |
48 |
49 |
50 |
51 | org.apache.maven.plugins
52 | maven-compiler-plugin
53 |
54 | 6
55 | 6
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/ipaTest/src/main/java/utils/FileUtils.java:
--------------------------------------------------------------------------------
1 | package utils;
2 |
3 | import org.apache.commons.codec.digest.DigestUtils;
4 | import vo.ipaInfo;
5 |
6 | import java.io.*;
7 | import java.text.DecimalFormat;
8 |
9 | /**
10 | * Created by Benjamin on 2019/1/9.
11 | */
12 | public class FileUtils {
13 |
14 | // 回收资源,删除文件
15 | public static void fileDelet(File filename){
16 | // 如果有必要,应该删除解压的结果文件
17 | boolean result = filename.delete();
18 |
19 | int tryCount = 0;
20 | while(!result && tryCount++ < 6 )
21 | {
22 | System.gc();
23 | result = filename.delete();
24 | }
25 |
26 | // if ( !result ) {
27 | // System.gc(); // 强制解除对文件的占用,回收资源
28 | // filename.delete();
29 | // }
30 |
31 | filename.getParentFile().delete();
32 |
33 | }
34 |
35 | // 读文件并以字符串形式返回
36 | public static String fileRead(File filename) throws IOException {
37 | /* 读入文件 */
38 | InputStreamReader reader = new InputStreamReader(new FileInputStream(filename)); // 建立一个输入流对象reader
39 | BufferedReader br = new BufferedReader(reader); // 建立一个对象,它把文件内容转成计算机能读懂的语言
40 |
41 | String filedata = "";
42 | String line = "";
43 | line = br.readLine();
44 | while (line != null) {
45 | line = br.readLine(); // 一次读入一行数据
46 | filedata += line;
47 | }
48 | br.close(); // 关闭文件流
49 |
50 | return filedata;
51 | }
52 |
53 | // 判断文件后缀名并存储到实体类中
54 | public static void fileName(String dirpath,String filename){
55 |
56 | if ( filename.substring(filename.length() - 3).equals("ipa") ){ //文件后缀名是否包含 ipa
57 | ipaInfo.setFilePath( dirpath + filename );
58 | }else if (dirpath == null || filename == null){ //判断路径和文件是否为空
59 | ipaInfo.setFilePath( null );
60 | }
61 | else{
62 | ipaInfo.setFilePath( null );
63 | }
64 |
65 | }
66 |
67 | // 获取文件MD5
68 | public static void getFileMD5(String filename) throws IOException {
69 | // 设置文件MD5值
70 | String fileMD5 = DigestUtils.md5Hex(new FileInputStream(filename));
71 | ipaInfo.setFileMD5(fileMD5);
72 |
73 | }
74 |
75 | // 获取文件大小
76 | public static void getFileSize(String filename) throws IOException {
77 |
78 | getFileMD5(filename); // 获取文件MD5
79 |
80 | File file = new File(filename);
81 | if (file.exists() && file.isFile()) {
82 |
83 | long filelen = file.length();
84 | float num= (float)filelen/1024/1024;
85 | DecimalFormat df = new DecimalFormat("0.00"); //格式化小数
86 |
87 | ipaInfo.setFileSizeByte(String.valueOf(filelen));
88 | ipaInfo.setFileSizeMB(df.format(num));
89 | }
90 |
91 | }
92 |
93 |
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/ipaTest/src/main/java/vo/ipaInfo.java:
--------------------------------------------------------------------------------
1 | package vo;
2 |
3 | import java.io.File;
4 |
5 | /**
6 | * Created by Benjamin on 2019/1/9.
7 | */
8 | public class ipaInfo {
9 | public static String appName;
10 | public static String packgeName;
11 | public static String versionCode;
12 | public static String versionName;
13 | public static String minSdk;
14 |
15 | public static String provisionName;
16 | public static String AppIDName;
17 | public static String UUID;
18 | public static String TeamName;
19 | public static String ExpirationDate;
20 |
21 | public static String filePath;
22 | public static File mobileprovision;
23 |
24 | public static String fileMD5;
25 | public static String fileSizeByte;
26 | public static String fileSizeMB;
27 |
28 |
29 | public static String getAppName() {
30 | return appName;
31 | }
32 |
33 | public static void setAppName(String appName) {
34 | ipaInfo.appName = appName;
35 | }
36 |
37 | public static String getPackgeName() {
38 | return packgeName;
39 | }
40 |
41 | public static void setPackgeName(String packgeName) {
42 | ipaInfo.packgeName = packgeName;
43 | }
44 |
45 | public static String getVersionCode() {
46 | return versionCode;
47 | }
48 |
49 | public static void setVersionCode(String versionCode) {
50 | ipaInfo.versionCode = versionCode;
51 | }
52 |
53 | public static String getVersionName() {
54 | return versionName;
55 | }
56 |
57 | public static void setVersionName(String versionName) {
58 | ipaInfo.versionName = versionName;
59 | }
60 |
61 | public static String getMinSdk() {
62 | return minSdk;
63 | }
64 |
65 | public static void setMinSdk(String minSdk) {
66 | ipaInfo.minSdk = minSdk;
67 | }
68 |
69 | public static String getProvisionName() {
70 | return provisionName;
71 | }
72 |
73 | public static void setProvisionName(String provisionName) {
74 | ipaInfo.provisionName = provisionName;
75 | }
76 |
77 | public static String getAppIDName() {
78 | return AppIDName;
79 | }
80 |
81 | public static void setAppIDName(String appIDName) {
82 | AppIDName = appIDName;
83 | }
84 |
85 | public static String getUUID() {
86 | return UUID;
87 | }
88 |
89 | public static void setUUID(String UUID) {
90 | ipaInfo.UUID = UUID;
91 | }
92 |
93 | public static String getTeamName() {
94 | return TeamName;
95 | }
96 |
97 | public static void setTeamName(String teamName) {
98 | TeamName = teamName;
99 | }
100 |
101 | public static String getExpirationDate() {
102 | return ExpirationDate;
103 | }
104 |
105 | public static void setExpirationDate(String expirationDate) {
106 | ExpirationDate = expirationDate;
107 | }
108 |
109 | public static String getFilePath() {
110 | return filePath;
111 | }
112 |
113 | public static void setFilePath(String filePath) {
114 | ipaInfo.filePath = filePath;
115 | }
116 |
117 | public static File getMobileprovision() {
118 | return mobileprovision;
119 | }
120 |
121 | public static void setMobileprovision(File mobileprovision) {
122 | ipaInfo.mobileprovision = mobileprovision;
123 | }
124 |
125 | public static String getFileMD5() {
126 | return fileMD5;
127 | }
128 |
129 | public static void setFileMD5(String fileMD5) {
130 | ipaInfo.fileMD5 = fileMD5;
131 | }
132 |
133 | public static String getFileSizeByte() {
134 | return fileSizeByte;
135 | }
136 |
137 | public static void setFileSizeByte(String fileSizeByte) {
138 | ipaInfo.fileSizeByte = fileSizeByte;
139 | }
140 |
141 | public static String getFileSizeMB() {
142 | return fileSizeMB;
143 | }
144 |
145 | public static void setFileSizeMB(String fileSizeMB) {
146 | ipaInfo.fileSizeMB = fileSizeMB;
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/ipaTest/src/main/java/MainUI.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Benjamin on 2018/12/2.
3 | */
4 |
5 | import utils.FileUtils;
6 | import utils.IpaUtil;
7 | import vo.ipaInfo;
8 |
9 | import javax.swing.*;
10 | import java.awt.*;
11 | import java.awt.event.ActionEvent;
12 | import java.awt.event.ActionListener;
13 | import java.io.File;
14 |
15 | public class MainUI extends JFrame implements ActionListener {
16 |
17 | // 定义组件
18 | private static FileDialog openDia; // 文件打开窗口
19 | JButton EnterBtn,EmptyBtn; // 定义确认按钮
20 | JMenuItem MenuAbout;
21 | JLabel ipainfo,noneline,fileinfo,appName,packgeName,versionCode,versionName,minSdk,provisionName,AppIDName,UUID,TeamName,ExpirationDate,filePaths,fileMD5,fileSize;
22 |
23 | public static void main(String[] args) {
24 | MainUI mUI=new MainUI();
25 | }
26 |
27 | public MainUI()
28 | {
29 |
30 | // 创建组件并设置监听
31 | EnterBtn = new JButton("获取IPA信息");
32 | EmptyBtn = new JButton("清空");
33 | EnterBtn.addActionListener(this);
34 | EmptyBtn.addActionListener(this);
35 |
36 | //初始化一个菜单栏
37 | JMenuBar menuBar = new JMenuBar();
38 | MenuAbout = new JMenuItem("About");
39 | menuBar.add(MenuAbout);
40 | myEvent(); // 加载菜单栏监听事件处理
41 |
42 | getContentPane().add(new JLabel("IPA 信息", SwingConstants.CENTER ));
43 | ipainfo = new JLabel("");
44 | getContentPane().add(ipainfo);
45 |
46 | getContentPane().add(new JLabel("appName:", SwingConstants.CENTER ));
47 | appName = new JLabel("CFBundleName");
48 | getContentPane().add(appName);
49 |
50 | getContentPane().add(new JLabel("packgeName:", SwingConstants.CENTER ));
51 | packgeName = new JLabel("CFBundleIdentifier");
52 | getContentPane().add(packgeName);
53 |
54 | getContentPane().add(new JLabel("versionName:", SwingConstants.CENTER ));
55 | versionName = new JLabel("CFBundleShortVersionString");
56 | getContentPane().add(versionName);
57 |
58 | getContentPane().add(new JLabel("versionCode:", SwingConstants.CENTER ));
59 | versionCode = new JLabel("CFBundleVersion");
60 | getContentPane().add(versionCode);
61 |
62 | getContentPane().add(new JLabel("minSdk:", SwingConstants.CENTER ));
63 | minSdk = new JLabel("MinimumOSVersion");
64 | getContentPane().add(minSdk);
65 |
66 | getContentPane().add(new JLabel("provisionName:", SwingConstants.CENTER ));
67 | provisionName = new JLabel("provisionName");
68 | getContentPane().add(provisionName);
69 |
70 | getContentPane().add(new JLabel("AppIDName:", SwingConstants.CENTER ));
71 | AppIDName = new JLabel("provisionAppIDName", SwingConstants.LEFT );
72 | getContentPane().add(AppIDName);
73 |
74 | getContentPane().add(new JLabel("UUID:", SwingConstants.CENTER ));
75 | UUID = new JLabel("provisionUUID", SwingConstants.LEFT );
76 | getContentPane().add(UUID);
77 |
78 | getContentPane().add(new JLabel("TeamName:", SwingConstants.CENTER ));
79 | TeamName = new JLabel("TeamName", SwingConstants.LEFT );
80 | getContentPane().add(TeamName);
81 |
82 | getContentPane().add(new JLabel("ExpirationDate:", SwingConstants.CENTER ));
83 | ExpirationDate = new JLabel("ExpirationDate", SwingConstants.LEFT );
84 | getContentPane().add(ExpirationDate);
85 |
86 | getContentPane().add(new JLabel(" ", SwingConstants.CENTER ));
87 | noneline = new JLabel(" ");
88 | getContentPane().add(noneline);
89 |
90 | getContentPane().add(new JLabel("文件信息", SwingConstants.CENTER ));
91 | fileinfo = new JLabel("");
92 | getContentPane().add(fileinfo);
93 |
94 | getContentPane().add(new JLabel("filePath:", SwingConstants.CENTER ));
95 | filePaths = new JLabel("filePath");
96 | getContentPane().add(filePaths);
97 |
98 | getContentPane().add(new JLabel("fileMD5:", SwingConstants.CENTER ));
99 | fileMD5 = new JLabel("fileMD5");
100 | getContentPane().add(fileMD5);
101 |
102 | getContentPane().add(new JLabel("fileSize:", SwingConstants.CENTER ));
103 | fileSize = new JLabel("fileSize");
104 | getContentPane().add(fileSize);
105 |
106 | getContentPane().add(new JLabel(" ", SwingConstants.CENTER ));
107 | noneline = new JLabel(" ");
108 | getContentPane().add(noneline);
109 |
110 | getContentPane().add(EnterBtn);
111 | getContentPane().add(EmptyBtn);
112 |
113 | openDia = new FileDialog(this, "打开", FileDialog.LOAD);
114 |
115 | this.setJMenuBar(menuBar); //设置菜单栏
116 | this.setLayout(new GridLayout(0,2)); //选择GridLayout布局管理器
117 | this.setTitle("iOS-checkIPA");
118 | this.setSize(700,500);
119 | this.setLocation(0, 0);
120 | this.setLocationRelativeTo(null);//窗体居中显示
121 | this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置当关闭窗口时,保证JVM也退出
122 | this.setVisible(true);
123 | this.setResizable(true);
124 |
125 | }
126 |
127 |
128 | // 菜单栏监听
129 | private void myEvent()
130 | {
131 | // About 菜单栏监听
132 | MenuAbout.addActionListener(new ActionListener()
133 | {
134 | public void actionPerformed(ActionEvent e)
135 | {
136 | JOptionPane.showMessageDialog(null, "Author: Benjamin\nWeChat: WeChat_Benjamin\nEmail: Benjamin_v@qq.com", "AboutInfo",JOptionPane.INFORMATION_MESSAGE);
137 | return;
138 | }
139 | });
140 | }
141 |
142 |
143 | // 事件判断
144 | @Override
145 | public void actionPerformed(ActionEvent e) {
146 |
147 | if(e.getActionCommand()=="获取IPA信息") {
148 |
149 | getFilePath(); // 获取文件路径
150 | String filePath = ipaInfo.getFilePath();
151 |
152 |
153 | if ( filePath == null ){ //判断路径和文件是否为空,或非ipa后缀文件
154 | JOptionPane.showMessageDialog(null,"读取ipa文件异常,请切换文件或替换文件目录后重试。","提示消息",JOptionPane.WARNING_MESSAGE);
155 | return;
156 | } else {
157 | try {
158 | FileUtils.getFileSize(filePath); // 获取文件信息
159 | File files = new File(filePath); // 获取ipa文件路径
160 | IpaUtil.getIpaMobileProvisio(files); // 获取并分析文件信息
161 | } catch (Exception e1) {
162 | JOptionPane.showMessageDialog(null,"读取ipa文件异常,请切换文件或替换文件目录后重试。","提示消息",JOptionPane.WARNING_MESSAGE);
163 | e1.printStackTrace();
164 | return;
165 | }
166 |
167 | appName.setText(ipaInfo.getAppName());
168 | packgeName.setText(ipaInfo.getPackgeName());
169 | versionCode.setText(ipaInfo.getVersionCode());
170 | versionName.setText(ipaInfo.getVersionName());
171 | minSdk.setText(ipaInfo.getMinSdk());
172 | provisionName.setText(ipaInfo.getProvisionName());
173 | AppIDName.setText(ipaInfo.getAppIDName());
174 | UUID.setText(ipaInfo.getUUID());
175 | TeamName.setText(ipaInfo.getTeamName());
176 | ExpirationDate.setText(ipaInfo.getExpirationDate());
177 |
178 | filePaths.setText(ipaInfo.getFilePath());
179 | fileMD5.setText(ipaInfo.getFileMD5());
180 | fileSize.setText( ipaInfo.getFileSizeByte() + " 字节(" + ipaInfo.getFileSizeMB() + " MB)" );
181 |
182 | return;
183 | }
184 |
185 | }
186 |
187 | else if(e.getActionCommand() == "清空" ){
188 |
189 | Object ipaInfo=new ipaInfo();
190 | ipaInfo = null; // 清空对象,对象被赋值为null将被视为垃圾
191 |
192 | appName.setText("NaN");
193 | packgeName.setText("NaN");
194 | versionCode.setText("NaN");
195 | versionName.setText("NaN");
196 | minSdk.setText("NaN");
197 | provisionName.setText("NaN");
198 | AppIDName.setText("NaN");
199 | UUID.setText("NaN");
200 | TeamName.setText("NaN");
201 | ExpirationDate.setText("NaN");
202 |
203 | filePaths.setText("NaN");
204 | fileMD5.setText("NaN");
205 | fileSize.setText("NaN");
206 |
207 | return;
208 |
209 | }
210 |
211 | }
212 |
213 | // 弹出窗口选择获取文件路径
214 | public static void getFilePath(){
215 | openDia.setVisible(true); // 显示打开文件对话框
216 | String dirpath = openDia.getDirectory(); //获取打开文件路径并保存到字符串中。
217 | String fileName = openDia.getFile(); //获取打开文件名称并保存到字符串中
218 | // System.out.println(dirpath+fileName); // 打印获取到的文件路径
219 | FileUtils.fileName(dirpath,fileName); // 判断文件后缀
220 | }
221 |
222 |
223 | }
224 |
--------------------------------------------------------------------------------
/ipaTest/src/main/java/utils/IpaUtil.java:
--------------------------------------------------------------------------------
1 |
2 | package utils;
3 |
4 | import com.dd.plist.NSDictionary;
5 | import com.dd.plist.NSString;
6 | import com.dd.plist.PropertyListParser;
7 | import vo.ipaInfo;
8 | import java.io.*;
9 | import java.util.Enumeration;
10 | import java.util.zip.ZipEntry;
11 | import java.util.zip.ZipFile;
12 |
13 | /**
14 | * Created by Benjamin on 2019/1/8.
15 | */
16 |
17 |
18 |
19 | public class IpaUtil {
20 |
21 | private static String reBody = "(.*?)";
22 | private static String reprovisionName = "Name.*?(.*?)";
23 | private static String reAppIDName = "AppIDName.*?(.*?)";
24 | private static String reUUID = "UUID.*?(.*?)";
25 | private static String reTeamName = "TeamName.*?(.*?)";
26 | private static String reExpirationDate = "ExpirationDate.*?(.*?)";
27 | private static String notFoundFile = "ipa no embedded.mobileprovision file";
28 |
29 | /**
30 | * 解压IPA文件,只获取IPA文件中的Info.plist、embedded.mobileprovision文件存储指定位置
31 | * @param file zip文件
32 | * @param unzipDirectory 解压到的目录
33 | * @throws Exception
34 | */
35 | private static File getZipInfo(File file, String unzipDirectory) throws Exception{
36 | // 定义输入输出流对象
37 | InputStream input = null;
38 | OutputStream output = null;
39 | File result = null;
40 | File unzipFile = null;
41 | ZipFile zipFile = null;
42 |
43 | try{
44 | // 创建zip文件对象
45 | zipFile = new ZipFile(file);
46 | // 创建本zip文件解压目录
47 | String name = file.getName().substring(0, file.getName().lastIndexOf("."));
48 | unzipFile = new File(unzipDirectory + "/" + name);
49 | if(unzipFile.exists()){
50 | unzipFile.delete();
51 | }
52 | unzipFile.mkdir();
53 | // 得到zip文件条目枚举对象
54 | Enumeration extends ZipEntry> zipEnum = zipFile.entries();
55 | // 定义对象
56 | ZipEntry entry = null;
57 | String entryName = null;
58 | String names[] = null;
59 | int length;
60 |
61 | // 循环读取条目
62 | while(zipEnum.hasMoreElements()){
63 | // 得到当前条目
64 | entry = zipEnum.nextElement();
65 | entryName = new String(entry.getName());
66 | // 用/分隔条目名称
67 | names = entryName.split("\\/");
68 | length = names.length;
69 | for(int v = 0; v < length; v++){
70 |
71 |
72 | if(entryName.endsWith(".app/embedded.mobileprovision")){ // 为embedded.mobileprovision文件,则输出到文件
73 | input = zipFile.getInputStream(entry);
74 | result = new File(unzipFile.getAbsolutePath() + "/embedded.mobileprovision");
75 | ipaInfo.setMobileprovision(result); // 将embedded.mobileprovision存到模块实体类中
76 | output = new FileOutputStream(result);
77 | byte[] buffer = new byte[1024 * 8];
78 | int readLen = 0;
79 | while((readLen = input.read(buffer, 0, 1024 * 8)) != -1){
80 | output.write(buffer, 0, readLen);
81 | }
82 | break;
83 | }
84 |
85 | if(entryName.endsWith(".app/Info.plist")){ // 为Info.plist文件,则输出到文件
86 | input = zipFile.getInputStream(entry);
87 | result = new File(unzipFile.getAbsolutePath() + "/Info.plist");
88 | output = new FileOutputStream(result);
89 | byte[] buffer = new byte[1024 * 8];
90 | int readLen = 0;
91 | while((readLen = input.read(buffer, 0, 1024 * 8)) != -1){
92 | output.write(buffer, 0, readLen);
93 | }
94 | break;
95 | }
96 |
97 | }
98 | }
99 | }
100 | catch(Exception ex){
101 | ex.printStackTrace();
102 | }
103 | finally{
104 | if(input != null){
105 | input.close();
106 | }
107 | if(output != null){
108 | output.flush();
109 | output.close();
110 | }
111 | // 必须关流,否则文件无法删除
112 | if(zipFile != null){
113 | zipFile.close();
114 | }
115 | }
116 |
117 | // 如果有必要删除多余的文件
118 | if(file.exists()){
119 | file.delete();
120 | }
121 |
122 | return result;
123 | }
124 |
125 |
126 |
127 | /**
128 | * IPA文件的拷贝,把一个IPA文件复制为Zip文件,同时返回Info.plist文件 参数 oldfile 为 IPA文件
129 | */
130 | private static File getIpaInfo(File oldfile) throws IOException {
131 | try{
132 | int byteread = 0;
133 | String filename = oldfile.getAbsolutePath().replaceAll(".ipa", ".zip");
134 | File newfile = new File(filename);
135 | if(oldfile.exists()){
136 | // 创建一个Zip文件
137 | InputStream inStream = new FileInputStream(oldfile);
138 | FileOutputStream fs = new FileOutputStream(newfile);
139 | byte[] buffer = new byte[1444];
140 | while((byteread = inStream.read(buffer)) != -1){
141 | fs.write(buffer, 0, byteread);
142 | }
143 | if(inStream != null){
144 | inStream.close();
145 | }
146 | if(fs != null){
147 | fs.close();
148 | }
149 | // 解析Zip文件
150 | return getZipInfo(newfile, newfile.getParent());
151 | }
152 | }
153 | catch(Exception e){
154 | e.printStackTrace();
155 | }
156 | return null;
157 | }
158 |
159 |
160 |
161 | /**
162 | * 通过IPA文件获取Info.plist信息
163 | */
164 | public static void getIpaInfoMap(File ipa) throws Exception{
165 |
166 | File file = getIpaInfo(ipa);
167 |
168 | // Map map = new HashMap();
169 |
170 | // 需要第三方jar包dd-plist
171 | NSDictionary rootDict = (NSDictionary)PropertyListParser.parse(file);
172 |
173 | // 应用包名
174 | NSString parameters = (NSString)rootDict.objectForKey("CFBundleIdentifier");
175 | // map.put("CFBundleIdentifier", parameters.toString());
176 | ipaInfo.setPackgeName(parameters.toString());
177 |
178 | // 应用名称
179 | parameters = (NSString) rootDict.objectForKey("CFBundleName");
180 | // map.put("CFBundleName", parameters.toString());
181 | ipaInfo.setAppName(parameters.toString());
182 |
183 | // 应用外部版本
184 | parameters = (NSString)rootDict.objectForKey("CFBundleShortVersionString");
185 | // map.put("CFBundleShortVersionString", parameters.toString());
186 | ipaInfo.setVersionName(parameters.toString());
187 |
188 | // 应用内部版本
189 | parameters = (NSString)rootDict.objectForKey("CFBundleVersion");
190 | // map.put("CFBundleVersion", parameters.toString());
191 | ipaInfo.setVersionCode(parameters.toString());
192 |
193 | // 应用所需IOS最低版本
194 | parameters = (NSString)rootDict.objectForKey("MinimumOSVersion");
195 | // map.put("MinimumOSVersion", parameters.toString());
196 | ipaInfo.setMinSdk(parameters.toString());
197 |
198 | // 如果有必要,应该删除解压的结果文件
199 | FileUtils.fileDelet(file);
200 |
201 | }
202 |
203 | /**
204 | * 通过IPA文件获取embedded.mobileprovision信息
205 | */
206 | public static void getIpaMobileProvisio(File ipa) throws Exception {
207 |
208 | // 解压文件 Info.plist、embedded.mobileprovision,解析Info.plist文件并获取embedded.mobileprovision文件中的信息
209 | getIpaInfoMap(ipa);
210 |
211 | try {
212 |
213 | // 获取文件并以字符串的形式返回
214 | File filename = ipaInfo.getMobileprovision();
215 | String filedata = FileUtils.fileRead(filename);
216 |
217 | // 正则匹配Body字段
218 | String dictData = ReUtils.findString(filedata,reBody);
219 |
220 | // 匹配 provisionName
221 | ipaInfo.setProvisionName(ReUtils.findString(dictData,reprovisionName));
222 |
223 | // 匹配 reAppIDName
224 | ipaInfo.setAppIDName(ReUtils.findString(dictData,reAppIDName));
225 |
226 | // 匹配 UUID
227 | ipaInfo.setUUID(ReUtils.findString(dictData,reUUID).replaceAll("-",""));
228 |
229 | // 匹配 reTeamName
230 | ipaInfo.setTeamName(ReUtils.findString(dictData,reTeamName));
231 |
232 | // 匹配 reExpirationDate
233 | ipaInfo.setExpirationDate(ReUtils.findString(dictData,reExpirationDate));
234 |
235 | // 如果有必要,应该删除解压的结果文件
236 | FileUtils.fileDelet(filename);
237 | }catch(Exception e){
238 |
239 | ipaInfo.setProvisionName(notFoundFile);
240 | ipaInfo.setAppIDName(notFoundFile);
241 | ipaInfo.setUUID(notFoundFile);
242 | ipaInfo.setTeamName(notFoundFile);
243 | ipaInfo.setExpirationDate(notFoundFile);
244 |
245 | e.printStackTrace();
246 | }
247 |
248 | }
249 |
250 |
251 |
252 | }
253 |
254 |
--------------------------------------------------------------------------------