385 lines
15 KiB
Java
385 lines
15 KiB
Java
package com.qy.utils;
|
||
|
||
import com.qy.Interfaces.SmaliApkToolsPath;
|
||
import com.qy.ui.EditToDalog;
|
||
import org.json.JSONArray;
|
||
import org.json.JSONObject;
|
||
|
||
import java.io.*;
|
||
import java.util.*;
|
||
import java.util.regex.Matcher;
|
||
import java.util.regex.Pattern;
|
||
|
||
public class CsjTools {
|
||
private static String csj_res = "D:\\IdeaProjects\\android_sdk_tools\\demo_2.8.0.2\\res\\values";
|
||
private static String apk_res = "D:\\IdeaProjects\\android_sdk_tools\\app-release\\res\\values";
|
||
private static String apk_Path = "D:\\IdeaProjects\\android_sdk_tools\\app-release";
|
||
private static String csj_Path = "D:\\IdeaProjects\\android_sdk_tools\\demo_2.8.0.2";
|
||
private List<String> r_list;
|
||
private String packageName = null;
|
||
|
||
public CsjTools() {
|
||
}
|
||
|
||
public CsjTools(String apkFile, String csjFile, String packageName, String version, SmaliApkToolsPath toolsPath) {
|
||
setUserPackageName(false);
|
||
this.packageName = packageName;
|
||
build(csjFile, apkFile, new SmaliApkToolsPath() {
|
||
@Override
|
||
public void smaliPath(String path) {
|
||
System.out.println(path);
|
||
if (path.startsWith("已出包")) {
|
||
out(path.replace("已出包", ""),
|
||
new File("csj").getAbsolutePath() + File.separator + "csc",
|
||
Integer.parseInt(version));
|
||
toolsPath.smaliPath(new File("csj").getAbsolutePath() + File.separator + "csc");
|
||
}
|
||
|
||
}
|
||
});
|
||
}
|
||
|
||
public String loadXml(String path) {
|
||
File file = new File(path);
|
||
String xml = null;
|
||
try {
|
||
BufferedReader reader = new BufferedReader(new FileReader(file));
|
||
String tmp;
|
||
while ((tmp = reader.readLine()) != null) {
|
||
if (xml == null) {
|
||
xml = tmp + "\n";
|
||
} else {
|
||
xml += tmp + "\n";
|
||
}
|
||
}
|
||
reader.close();
|
||
} catch (Exception e) {
|
||
e.printStackTrace();
|
||
}
|
||
return xml;
|
||
}
|
||
|
||
|
||
public long getId(String publicXml) {
|
||
long maxId = 0;
|
||
for (String xml : publicXml.split("\n")) {
|
||
String id = getXMLValue("id", xml.trim());
|
||
if (id != null) {
|
||
id = id.substring(2, 6);
|
||
if (maxId < Long.parseLong(id, 16)) {
|
||
maxId = Long.parseLong(id, 16);
|
||
}
|
||
}
|
||
|
||
}
|
||
return maxId;
|
||
|
||
}
|
||
|
||
public String getXMLValue(String name, String message) {
|
||
Pattern p = Pattern.compile(name + "=\"([^\"]+)\"");
|
||
Matcher m = p.matcher(message);
|
||
if (m.find()) {
|
||
String tmp = message.substring(m.start(), m.end()).split("=")[1];
|
||
return tmp.substring(1, tmp.length() - 1);
|
||
}
|
||
return null;
|
||
}
|
||
|
||
private boolean isAppPackageName = false;
|
||
|
||
public void setUserPackageName(boolean isAppPackageName) {
|
||
this.isAppPackageName = isAppPackageName;
|
||
}
|
||
|
||
private String getPackageName() {
|
||
try {
|
||
if (isAppPackageName) {
|
||
File apkManifest = new File(apk_Path + File.separator + "AndroidManifest.xml");
|
||
BufferedReader reader = new BufferedReader(new FileReader(apkManifest));
|
||
String tmp = reader.readLine();
|
||
reader.close();
|
||
return getXMLValue("package", tmp);
|
||
} else {
|
||
if (packageName == null) {
|
||
return Tools.loadConfig(new File("config.cfg")).getString("csjPackageName");
|
||
} else {
|
||
return packageName;
|
||
}
|
||
}
|
||
} catch (Exception e) {
|
||
e.printStackTrace();
|
||
}
|
||
return null;
|
||
}
|
||
|
||
private void outManifest() {
|
||
try {
|
||
File apkManifest = new File(apk_Path + File.separator + "AndroidManifest.xml");
|
||
File demoManifest = new File(csj_Path + File.separator + "AndroidManifest.xml");
|
||
BufferedReader reader = new BufferedReader(new FileReader(apkManifest));
|
||
String tmp = reader.readLine();
|
||
reader.close();
|
||
String apkPackage = getXMLValue("package", tmp);
|
||
System.out.println(apkPackage);
|
||
_log.smaliPath("获取到APK包名:" + apkPackage);
|
||
reader = new BufferedReader(new FileReader(demoManifest));
|
||
tmp = reader.readLine();
|
||
String manifest = tmp.replace(getXMLValue("package", tmp), apkPackage) + "\n";
|
||
while ((tmp = reader.readLine()) != null) {
|
||
manifest += tmp + "\n";
|
||
}
|
||
FileWriter writer = new FileWriter(demoManifest);
|
||
writer.write(manifest);
|
||
writer.flush();
|
||
writer.close();
|
||
reader.close();
|
||
|
||
} catch (Exception e) {
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
|
||
public void out(String srcFile, String encryptFile, int version) {
|
||
EncryptJar encryptJar = new EncryptJar();
|
||
encryptJar.encrypt(new File(srcFile), encryptFile, 13, version);
|
||
|
||
}
|
||
|
||
|
||
private void commandFile() {
|
||
JSONObject config = Tools.loadConfig(new File("config.cfg"));
|
||
if (config != null && config.getJSONObject("csjConfig") != null) {
|
||
JSONObject _config = config.getJSONObject("csjConfig");
|
||
JSONObject fileConfig = _config.getJSONObject("file");
|
||
JSONArray data = fileConfig.getJSONArray("data");
|
||
for (Object _item : data) {
|
||
JSONObject item = (JSONObject) _item;
|
||
String path = item.getString("name");
|
||
if (item.getString("command").equals("delete")) {
|
||
path = path.replace("${demoRoot}", csj_Path)
|
||
.replace("${apkRoot}", apk_Path)
|
||
.replace("/", File.separator);
|
||
File file = new File(path.replace("*", ""));
|
||
if (path.endsWith("*")) {
|
||
Tools.deleteFiles(file.getAbsolutePath());
|
||
} else {
|
||
file.delete();
|
||
}
|
||
}
|
||
}
|
||
_config = config.getJSONObject("csjConfig").getJSONObject("xml");
|
||
if (_config != null) {
|
||
data = _config.getJSONArray("data");
|
||
for (Object _item : data) {
|
||
JSONObject item = (JSONObject) _item;
|
||
if (item.getString("command").equals("remove")) {
|
||
String path = item.getString("name")
|
||
.replace("${demoRoot}", csj_Path)
|
||
.replace("${apkRoot}", apk_Path)
|
||
.replace("/", File.separator);
|
||
File file = new File(path);
|
||
commandXml(file, item);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void commandXml(File file, JSONObject item) {
|
||
try {
|
||
String fileXml = loadXml(file.getAbsolutePath());
|
||
String newXml = "";
|
||
boolean remove = false;
|
||
for (String xml : fileXml.split("\n")) {
|
||
for (Object data : item.getJSONArray("data")) {
|
||
JSONObject _item = (JSONObject) data;
|
||
String value = getXMLValue(_item.getString("title"), xml.trim());
|
||
if (value != null && value.equals(_item.getString("value"))) {
|
||
remove = true;
|
||
}
|
||
}
|
||
if (remove) {
|
||
remove = false;
|
||
continue;
|
||
}
|
||
newXml += xml + "\n";
|
||
|
||
}
|
||
FileWriter writer = new FileWriter(file);
|
||
writer.write(newXml);
|
||
writer.flush();
|
||
writer.close();
|
||
} catch (Exception e) {
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
|
||
private void start() {
|
||
_log.smaliPath("开始制作资源包");
|
||
|
||
commandFile();
|
||
String apkXML = loadXml(apk_res + File.separator + "public.xml");
|
||
String demoXML = loadXml(csj_res + File.separator + "public.xml");
|
||
long maxId = getId(apkXML);
|
||
int index = 0;
|
||
String message = "";
|
||
String oldType = "";
|
||
for (String xml : demoXML.split("\n")) {
|
||
String type = getXMLValue("type", xml.trim());
|
||
// String name = getXMLValue("name", xml.trim());
|
||
String oldId = getXMLValue("id", xml.trim());
|
||
if (type != null && !type.equals(oldType)) {
|
||
oldType = type;
|
||
maxId++;
|
||
index = 0;
|
||
}
|
||
if (type != null) {
|
||
String nextId = "0x" + Long.toHexString(maxId + 1) + String.format("%.3f", (index++) / 1000f).replace(".", "");
|
||
xml = xml.replace(oldId, nextId);
|
||
}
|
||
message += xml + "\n";
|
||
}
|
||
try {
|
||
FileWriter writer = new FileWriter(new File(csj_res + File.separator + "public.xml"));
|
||
writer.write(message);
|
||
writer.flush();
|
||
writer.close();
|
||
} catch (IOException e) {
|
||
e.printStackTrace();
|
||
}
|
||
outManifest();
|
||
File csjRes = new File("csj" + File.separator + "csc.apk");
|
||
if (!new File("csj").exists()) {
|
||
new File("csj").mkdirs();
|
||
}
|
||
SmaliUtils utils = new SmaliUtils();
|
||
_log.smaliPath("资源包制作完成,开始打包为apk");
|
||
utils.bale(csj_Path, csjRes.getAbsolutePath(), new SmaliApkToolsPath() {
|
||
@Override
|
||
public void smaliPath(String path) {
|
||
_log.smaliPath("已出包" + csjRes.getAbsolutePath());
|
||
_log.smaliPath("耗时:" + (System.currentTimeMillis() - time) / 1000 + " 秒");
|
||
System.gc();
|
||
|
||
}
|
||
});
|
||
}
|
||
|
||
private long time;
|
||
private boolean unPackageCSJ = false;
|
||
private SmaliApkToolsPath _log;
|
||
|
||
public void build(String csjPath, String apkPath, SmaliApkToolsPath log) {
|
||
time = System.currentTimeMillis();
|
||
_log = log;
|
||
unPackageCSJ = false;
|
||
File csjFile = new File(csjPath);
|
||
//由于改成动态SDK,所以每个应用都要单独打包
|
||
/*if (new File(csjFile.getName().replace(".apk", "")).exists()) {
|
||
System.out.println(">?>>" + new File(csjFile.getName().replace(".apk", "")).getAbsolutePath());
|
||
unPackageCSJ = true;
|
||
csj_Path = new File(csjFile.getName().replace(".apk", "")).getAbsolutePath();
|
||
csj_res = csj_Path + File.separator + "res" + File.separator + "values";
|
||
}*/
|
||
SmaliUtils utils = new SmaliUtils();
|
||
Tools.deleteFiles(new File("").getAbsolutePath() + File.separator + new File(csjPath).getName().replace(".apk", File.separator));
|
||
Tools.deleteFiles(new File("").getAbsolutePath() + File.separator + new File(apkPath).getName().replace(".apk", File.separator));
|
||
|
||
|
||
new Thread(new Runnable() {
|
||
@Override
|
||
public void run() {
|
||
_log.smaliPath("开始反编译目标APK");
|
||
|
||
|
||
utils.unPack(apkPath, new SmaliApkToolsPath() {
|
||
@Override
|
||
public void smaliPath(String path) {
|
||
log.smaliPath("目标APK反编译完成:" + path);
|
||
apkUnPackage = true;
|
||
System.out.println(path);
|
||
apk_Path = path;
|
||
apk_res = apk_Path + File.separator + "res" + File.separator + "values";
|
||
runStart();
|
||
utils.clear();
|
||
}
|
||
});
|
||
|
||
if (unPackageCSJ) {
|
||
_log.smaliPath("穿山甲demo已存在,不再反编译");
|
||
csjManifest = true;
|
||
runStart();
|
||
} else {
|
||
_log.smaliPath("开始反编译穿山甲Demo");
|
||
utils.unPack(csjPath, new SmaliApkToolsPath() {
|
||
@Override
|
||
public void smaliPath(String path) {
|
||
_log.smaliPath("穿山甲Demo反编译完成:" + path);
|
||
System.out.println(path);
|
||
csj_Path = path;
|
||
csj_res = csj_Path + File.separator + "res" + File.separator + "values";
|
||
_log.smaliPath("开始修改穿山甲");
|
||
utils.clear();
|
||
new Thread(new Runnable() {
|
||
@Override
|
||
public void run() {
|
||
new AutoRandomAdSDK().startNotUnPackage(path, getPackageName(), new SmaliApkToolsPath() {
|
||
@Override
|
||
public void smaliPath(String path) {
|
||
_log.smaliPath("穿山甲修改完成");
|
||
System.out.println("-------" + path);
|
||
csjManifest = true;
|
||
runStart();
|
||
}
|
||
});
|
||
}
|
||
}).start();
|
||
}
|
||
|
||
});
|
||
}
|
||
}
|
||
}).start();
|
||
|
||
}
|
||
|
||
boolean csjManifest = false;
|
||
boolean apkUnPackage = false;
|
||
|
||
private void runStart() {
|
||
if (apkUnPackage && csjManifest) {
|
||
start();
|
||
}
|
||
}
|
||
|
||
//还有最后一个问题,穿山甲的Activity没改
|
||
public static void main(String[] args) {
|
||
CsjTools tools = new CsjTools();
|
||
tools.build("D:\\IdeaProjects\\android_sdk_tools\\demo_2.8.0.2.apk",
|
||
"D:\\IdeaProjects\\android_sdk_tools\\app-release.apk",
|
||
new SmaliApkToolsPath() {
|
||
@Override
|
||
public void smaliPath(String log) {
|
||
System.out.println(log);
|
||
if (log.startsWith("已出包")) {
|
||
System.out.println("打包完成");
|
||
new EditToDalog("成功", "打包完成,请输入版本号", "5600", new SmaliApkToolsPath() {
|
||
@Override
|
||
public void smaliPath(String path) {
|
||
System.out.println(">>" + path);
|
||
tools.out(log.replace("已出包", ""),
|
||
new File("csj").getAbsolutePath() + File.separator + "csc",
|
||
Integer.parseInt(path));
|
||
}
|
||
});
|
||
}
|
||
}
|
||
});
|
||
|
||
// tools.outManifest();
|
||
// tools.start();
|
||
|
||
}
|
||
}
|