aapt在处理png文件的时候,会断定文件类型,若是不是png,将会抛出此错误。出现这个问题的缘由是咱们不少时候凭感受手动将jpeg之类的其余文件后缀名强制修改成png,这个时候看图软件仍然可以识别图片。可是aapt却不识别,致使编译失败。java
使用as正向构建android工程的时候,能够设置aapt参数忽略png。android
可是使用apkTool回编的时候,没有设置入口,由于只要有此问题发送,其命令行返回类型就是1(非正常退出)。apache
在执行aapt命令的时候,先行修复全部存在此问题的png文件,避免aapt阻断。方案以下:app
package brut.util; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; /** * Created by virjar on 2017/8/30. 修复png文件格式 * * <pre> * libpng error: Not a PNG fileERROR: Failure processing PNG image /Users/virjar/Desktop/9candroid/com.china3s.android_635/res/drawable/xprod_arrow_green.png * </pre> * * 该错误会致使aapt命令返回1(非正常返回值),致使apk阻断。本工具读取全部.png结尾的图片,若是发现他不是png,则尝试转化为png格式文件 */ public class PNGRepair { public static void repair(File file) { if (file == null) { return; } if (!file.exists()) { return; } if (file.isDirectory()) { File[] files = file.listFiles(); if (files == null) { return; } for (File subFile : files) { repair(subFile); } return; } if (!StringUtils.endsWithIgnoreCase(file.getPath(), ".png")) { // 不是png不处理 return; } ImageTypeBufferedInputStream imageTypeBufferedInputStream = null; try { imageTypeBufferedInputStream = new ImageTypeBufferedInputStream(new FileInputStream(file)); if (StringUtils.equalsIgnoreCase(imageTypeBufferedInputStream.mType, "png")) { return;// 自己就是png文件,忽略处理 } System.out.println( "file: " + file.getPath() + " is a " + imageTypeBufferedInputStream.mType + " transfer to png"); BufferedImage bufferedImage = ImageIO.read(imageTypeBufferedInputStream); IOUtils.closeQuietly(imageTypeBufferedInputStream);// close stream advance ImageIO.write(bufferedImage, "png", file); } catch (IOException e) { e.printStackTrace();// ignore } finally { // make sure stream is closed IOUtils.closeQuietly(imageTypeBufferedInputStream); } } private static class ImageTypeBufferedInputStream extends InputStream { private InputStream delegate; private byte[] type = new byte[4]; private byte cursor = 0; private String mType; ImageTypeBufferedInputStream(InputStream delegate) throws IOException { this.delegate = delegate; int read = delegate.read(type, 0, type.length); if (read < 4) { mType = "unknown"; return; } String s = bytesToHexString(type).toUpperCase(); if (StringUtils.equals(s, "FFD8FFE1")) { mType = "jpg"; } else if (StringUtils.equals(s, "89504E47")) { mType = "png"; } else if (StringUtils.equals(s, "47494638")) { mType = "gif"; } else if (StringUtils.equals(s, "424D0890")) { mType = "bmp"; } else { mType = "unknown"; } } private static String bytesToHexString(byte[] src) { StringBuilder stringBuilder = new StringBuilder(); if (src == null || src.length <= 0) { return ""; } for (byte aSrc : src) { int v = aSrc & 0xFF; String hv = Integer.toHexString(v); if (hv.length() < 2) { stringBuilder.append(0); } stringBuilder.append(hv); } return stringBuilder.toString(); } @Override public int read() throws IOException { if (cursor < 4) { return type[cursor++]; } return delegate.read(); } @Override public long skip(long n) throws IOException { return delegate.skip(n + 4 - cursor); } @Override public int available() throws IOException { return delegate.available() + cursor - 4; } @Override public void close() throws IOException { delegate.close(); } @Override public synchronized void mark(int readlimit) { delegate.mark(readlimit); } @Override public synchronized void reset() throws IOException { delegate.reset(); } @Override public boolean markSupported() { return delegate.markSupported(); } } }
public void aaptPackage(File apkFile, File manifest, File resDir, File rawDir, File assetDir, File[] include) throws AndrolibException { boolean customAapt = false; String aaptPath = apkOptions.aaptPath; List<String> cmd = new ArrayList<String>(); //convert png file //TODO add switch LOGGER.info("convert png file, to avoid \"libpng error: Not a PNG fileERROR\" from aapt"); PNGRepair.repair(resDir);//在这里加入修复代码 // path for aapt binary if (! aaptPath.isEmpty()) { File aaptFile = new File(aaptPath); if (aaptFile.canRead() && aaptFile.exist .....
流程方法全称为:brut.androlib.res.AndrolibResources#aaptPackage
ide
以后,编译便可通关工具