// 替换除包名路径下,所有R文件中的id信息 public static void updateALL_RIds(String unpackDir, String package, Dictionary <String, List <xmlNode> > gemeDicSrc, Dictionary <String, List <xmlNode> > DicSrc, Dictionary <String, List <xmlNode> > DicTar, Cmd.Callback call, bool R_Process_Game = false) { String packagePath = unpackDir + "\\smali\\" + package.Trim('.').Replace('.', '\\'); List <String> R_path = getR_smaliPath(unpackDir); int i = 0; foreach (String R_smaliDir in R_path) { if (!R_smaliDir.Equals(packagePath)) // 非包名路径下的R文件所在路径 { //string relative = ApkCombine.relativePath(R_smaliDir, unpackDir); //if (relative.StartsWith("smali\\android\\")) continue; //else if (relative.StartsWith("smali\\com\\helpshift")) continue; //string ortherR = ApkCombine.relativePath(R_smaliDir, unpackDir); //if (ortherR.Contains(@"\android\")) continue; // 忽略android路径下的R文件修改 //String relaPath = ApkCombine.relativePath(R_smaliDir, unpackDir); //if (relaPath.Equals(@"smali\com\google\android\gms\common")) // relaPath = relaPath + ""; if (call != null) { call("【I】- 7." + ++i + " 修改路径" + ApkCombine.relativePath(R_smaliDir, unpackDir) + "下所有R文件id信息"); } update_RDirIds(R_smaliDir, DicSrc, DicTar, call); if (R_Process_Game) { update_RDirIds(R_smaliDir, gemeDicSrc, DicTar, call); // 修改游戏包中对应的资源id } } } }
/// <summary> /// 添加渠道附加资源 /// </summary> private static void addChannelAttachs(ToolSetting toolSet, Cmd.Callback call, String dirSource, String channelAttachDir, String Set_channelId) { // 获取渠道附加目录资源路径 String channelDir = toolSet.chargeAPK_dir + "\\" + Set_channelId; //String channelAttachDir = channelDir + "\\附加资源"; String channelAttachDir2 = channelDir + channelAttachDir; // 复制渠道附加目录中的文件 if (Directory.Exists(channelAttachDir2) && !ApkCombine.isEmptyDirectorty(channelAttachDir2)) { bool isEmptyDir = ApkCombine.isEmptyDirectorty(channelAttachDir); if (!isEmptyDir && call != null) { call("【I】"); } if (!isEmptyDir && call != null) { call("【I】复制," + channelAttachDir); } ApkCombine.CopyFolderTo(channelAttachDir2, dirSource, true, call); if (!isEmptyDir && call != null) { call("【I】复制," + channelAttachDir + "完成"); } } }
/// <summary> /// 添加游戏附加资源 /// </summary> private static void addGameAttachs(ToolSetting toolSet, Cmd.Callback call, String dirTarget, String gameAttachDir, String Set_gameId, String Set_channelId, String tittle = "") { // 获取选中的游戏包所在的目录的附加资源 //toolSet.gameAPK_dir + "\\" + Settings.gameId + "\\" String selectGameDir = toolSet.gameAPK_dir + "\\" + Set_gameId; //String selectVersionDir = Form4.SelectVersionDir; //String[] attachDirs = { selectGameDir + "\\游戏Icon或Logo", selectVersionDir + "\\附加资源" }; //foreach (String gameAttachDir0 in attachDirs) { String gameAttachDir2 = selectGameDir + gameAttachDir; // 生成附加资源路径 // 复制游戏附加目录中的文件 List <String> list_channel = new List <string>(); list_channel.Add("所有渠道"); list_channel.Add(Set_channelId); bool isEmptyDir = ApkCombine.isEmptyDirectorty(gameAttachDir2); if (!isEmptyDir && call != null) { call("【I】"); } if (!isEmptyDir && call != null) { call("【I】复制," + gameAttachDir + (tittle.Equals("") ? "" : ("到" + tittle))); } foreach (String channelId in list_channel) { String Dir = gameAttachDir2 + "\\" + channelId; isEmptyDir = ApkCombine.isEmptyDirectorty(Dir); // 拷贝游戏附加资源目录 if (channelId != null && !channelId.Equals("") && Directory.Exists(Dir) && !ApkCombine.isEmptyDirectorty(Dir)) { if (!isEmptyDir && call != null) { call("【I】复制," + gameAttachDir + "\\" + channelId); } ApkCombine.CopyFolderTo(Dir, dirTarget, true, call); if (!isEmptyDir && call != null) { call("【I】复制," + gameAttachDir + "\\" + channelId + " 完成"); } } } } // 复制游戏Icon、Logo if (gameAttachDir.Equals("\\游戏Icon或Logo") && StartParam.AutoRun && Form4.channelIconDir.ContainsKey(Set_channelId)) { String ICONDIR = Form4.channelIconDir[Set_channelId]; if (!ICONDIR.Equals("") && Directory.Exists(ICONDIR)) { ApkCombine.CopyFolderTo(ICONDIR, dirTarget + @"\res\drawable", true, call); } } }
static bool showCopyInfo = false; // 是否显示复制信息 /// <summary> /// 对两个apk解包后的文件进行混合,复制目录dirSource下的文件到dirDest中 /// </summary> public static void Combine(String dirSource, String dirDest, Cmd.Callback call) { if (Apktool.isApkDir(dirDest) && Apktool.isApkDir(dirSource)) { Cmd.Callback tmp = Settings.call; // 记录call Settings.call = call; Settings setting = Settings.Load(dirSource, dirDest); //setting.GetPackageName_GAMEPRE_CHANNEL(dirSource, dirDest); // 更新渠道参数信息 // 若设置为使用所有渠道通用基础配置,则拷贝混合基础配置信息到游戏包 if (setting.useAllChannelCommon) { ToolSetting toolSet = ToolSetting.Instance(); // 载入配置信息 //String AllChannelCommon = toolSet.chargeAPK_dir + "\\所有渠道\\附加资源"; // 获取所有渠道配置目录 //ToolSetting.confirmDir(AllChannelCommon); //// 混合所有渠道公用配置 //if (!ApkCombine.isEmptyDirectorty(AllChannelCommon)) //{ // if (call != null) call("【L】拷贝所有渠道附加资源:"); // Combine(AllChannelCommon, dirDest, call); // if (call != null) call("【I】拷贝所有渠道附加资源完成!"); //} String commonDir = toolSet.chargeAPK_dir + "\\所有渠道"; // 获取所有渠道配置目录 Dictionary <String, String> apk_dirs = Form3.getApk_FileOrDir(commonDir); // 获取目录下的apk文件或解压目录 if (apk_dirs.Count > 0) { String apk_dir = apk_dirs.Values.ToArray <String>()[0]; if (call != null) { call("【I】"); } if (call != null) { call("【I】---------------------------------"); } if (call != null) { call("【L】混合,所有渠道,通用基础包资源:\r\n" + apk_dir); } // 所有渠道通用apk解包 String AllChannelCommon = Form2.apkUnpack(apk_dir, call); // 获取所有渠道配置目录 if (AllChannelCommon.Contains("【E】")) { return; } // 混合所有渠道公用配置 if (!ApkCombine.isEmptyDirectorty(AllChannelCommon)) { if (call != null) { call("【L】拷贝所有渠道附加资源:"); } Combine(AllChannelCommon, dirDest, call); if (call != null) { call("【I】拷贝所有渠道附加资源完成!"); } } if (call != null) { call("【I】---------------------------------\r\n"); } // 拷贝所有渠道配置中的【其他渠道参数替换文件列表】 string str = FileProcess.fileToString(AllChannelCommon + ".txt"); Settings allChannel = Settings.Parse(str); setting.addSettings(allChannel, 5); setting.ReplaceLateParams(); // 替换设置的关键字信息为在线获取的参数 // 清除所有渠道通用配置缓存 Apktool.DeletDir(AllChannelCommon); Apktool.DeletFile(AllChannelCommon + ".txt"); // 清除配置文件信息 } } if (call != null) { call("【L】1、拷贝文件前,清除游戏包中指定的文件:"); } RemoveDirFile(dirDest, call, setting); if (call != null) { call("【L】2、复制所有文件,并忽略忽略列表中的文件和目录:"); } CopyFolderTo_Ignore(dirSource, dirDest, call, setting); // 复制所有文件,并忽略忽略列表中的文件和目录 if (call != null) { call("【L】3、附加拷贝,附加列表中的文件和目录:"); } CopyFolderTo_addCopyDir(dirSource, dirDest, call, setting); // 附加拷贝,附加列表中的文件和目录 RemoveDirFile(dirDest, call, setting); // 清除复制时,原有目录 String ManifestPath = dirDest + "\\" + "AndroidManifest.xml"; if (File.Exists(ManifestPath)) { if (call != null) { call("【L】4、修改Manifest.xml文件:"); } Manifest manifest = new Manifest(ManifestPath); // 创建Manifest对象 Settings.gameLabel = manifest.label; // 获取游戏显示名称,如: @string/app_name manifest.runCMD(setting.ManifestCMD); // 执行manifest修改逻辑 manifest.save(); // 保存manifest Settings.gameIcon = manifest.icon; // 获取游戏图标名称,如: @drawable/icon } setting.ReplaceFiles_ChannelParams(dirDest); // 替换其他文件中配置的渠道参数变量 setting.ProcessIcon(dirDest); // 处理icon Settings.call = tmp; //还原call } }
//从dirTarget目录下获取res资源,重新编译生成public.xml private static bool UpdatePublicXML(String dirTarget, Cmd.Callback call) { ToolSetting settting = ToolSetting.Instance(); // 载入设置信息 if (call != null) { call("【I】- 2.解包Empty.apk"); } String emptyApk = DependentFiles.curDir() + "\\tools\\Empty.apk"; // 空项目资源路径 if (emptyApk.Contains("\\\\")) { emptyApk = emptyApk.Replace("\\\\", "\\"); } String emptyDir = Apktool.unPackage(emptyApk, null, false); // 解包空apk if (emptyDir.Contains("【E】") && call != null) { call("【E】 解包Empty.apk异常"); return(false); } if (call != null) { call("【I】- 复制游戏res资源"); } String Res = emptyDir + "\\res"; ApkCombine.CopyFolderTo(dirTarget + "\\res", Res, true); // 复制Target目录到res目录,到空工程解包路径下 Program.Delay(3000); // 部分机器复制文件,存在异步延时,确保文件复制完成 if (call != null) { call("【I】- 3.使用新的res资源,生成新的Empty.apk"); } String apkFile = Apktool.package(emptyDir, null); // 使用apktool进行打包 if (apkFile.Contains("【E】") && call != null) { call("【E】 打包Empty.apk异常"); call("【E】 异常信息:" + apkFile); return(false); } if (call != null) { call("【I】- 4.解包Empty.apk"); } string unpackDir = Apktool.unPackage(apkFile, null, false); // 使用apktool进行apk的解包,生成新的public.xml if (unpackDir.Contains("【E】") || unpackDir.Trim().Equals("")) { if (call != null) { call("【E】 解包Empty.apk异常"); } return(false); } if (call != null) { call("【I】- 5.复制生成的public.xml文件,到游戏res目录中"); } String relativePath = @"\res\values\public.xml"; File.Copy(unpackDir + relativePath, dirTarget + relativePath, true); // 替换原有public.xml relativePath = @"\res\drawable\empty_ic_launcher.png"; File.Copy(unpackDir + relativePath, dirTarget + relativePath, true); relativePath = @"\res\layout\empty_activity_main.xml"; File.Copy(unpackDir + relativePath, dirTarget + relativePath, true); if (call != null) { call("【I】- 清除Empty.apk相关缓存资源..."); } // 清除缓存资源 Directory.Delete(emptyDir, true); // 删除空项目解包文件 File.Delete(apkFile); // 删除生成的临时文件 Directory.Delete(unpackDir, true); // 删除空工程解包目录 return(true); }
// ------------------------------------------- //unknownFiles: //com/tencent/mm/sdk/platformtools/rep5402863540997075488.tmp: '8' //com/fxlib/util/version.txt: '8' /// <summary> /// 修改apktool.yml中的Unknown文件列表 /// </summary> public static void appendunknown(String dirTarget, Cmd.Callback call) { // 获取文件内容 String apktoolYmlPath = dirTarget + "\\apktool.yml"; String apktoolYml = FileProcess.fileToString(apktoolYmlPath); String apktoolYml0 = apktoolYml; // 获取文件原有unknown部分 String unknownFiles = ""; if (apktoolYml.Contains("unknownFiles")) { unknownFiles = apktoolYml.Substring(apktoolYml.IndexOf("unknownFiles")); } String unknown = dirTarget + "\\unknown"; String[] files = getAllFiles(unknown).Split(';'); if (files != null && files.Length > 0) { if (call != null) { call("【I】- 8.修改apktool.yml中的Unknown文件列表:"); } // 生成新的unknown String appendUnknowns = ""; foreach (String file in files) { String relativeName = ApkCombine.relativePath(file, unknown).Replace('\\', '/'); appendUnknowns += "\n " + relativeName + ": '8'"; if (call != null) { call("【I】Unknown添加:" + relativeName); } } if (!appendUnknowns.Equals("")) { appendUnknowns = "unknownFiles:" + appendUnknowns + "\n"; } // 替换为新的unknown文件列表信息 if (unknownFiles.Equals("")) { apktoolYml = apktoolYml + appendUnknowns; } else { apktoolYml = apktoolYml.Replace(unknownFiles, appendUnknowns); } } // 文件内容变动,则保存为新的apktoolYml if (!apktoolYml.Equals(apktoolYml0)) { FileProcess.SaveProcess(apktoolYml, apktoolYmlPath); if (call != null) { call("【I】对apktool.yml的修改已保存!\r\n"); } } }
/// <summary> /// 执行apk解包文件混合逻辑 /// </summary> public static void CombineApk(String dirSource, String dirTarget, String signFileName, Cmd.Callback call, bool deletTXT = true) { if (call != null) { call("【I】"); } ToolSetting toolSet = ToolSetting.Instance(); // 载入配置信息 String Set_gameId = Settings.gameId, Set_channelId = Settings.channelId; // 获取游戏id、渠道id //-------------------------1 // 游戏apk解包 dirTarget = apkUnpack(dirTarget, call /*, true*/); // 解包游戏包并删除res\values\public.xml文件 if (dirTarget.Contains("【E】")) { return; } //-------------------------2 // 渠道apk解包 dirSource = apkUnpack(dirSource, call); //ReplaceValues.ReplaceFileContent(dirSource, "0x7f0", "0x7ff"); //if (call != null) call("【I】替换渠道解包文件下,所有0x7f0 为 0x7ff"); if (dirSource.Contains("【E】")) { return; } // 添加游戏Icon或Logo到游戏解包文件 addGameAttachs(toolSet, call, dirTarget, "\\游戏Icon或Logo", Set_gameId, Set_channelId, "游戏解包目录"); // 添加游戏Icon或Logo到渠道解包文件 addGameAttachs(toolSet, call, dirSource, "\\游戏Icon或Logo", Set_gameId, Set_channelId, "渠道解包目录"); //-------------------------3 if (call != null) { call("【I】"); } if (call != null) { call("【I】执行apk混合逻辑..."); } if (call != null) { call("【I】添加" + dirSource + "\r\n到" + dirTarget + "中"); } // 进行apk文件的混合 ApkCombine.Combine(dirSource, dirTarget, call); if (call != null) { call("【I】apk混合完成!\r\n"); } //-------------------------4 // 添加渠道附加资源 addChannelAttachs(toolSet, call, dirTarget, "\\附加资源", Set_channelId); // 添加游戏包附加资源 addGameAttachs(toolSet, call, dirTarget, "\\附加资源", Set_gameId, Set_channelId); //-------------------------5 // 执行R文件修改逻辑 if (toolSet.R_Process) { bool R_result = R_process.Start(dirTarget, dirSource, call, toolSet.apktool_yml_Process, toolSet.R_Process_Game); if (!R_result) { return; } } //String path = R_process.create_publicXML(dirTarget, call); //String package = Settings.channel_param["package"]; // 获取包名信息 //R_process.rebuidR_smali(path, dirTarget + "\\smali", package, call); // 重新生成包名路径下的R文件 //File.Copy(path, dirTarget + @"\res\values\public.xml"); // 替换原有public.xml //-------------------------6 // apk重新打包 String result = apkPackage(dirTarget, signFileName, call); if (result.Contains("【E】")) { return; } // 打包完成后清除缓存中的解包文件 if (call != null) { call("【I】清除缓存目录," + dirSource); } Apktool.DeletDir(dirSource); if (call != null) { call("【I】清除缓存目录," + dirTarget); } Apktool.DeletDir(dirTarget); if (deletTXT) { if (call != null) { call("【I】清除缓存文件," + dirSource + ".txt"); } Apktool.DeletFile(dirSource + ".txt"); } }