package com.xunlei.app.tools;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* @author pengjin 2013-08-01
*
*
* apk icon全尺寸解析(解决有些apk解析信息比较特殊的bug:application-icon-120:'res/drawable-xlarge-mdpi/appicon.xml)
*/
public class ApkIconTool {
public static String separator = File.separator;
static String[] dpis = new String[] { "ldpi", "mdpi", "hdpi", "xhdpi" };
/**
* 解析获取icon
*
* @param apkPath
* @param imgPath
* @throws InterruptedException
* @throws IOException
*/
public static void getIcon(String apkPath, String imgPath)
throws InterruptedException, IOException {
// 通过aapt解析apk信息到文件中
String apkName = apkPath.substring(apkPath.lastIndexOf(separator) + 1);
if (!isLinux() && apkName.indexOf(".") != -1) {
apkName = apkName.substring(0, apkName.lastIndexOf("."));
}
String imgDir = imgPath
.substring(0, imgPath.lastIndexOf(separator) + 1);
String imgName = imgPath.substring(imgPath
.lastIndexOf(separator) + 1);
String aaptPath = ApkIconTool.class.getClassLoader()
.getResource("config.xml").getPath();
// 打包后在windows环境下
if (aaptPath.startsWith("file:/") && !isLinux()) {
//System.out.println("run in windows");
aaptPath = aaptPath.substring(6);
}
// 打包后在linux环境下
if (aaptPath.startsWith("file:/") && isLinux()) {
//System.out.println("run in linux");
aaptPath = aaptPath.substring(5);
}
// 调试环境和linux下aaptPath都会以"/"开头
if (aaptPath.startsWith("/") && !isLinux()) {
//System.out.println("调试环境下");
aaptPath = aaptPath.substring(1);
}
aaptPath = aaptPath.substring(0, aaptPath.indexOf("config.xml") - 1);
aaptPath = aaptPath.substring(0, aaptPath.lastIndexOf("/") + 1);
aaptPath = isLinux() ? aaptPath + "aapt" : aaptPath + "aapt.exe";
Process pcs = null;
try {
/*String commond = aaptPath + " d badging " + apkPath + ">" + imgDir
+ apkName + ".txt";*/
String commond = aaptPath + " d badging " + apkPath ;
/*
* System.out.println("---------exec commond:" + commond +
* "---------------------");
*/
String[] shell = { "/bin/sh", "-c", commond };
String[] cmd = { "cmd.exe ", "/C", commond };
if (isLinux()) {
pcs = Runtime.getRuntime().exec(shell);
} else {
pcs = Runtime.getRuntime().exec(cmd);
}
} catch (IOException e) {
e.printStackTrace();
}
InputStream msgStream = pcs.getInputStream();
// 解析apk信息文件。获取icon路径及icon名
//String msgPath = imgDir + apkName + ".txt";
// 全尺寸解析icon图标
//Map<String, String> iconInfo = getIconInfo(msgPath);
//new File(msgPath).delete();
Map<String, String> iconInfo = getIconInfoEX(msgStream);
pcs.waitFor();// 阻塞外部程序
/*String iconPath = null;
// 优先使用72*72图片
iconPath = iconInfo.get("hdpi") == null ? iconInfo.get("default")
: iconInfo.get("hdpi");
iconInfo.put("default", iconPath);*/
//System.out.println("aapt Last iconPath====================" + iconPath);
// 解压apk包查找icon
if(iconInfo==null){//aapt解析不出调apktool反编译
GetIconFile.getIcon(apkPath, imgDir, imgName);
Map<String,String> iconResult = new HashMap<String, String>();
for (String dpi : dpis) {
iconResult.put(dpi, "");
}
iconResult.put("hdpi", imgPath+";"+getIconDpi(imgPath));
//打印结果
printMapJson(iconResult);
}else{
writeFile(apkPath, imgPath, iconInfo);
}
}
/**
* @return
*
* 判断是否是linux
*/
public static boolean isLinux() {
return !"\\".equals(File.separator);
}
/**
* 获取icon各分辨率路径及apk使用的icon路径
*
* @param path
* @return
* @throws IOException
*/
public static Map<String, String> getIconInfo(String path)
throws IOException {
Map<String, String> map = new HashMap<String, String>();
for (String dpi : dpis) {
map.put(dpi, "");
}
String iconPath = "";
String iconRealPath = "";
BufferedReader br = null;
boolean isDpiExsis = false;
try {
br = new BufferedReader(new FileReader(path));
String s = null;
while ((s = br.readLine()) != null) {
// 各分辨率下icon路径
if (s.indexOf("application-icon") != -1) {
iconPath = s.substring(s.lastIndexOf(":") + 2,
s.length() - 1);
if(iconPath.endsWith(".xml")){
return null;
}
for (String dpi : dpis) {
if (s.indexOf("drawable-" + dpi) != -1) {
isDpiExsis = true;
map.put(dpi, iconPath);
}
}
}
// apk实际使用icon
if (s.indexOf("icon=") != -1 && "".equals(iconRealPath)) {
iconRealPath = s.substring(s.indexOf("icon") + 6,
s.length() - 1);
//map.put("default", iconRealPath);
}
}
//如果没有application-icon-120:'res/drawable/icontaxi.png 信息,保存apk实际使用icon信息
if(!isDpiExsis){
map.put("hdpi", iconRealPath);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
br.close();
}
}
return map;
}
/**
* 获取icon各分辨率路径及apk使用的icon路径
*
* @param path
* @return
* @throws IOException
*/
public static Map<String, String> getIconInfoEX(InputStream stream)
throws IOException {
Map<String, String> map = new HashMap<String, String>();
for (String dpi : dpis) {
map.put(dpi, "");
}
String iconPath = "";
String iconRealPath = "";
BufferedReader br = null;
boolean isDpiExsis = false;
try {
br = new BufferedReader(new InputStreamReader(stream));
String s = null;
while ((s = br.readLine()) != null) {
// 各分辨率下icon路径
if (s.indexOf("application-icon") != -1) {
iconPath = s.substring(s.lastIndexOf(":") + 2,
s.length() - 1);
if(iconPath.endsWith(".xml")){
return null;
}
for (String dpi : dpis) {
if (s.indexOf("drawable-" + dpi) != -1) {
isDpiExsis = true;
map.put(dpi, iconPath);
}
}
}
// apk实际使用icon
if (s.indexOf("icon=") != -1 && "".equals(iconRealPath)) {
iconRealPath = s.substring(s.indexOf("icon") + 6,
s.length() - 1);
//map.put("default", iconRealPath);
}
}
if(!isDpiExsis){
map.put("hdpi", iconRealPath);
}
/*System.out.println("aapt Default iconPath==============="
+ iconRealPath);*/
//printMapJson(map);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
br.close();
}
stream.close();
}
return map;
}
/**
*
*
* 根据解析的icon信息遍历apk输出图片
*
*
* @param apkPath
* @param imgPath
* @param iconInfo
* @throws IOException
*/
public static void writeFile(String apkPath, String imgPath,
Map<String, String> iconInfo) throws IOException {
FileInputStream in = null;
ZipInputStream zipin = null;
Map<String,String> iconResult = new HashMap<String, String>();
for (String dpi : dpis) {
iconResult.put(dpi, "");
}
try {
in = new FileInputStream(apkPath);
zipin = new ZipInputStream(in);
ZipEntry entry = null;
while ((entry = zipin.getNextEntry()) != null) {
String name = entry.getName();
for (Entry<String, String> e : iconInfo.entrySet()) {
if (!"".equals(e.getValue())&&!"default".equals(e.getKey())&&name.contains(e.getValue())) {
String imgDir = imgPath.substring(0,
imgPath.lastIndexOf(separator) + 1);
String imgName = imgPath.substring(imgPath
.lastIndexOf(separator) + 1);
if (!isLinux()&&imgName.indexOf(".") != -1) {
imgName = imgName
.substring(0, imgName.lastIndexOf("."))
+ "_"
+ e.getKey()
+ imgName
.substring(imgName.lastIndexOf("."));
} else {
imgName += "_" + e.getKey();
}
String dpiPath = imgDir + imgName;
FileOutputStream out = new FileOutputStream(new File(
dpiPath));
byte[] buff = new byte[1024];
int n = 0;
while ((n = zipin.read(buff, 0, buff.length)) != -1) {
out.write(buff, 0, n);
}
iconResult.put(e.getKey(), dpiPath+";"+getIconDpi(dpiPath));
iconInfo.remove(e.getKey());
break;
}
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (in != null) {
in.close();
}
if (zipin != null) {
zipin.close();
}
}
/*//加入default icon
for(Entry<String, String> e : iconResult.entrySet()){
if(iconInfo.get("default").contains(e.getKey())){
iconResult.put("default",e.getValue());
break;
}
}*/
//打印结果
printMapJson(iconResult);
}
public static void printMapJson(Map<String, String> map){
StringBuffer sb = new StringBuffer();
sb.append("{");
int i=0;
for(Entry<String, String> e : map.entrySet()){
i++;
sb.append("\"").append(e.getKey()).append("\":").append("\"").append(e.getValue()).append("\"");
if(i<map.size()){
sb.append(",");
}
}
sb.append("}");
System.out.println(sb.toString());
}
/**
* 返回图片像素值
*
* @param srcFileName
* @return
* @throws IOException
*/
public static String getIconDpi(String srcFileName) throws IOException {
BufferedImage src = null;
InputStream is = null;
try {
is = new FileInputStream(srcFileName);
src = javax.imageio.ImageIO.read(is);
} catch (Exception e) {
//e.printStackTrace();
return "";
}finally{
if(is!=null){
is.close();
}
}
int srcWidth = src.getWidth(null); // 得到源图宽
int srcHeight = src.getHeight(null); // 得到源图长
return String.valueOf(srcWidth)+"*"+String.valueOf(srcHeight);
}
public static void main(String[] getIcon) throws InterruptedException,
IOException {
getIcon(getIcon[0], getIcon[1]);
}
}