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 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(); } }