.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图片,最后删除生成的临时文件。
程序源码如下:
此外,需要注意的是,为了让aapt.ext正常工作,需要手动构造它的执行参数,由于aapt工具需要加载android.jar和AndroidManifest.xml
程序的设计很简单,调用系统的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