开发android应用的时候,界面有时会经常更改,导致很多无用的资源文件。如果不清理掉,可能会导致apk变大,性能降低。手动清理又很难判断哪些资源有用,哪些资源无用。所以,下面就开发了一个利用lint自动删除无用资源文件的工具。
一、基本原理
原理非常简单,首先,运行lint命令,生成分析文件。命令如下:
lint --check "UnusedResources" <projectPath> > result.txt
生成文件之后,就解析改文件,得到无用的资源,然后删除它们。
二、源码
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
public class RemoveUnuseFile {
private static final String RESULT_FILE_NAME = "result";
private String mProjectPath;
private String mCmd;
public static void main(String[] args) throws Exception {
RemoveUnuseFile ruf = new RemoveUnuseFile();
ruf.execute();
}
public void execute() throws Exception {
mProjectPath = getProjectPath();
mCmd = getCmdPath();
mCmd += " --check \"UnusedResources\" " + mProjectPath + " > "
+ RESULT_FILE_NAME;
int optimizedCount = 0;
int count = 0;
while (optimizedCount < 3) {
String result = getLintFile();
boolean isOptimezed1 = deleteUnuseFile(result);
boolean isOptimized2 = deleteUnuseRes(result);
if (isOptimezed1 || isOptimized2) {
optimizedCount = 0;
} else {
optimizedCount++;
}
System.out.println(++count
+ "==================================================");
}
}
private String getProjectPath() {
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.showDialog(new JLabel(), "选择工程");
File file = chooser.getSelectedFile();
System.out.print("" + file.getPath());
return file.getAbsolutePath();
}
private String getCmdPath() {
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
chooser.showDialog(new JLabel(), "选择lint命令");
File file = chooser.getSelectedFile();
System.out.print("" + file.getPath());
return file.getAbsolutePath();
}
private String getLintFile() throws IOException, InterruptedException {
File f = new File(RESULT_FILE_NAME);
if (!f.exists()) {
f.mkdir();
}
String fileName = System.currentTimeMillis() + ".txt";
Process p = Runtime.getRuntime().exec(mCmd + "//" + fileName);
p.waitFor();
/*
* while(!(new File(getResultFilePath(fileName))).exists()){ try {
* TimeUnit.MILLISECONDS.sleep(200); } catch (InterruptedException e) {
* // TODO Auto-generated catch block e.printStackTrace(); } }
*/
System.out.println("got result file:"
+ (new File(getResultFilePath(fileName))).exists());
return fileName;
}
private String getResultFilePath(String result) {
return RESULT_FILE_NAME + "\\" + result;
}
private boolean deleteUnuseRes(String result) throws IOException {
System.out.println("deleteUnuseRes:" + result);
BufferedReader reader = new BufferedReader(new FileReader(
getResultFilePath(result)));
File f2 = new File(getResultFilePath(result));
System.out.println("" + f2.length());
String line;
boolean isOptimized = false;
while ((line = reader.readLine()) != null) {
if (line.contains("UnusedResources")
&& line.startsWith("res\\values")) {
int end = line.indexOf(":");
if (end != -1) {
String file = line.substring(0, end);
String f = mProjectPath + file;
line = line.substring(end + 1);
end = line.indexOf(":");
int l = Integer.valueOf(line.substring(0, end));
FileVaulesProcess.getFileValueProcess(f).deleteLine(l);
isOptimized = true;
}
}
}
System.out.println("last line:" + line);
reader.close();
FileVaulesProcess.finish();
return isOptimized;
}
public boolean deleteUnuseFile(String result) throws IOException {
System.out.println("deleteUnuseFile:" + result);
BufferedReader reader = new BufferedReader(new FileReader(
getResultFilePath(result)));
String line;
boolean isOptimized = false;
while ((line = reader.readLine()) != null) {
if (line.contains("UnusedResources")
&& !line.contains("res\\values")
&& !line.contains("appcompat")) {
int end = line.indexOf(":");
if (end != -1) {
String file = line.substring(0, end);
String f = mProjectPath + file;
System.out.println(f);
new File(f).delete();
System.out.println("delete file:" + file);
isOptimized = true;
}
}
}
reader.close();
return isOptimized;
}
}
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Set;
public class FileVaulesProcess {
private String mFileName;
private BufferedReader mBufferReader;
private FileOutputStream mOutputSteam;
private OutputStreamWriter mOutputStreamWriter;
private int mLine = 1;
private File mOutFile;
private static HashMap<String,FileVaulesProcess> mHashMap = new HashMap<String,FileVaulesProcess>();
public static FileVaulesProcess getFileValueProcess(String fileName){
if(!mHashMap.containsKey(fileName)){
FileVaulesProcess fp = new FileVaulesProcess(fileName);
mHashMap.put(fileName, fp);
return fp;
}else{
return mHashMap.get(fileName);
}
}
private FileVaulesProcess(String file) {
System.out.println("file:" + file);
mFileName = file;
try {
init();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private void init() throws FileNotFoundException{
mBufferReader = new BufferedReader(new FileReader(mFileName));
mOutFile = new File(mFileName + ".bck");
mOutputSteam = new FileOutputStream(mOutFile);
mOutputStreamWriter = new OutputStreamWriter(mOutputSteam);
}
public void deleteLine(int line) throws IOException{
while(mLine < line){
String str = mBufferReader.readLine();
mOutputStreamWriter.write(str+"\n");
mLine++;
}
String str = mBufferReader.readLine();
mLine++;
System.out.println("delete line:" + line +":" + str);
}
public void finishDelete() throws IOException{
String str= null;
while((str = mBufferReader.readLine())!= null){
mOutputStreamWriter.write(str + "\n");
}
mOutputStreamWriter.close();
mOutputSteam.close();
mBufferReader.close();
File oldFile = new File(mFileName);
oldFile.delete();
oldFile = new File(mFileName);
mOutFile.renameTo(oldFile);
}
public static void finish() throws IOException {
Set<String> keySet = mHashMap.keySet();
for(String key:keySet){
mHashMap.get(key).finishDelete();
}
mHashMap.clear();
}
}