自动编译.9.png文件

.9.png文件是一种可以被android系统利用的可拉伸图片,可以使用draw9patch.bat工具处理普通的png文件来生成.9.png文件,这种经过处理的文件被称为.9.png的“源文件”,此时用图片浏览工具打开该文件可以看到图片的周围是一圈单像素,呈现黑色的像素点就是我们使用draw9patch.bat工具画上去的,当我们把图片放在res/drawable文件夹后,使用android编译之后,解压apk包,可以看到虽然res/drawable下的.9.png文件仍然存在,但是使用图片浏览工具打开的时候,它周围的一圈单像素点已经没有,此时的.9.png文件可以称为“编译文件”,有时候为了获取编译后的.9.png文件只能采用这种方法,先用draw9patch.bat处理,然后编译,最后解压apk包,最后拷出编译好的.9.png文件,其实完全可以使用程序模拟这一过程,这样使用的时候就可以直接导入.9.png图片,然后自动生成编译好的.9.png图片。

程序的设计很简单,调用系统的aapt.ext工具对包含png的程序进行处理,生成一个临时的apk包,然后使用zip解压,抽取编译好的.9.png图片,最后删除生成的临时文件。

程序源码如下:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import javax.swing.filechooser.FileSystemView;


public class Compile {

	private static String ninepngPath = "";
	private static String command;
	private static String deskTop = FileSystemView.getFileSystemView().getHomeDirectory().getAbsolutePath();
	private static File tempFile = new File(deskTop + "\\temp");//拷贝成功后删除
	private static File compiledFile = new File(deskTop + "\\compiled");//拷贝成功后删除
	
	public static void main(String[] args) {
		if(!AccessAapt()) {
			System.out.println("不能访问aapt命令!");
			return;
		}
		if(args.length == 0){
			
		}else{
			ninepngPath = args[0];
		}
		File manifest = new File("AndroidManifest.xml");
		File android = new File("android.jar");
		File resource = new File("res");
		File ninepngFile = new File(ninepngPath);
		
		try{
			if(ninepngPath.trim().length() == 0 || !ninepngFile.exists()){
				System.out.println("您输入的参数有错误!");
			}else{
				//将.9.png文件复制到res/下
				copyFile(ninepngFile,resource.getAbsolutePath() + "\\drawable\\" + ninepngFile.getName());
				command = "aapt";
				command += " package";
				command += " -M " + manifest.getAbsolutePath();
				command += " -S " + resource.getAbsolutePath();
				command += " -I " + android.getAbsolutePath();
				command += " -F " + deskTop + "\\temp";
			}
			Runtime.getRuntime().exec(command);
			Thread.sleep(3000);
			if(tempFile.exists()){
				unZip(tempFile.getAbsolutePath(),compiledFile.getAbsolutePath());
				File srcFile = new File(compiledFile.getAbsolutePath() + "\\res\\drawable\\" + ninepngFile.getName()); 
				copyFile(srcFile,deskTop + "\\" + ninepngFile.getName());
			}else{
				System.out.println("没有获取到zip文件");
			}
		}catch(Exception e){
			System.out.println("命令执行错误!");
			e.printStackTrace();
		}
		System.out.println("文件输出到桌面!");
		//删除临时文件
        deleteTempFile(tempFile);
        //Runtime.getRuntime().exec("");
        deleteTempFile(compiledFile);
	}

   //解压zip文件,只需要抽取我们想要的.9.png文件即可 private static void unZip(String zipfile, String destDir) { destDir = destDir.endsWith( "\\" ) ? destDir : destDir + "\\" ; //System.out.println(destDir); byte b[] = new byte [1024]; int length; ZipFile zipFile; try { zipFile = new ZipFile( new File(zipfile)); Enumeration enumeration = zipFile.entries(); ZipEntry zipEntry = null ; while (enumeration.hasMoreElements()) { zipEntry = (ZipEntry) enumeration.nextElement(); if(!zipEntry.getName().endsWith("png")){ continue; } File loadFile = new File(destDir + zipEntry.getName()); //System.out.println(":"+loadFile.getAbsolutePath()); if (zipEntry.isDirectory()) { // 这段都可以不要,因为每次都貌似从最底层开始遍历的 loadFile.mkdirs(); } else { if (!loadFile.getParentFile().exists()) loadFile.getParentFile().mkdirs(); OutputStream outputStream = new FileOutputStream(loadFile); InputStream inputStream = zipFile.getInputStream(zipEntry); while ((length = inputStream.read(b)) > 0) outputStream.write(b, 0, length); inputStream.close(); outputStream.close(); } } zipFile.close(); System.out.println( "文件解压成功!" ); } catch (IOException e) { e.printStackTrace(); } } //测试系统中是否可以访问aapt.ext文件,注意配置好环境变量 private static boolean AccessAapt(){ Map<String,String> envs = System.getenv(); Iterator<Map.Entry<String,String>> iter = envs.entrySet().iterator(); while(iter.hasNext()){ Map.Entry<String,String> entry = iter.next(); String value = entry.getValue(); String[] values = value.split(";"); for(int i = 0; i < values.length; i++){ String str = values[i]; File f = new File(str); if(f.isDirectory()){ String[] fileNames = f.list(); for(int j = 0; j < fileNames.length; j++){ if(fileNames[j].trim().equals("aapt.exe")){ return true; } } } } } return false; } private static boolean copyFile(File srcFile,String descPath){ try{ FileInputStream fis = new FileInputStream(srcFile); File desc = new File(descPath); if(!desc.exists()){ desc.createNewFile(); } FileOutputStream fos = new FileOutputStream(desc); byte[] buffer = new byte[1024]; int length = 0; while((length = fis.read(buffer)) != -1){ fos.write(buffer, 0, length); } fos.flush(); fos.close(); fis.close(); fos = null; fis = null; System.out.println("拷贝成功~!"); //srcFile.delete(); return true; }catch(Exception e){ e.printStackTrace(); } return false; } private static void deleteTempFile(File file){ if(!file.canWrite()) try { Thread.sleep(2000); System.out.println("等待两秒"); } catch (InterruptedException e1) { e1.printStackTrace(); } if(!file.exists()){ System.out.println("文件已经不存在了!"); }else{ if(file.isFile()){ //file.delete(); try { Runtime.getRuntime().exec("cmd /c del /q " + file.getAbsolutePath()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else{ try { Runtime.getRuntime().exec("cmd /c rd /s /q " + file.getAbsolutePath()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } System.out.println("临时文件删除成功!"); } }

此外,需要注意的是,为了让aapt.ext正常工作,需要手动构造它的执行参数,由于aapt工具需要加载android.jar和AndroidManifest.xml,因此可以考虑把他们放在程序包中,下边是上边程序的目录结构:

原文地址:https://www.cnblogs.com/sunzhenxing19860608/p/2085414.html