/// <summary> /// 快速排序-比较方法(pxm.id_low比较) /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static int pxm_compare_id_low(public_xml_model a, public_xml_model b) { if (a.id_low > b.id_low) return 1; else if (a.id_low == b.id_low) return 0; else return -1; }
public virtual void MergeSmali(List<string> copy_folders, List<string> copy_files) { //合并R.smali(从新合并的public.xml中合并) do { if (!Directory.Exists(m_sdkinfo.in_res)) break; //寻找R.smali文件和对应的拓展文件 List<string> sdk_smalis = new List<string>(); string sdk_R = m_sdkinfo.in_smali + @"\" + m_sdkinfo.PrePackageName.Replace(".",@"\") + @"\R.smali"; if(!File.Exists(sdk_R)) throw new Exception("sdk has muiti R.smali"); string sdk_R_class = @"L" + Path.GetDirectoryName(sdk_R).Replace(m_sdkinfo.in_smali, "").Replace(@"\", @"/").TrimStart('/'); List<string> apk_smalis = new List<string>(); string dex_class_smali_folder = m_apkinfo.in_smali; string apk_R = string.Empty; utils.get_files_from_folder(m_apkinfo.in_smali, ref apk_smalis, "R.smali"); if (apk_smalis.Count == 0) { if (Directory.Exists(m_apkinfo.in_smali_classes2)) { utils.get_files_from_folder(m_apkinfo.in_smali_classes2, ref apk_smalis, "R.smali"); dex_class_smali_folder = m_apkinfo.in_smali_classes2; } } foreach (string key in apk_smalis) { string tempname = Path.GetDirectoryName(key).Replace(dex_class_smali_folder + @"\", "").Replace(@"\", "."); if (m_apkinfo.settings.MainActivity.IndexOf(tempname) != -1 || m_apkinfo.settings.PackageName == tempname || apk_smalis.Count == 1) { apk_R = key; break; } } if (apk_R != string.Empty) { utils.get_files_from_folder(Path.GetDirectoryName(apk_R), ref apk_smalis, "R$", "*.smali"); if (apk_smalis.Count > 0) { do { bool rm_flag = false; for (int m = 0; m < apk_smalis.Count; m++) { if (Path.GetFileName(apk_smalis[m]).Substring(0, 2) != "R$") { apk_smalis.RemoveAt(m); rm_flag = true; break; } } if (rm_flag == false) break; } while (true); } } else { throw new Exception("apk has muiti R.smali"); } string apk_R_class = @"L" + Path.GetDirectoryName(apk_R).Replace(dex_class_smali_folder, "").Replace(@"\", @"/").TrimStart('/'); //搜集sdk中R.smali和apk中R.smali中的type Encoding enc = null; enc = TxtFileEncoder.GetEncoding(sdk_R); List<string> sdk_R_lines = File.ReadAllText(sdk_R, enc).Replace("\r\n", "*").Split('*').ToList(); enc = TxtFileEncoder.GetEncoding(apk_R); List<string> apk_R_lines = File.ReadAllText(apk_R, enc).Replace("\r\n", "*").Split('*').ToList(); List<string> sdk_R_class_types = new List<string>(); List<string> apk_R_class_types = new List<string>(); string sdk_public = m_sdkinfo.in_res + @"\values\public.xml"; SortedDictionary<string, List<public_xml_model>> sdk_dict = new SortedDictionary<string, List<public_xml_model>>(); XmlDocument sdk_public_doc = new XmlDocument(); sdk_public_doc.Load(sdk_public); XmlNodeList sdk_nodes = sdk_public_doc.DocumentElement.ChildNodes; if (sdk_nodes.Count > 0) { foreach (XmlNode node in sdk_nodes) { public_xml_model pxm = new public_xml_model(); pxm.type = node.Attributes["type"].Value; pxm.name = node.Attributes["name"].Value; pxm.id = node.Attributes["id"].Value; pxm.id_high = Convert.ToInt32(pxm.id.Substring(2, 4), 16); pxm.id_low = Convert.ToInt32(pxm.id.Substring(6, 4), 16); if (!sdk_dict.ContainsKey(pxm.type)) sdk_dict.Add(pxm.type, new List<public_xml_model>()); sdk_dict[pxm.type].Add(pxm); } } foreach (string sdk_key in sdk_dict.Keys) { sdk_R_class_types.Add(sdk_key); } int insert_pos = -1; foreach (string apk_R_line in apk_R_lines) { if (apk_R_line.IndexOf(apk_R_class + @"/R$") != -1) { if (insert_pos == -1) insert_pos = apk_R_lines.IndexOf(apk_R_line); apk_R_class_types.Add(apk_R_line.Replace(" ", "").Replace(@";", "").Replace(@",", "").Replace(apk_R_class + @"/R$", "")); } } //向apk中R.smali添加新的type,并复制新的R$type.smali string insert_line = string.Empty; string copy_content = string.Empty; string copy_from_path = string.Empty; string copy_to_path = string.Empty; foreach (string sdk_type in sdk_R_class_types) { copy_from_path = Path.GetDirectoryName(sdk_R) + @"\R$" + sdk_type + @".smali"; copy_to_path = Path.GetDirectoryName(apk_R) + @"\R$" + sdk_type + @".smali"; if (!File.Exists(copy_to_path)) { File.Copy(copy_from_path, copy_to_path); enc = TxtFileEncoder.GetEncoding(copy_to_path); copy_content = File.ReadAllText(copy_to_path, enc); copy_content = copy_content.Replace(sdk_R_class, apk_R_class); File.WriteAllText(copy_to_path, copy_content, enc); } if (apk_R_class_types.Count == 0 || insert_pos == -1) break; if (apk_R_class_types.IndexOf(sdk_type) == -1) { insert_line = " " + apk_R_class + @"/R$" + sdk_type + @";,"; apk_R_lines.Insert(insert_pos, insert_line); } } string apk_R_new_content = string.Empty; for (int i = 0; i < apk_R_lines.Count; i++) { apk_R_new_content += apk_R_lines[i] + "\r\n"; } enc = TxtFileEncoder.GetEncoding(apk_R); File.WriteAllText(apk_R, apk_R_new_content, enc); //根据public.xml来调整R.smali string apk_public = m_apkinfo.in_res + @"\values\public.xml"; SortedDictionary<string, List<public_xml_model>> apk_dict = new SortedDictionary<string, List<public_xml_model>>(); XmlDocument apk_public_doc = new XmlDocument(); apk_public_doc.Load(apk_public); XmlNodeList apk_nodes = apk_public_doc.DocumentElement.ChildNodes; if (apk_nodes.Count > 0) { foreach (XmlNode node in apk_nodes) { public_xml_model pxm = new public_xml_model(); pxm.type = node.Attributes["type"].Value; pxm.name = node.Attributes["name"].Value; pxm.id = node.Attributes["id"].Value; pxm.id_high = Convert.ToInt32(pxm.id.Substring(2, 4), 16); pxm.id_low = Convert.ToInt32(pxm.id.Substring(6, 4), 16); if (!apk_dict.ContainsKey(pxm.type)) apk_dict.Add(pxm.type, new List<public_xml_model>()); apk_dict[pxm.type].Add(pxm); } } if (apk_dict.Count > 0) { string apk_R_type_path = string.Empty; string apk_R_type_content = string.Empty; int apk_R_type_start_pos = -1; int apk_R_type_end_pos = -1; List<string> apk_R_type_lines = new List<string>(); string apk_R_type_insert = string.Empty; List<public_xml_model> apk_R_type_pxms = null; foreach (string apk_type in apk_dict.Keys) { apk_R_type_path = Path.GetDirectoryName(apk_R) + @"\R$" + apk_type + @".smali"; if (!File.Exists(apk_R_type_path)) continue; enc = TxtFileEncoder.GetEncoding(apk_R_type_path); apk_R_type_content = File.ReadAllText(apk_R_type_path, enc); apk_R_type_lines = apk_R_type_content.Replace("\r\n", "*").Split('*').ToList(); apk_R_type_start_pos = apk_R_type_lines.IndexOf(@"# static fields") + 1; apk_R_type_end_pos = apk_R_type_lines.IndexOf(@"# direct methods"); apk_R_type_lines.RemoveRange(apk_R_type_start_pos, apk_R_type_end_pos - apk_R_type_start_pos); apk_R_type_pxms = apk_dict[apk_type]; apk_R_type_pxms.Reverse(); foreach (public_xml_model pxm in apk_R_type_pxms) { apk_R_type_insert = @".field public static final " + pxm.name.Replace(".", "_") + @":I = " + pxm.id; apk_R_type_lines.Insert(apk_R_type_start_pos, apk_R_type_insert); apk_R_type_lines.Insert(apk_R_type_start_pos + 1, ""); } apk_R_type_end_pos = apk_R_type_lines.IndexOf(@"# direct methods"); apk_R_type_lines.Insert(apk_R_type_end_pos, ""); apk_R_type_content = string.Empty; foreach (string apk_R_type_line in apk_R_type_lines) { apk_R_type_content += apk_R_type_line + "\r\n"; } File.WriteAllText(apk_R_type_path, apk_R_type_content, enc); } } } while (false); //合并smali文件夹和文件 if (copy_folders != null) { string from_folder = string.Empty; string to_folder = string.Empty; foreach (string folder in copy_folders) { from_folder = m_sdkinfo.in_smali + @"\" + folder; to_folder = m_apkinfo.in_smali; if (Directory.Exists(from_folder)) { List<string> split_folders = folder.Split('\\').ToList(); for (int i = 0; i < split_folders.Count; i++) { if ((i + 1) == split_folders.Count) { utils.copy_folder(from_folder, to_folder); } else { to_folder += @"\" + split_folders[i]; if (!Directory.Exists(to_folder)) Directory.CreateDirectory(to_folder); } } } } } if (copy_files != null) { try { string from_file = string.Empty; string to_file = string.Empty; foreach (string file in copy_files) { from_file = m_sdkinfo.in_smali + @"\" + file; to_file = m_apkinfo.in_smali; if (File.Exists(from_file)) { List<string> split_folders = file.Split('\\').ToList(); for (int i = 0; i < split_folders.Count; i++) { to_file += @"\" + split_folders[i]; if ((i + 1) == split_folders.Count) { if (File.Exists(to_file)) File.Delete(to_file); File.Copy(from_file, to_file); } else { if (!Directory.Exists(to_file)) Directory.CreateDirectory(to_file); } } } } } catch (Exception e) { e.ToString(); } } //植入smali代码 //需要在每个游戏合并类中自定义合并代码 }
/// <summary> /// 快速排序-比较方法(pxm.id_high比较) /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static int pxm_compare_id_high(public_xml_model a, public_xml_model b) { if (a.id_high > b.id_high) return 1; else if (a.id_high == b.id_high) return 0; else return -1; }
public virtual void MergeRes() { if (!Directory.Exists(m_sdkinfo.in_res)) return; string sdk_public = m_sdkinfo.in_res + @"\values\public.xml"; string apk_public = m_apkinfo.in_res + @"\values\public.xml"; SortedDictionary<string, List<public_xml_model>> sdk_dict = new SortedDictionary<string, List<public_xml_model>>(); SortedDictionary<string, List<public_xml_model>> apk_dict = new SortedDictionary<string, List<public_xml_model>>(); XmlDocument sdk_public_doc = new XmlDocument(); sdk_public_doc.Load(sdk_public); XmlNodeList sdk_nodes = sdk_public_doc.DocumentElement.ChildNodes; if (sdk_nodes.Count > 0) { foreach (XmlNode node in sdk_nodes) { public_xml_model pxm = new public_xml_model(); pxm.type = node.Attributes["type"].Value; pxm.name = node.Attributes["name"].Value; pxm.id = node.Attributes["id"].Value; pxm.id_high = Convert.ToInt32(pxm.id.Substring(2, 4), 16); pxm.id_low = Convert.ToInt32(pxm.id.Substring(6, 4), 16); if (!sdk_dict.ContainsKey(pxm.type)) sdk_dict.Add(pxm.type, new List<public_xml_model>()); sdk_dict[pxm.type].Add(pxm); } } XmlDocument apk_public_doc = new XmlDocument(); apk_public_doc.Load(apk_public); XmlNodeList apk_nodes = apk_public_doc.DocumentElement.ChildNodes; if (apk_nodes.Count > 0) { foreach (XmlNode node in apk_nodes) { public_xml_model pxm = new public_xml_model(); pxm.type = node.Attributes["type"].Value; pxm.name = node.Attributes["name"].Value; pxm.id = node.Attributes["id"].Value; pxm.id_high = Convert.ToInt32(pxm.id.Substring(2, 4), 16); pxm.id_low = Convert.ToInt32(pxm.id.Substring(6, 4), 16); if (!apk_dict.ContainsKey(pxm.type)) apk_dict.Add(pxm.type, new List<public_xml_model>()); apk_dict[pxm.type].Add(pxm); } } //调整dict集合内数据 if (sdk_dict.Count > 0) { for (int sdk_pos = 0; sdk_pos < sdk_dict.Count; sdk_pos++) { KeyValuePair<string, List<public_xml_model>> item = sdk_dict.ElementAt(sdk_pos); List<public_xml_model> pxms = item.Value; utils.quick_sort_fast<public_xml_model>(ref pxms, 0, pxms.Count - 1, shell_utils.pxm_compare_id_low); sdk_dict[item.Key] = pxms; } } if (apk_dict.Count > 0) { for (int apk_pos = 0; apk_pos < apk_dict.Count; apk_pos++) { KeyValuePair<string, List<public_xml_model>> item = apk_dict.ElementAt(apk_pos); List<public_xml_model> pxms = item.Value; utils.quick_sort_fast<public_xml_model>(ref pxms, 0, pxms.Count - 1, shell_utils.pxm_compare_id_low); apk_dict[item.Key] = pxms; } } //获取ID-HIGH最大值 int sdk_id_high_max = 0; int apk_id_high_max = 0; if (sdk_dict.Count > 0) { List<public_xml_model> pxms = new List<public_xml_model>(); for (int sort_pos = 0; sort_pos < sdk_dict.Count; sort_pos++) { pxms.Add(sdk_dict.ElementAt(sort_pos).Value[0]); } utils.quick_sort_fast<public_xml_model>(ref pxms, 0, pxms.Count - 1, shell_utils.pxm_compare_id_high); pxms.Reverse(); sdk_id_high_max = pxms[0].id_high; } if (apk_dict.Count > 0) { List<public_xml_model> pxms = new List<public_xml_model>(); for (int m = 0; m < apk_dict.Count; m++) { pxms.Add(apk_dict.ElementAt(m).Value[0]); } utils.quick_sort_fast<public_xml_model>(ref pxms, 0, pxms.Count - 1, shell_utils.pxm_compare_id_high); pxms.Reverse(); apk_id_high_max = pxms[0].id_high; } //合并public if (sdk_dict.Count > 0) { int insert_id_high = apk_id_high_max; int insert_id_low = 0; foreach (string sdk_type in sdk_dict.Keys) { if (apk_dict.ContainsKey(sdk_type)) { foreach (public_xml_model pxm in sdk_dict[sdk_type]) { if (!shell_utils.exist_pxm_name(apk_dict[sdk_type], pxm.name)) { public_xml_model insert_pxm = pxm; insert_pxm.id_high = apk_dict[sdk_type].Last().id_high; insert_pxm.id_low = apk_dict[sdk_type].Last().id_low + 1; insert_pxm.id = string.Format("0x{0:X4}", insert_pxm.id_high).ToLower() + string.Format("{0:X4}", insert_pxm.id_low).ToLower(); apk_dict[sdk_type].Add(insert_pxm); } } } else { insert_id_high++; insert_id_low = 0; apk_dict[sdk_type] = new List<public_xml_model>(); foreach (public_xml_model pxm in sdk_dict[sdk_type]) { public_xml_model insert_pxm = pxm; insert_pxm.id_high = insert_id_high; insert_pxm.id_low = insert_id_low++; insert_pxm.id = string.Format("0x{0:X4}", insert_pxm.id_high).ToLower() + string.Format("{0:X4}", insert_pxm.id_low).ToLower(); apk_dict[sdk_type].Add(insert_pxm); } } } } //重写public.xml if (apk_dict.Count > 0) { List<public_xml_model> pxms = new List<public_xml_model>(); for (int m = 0; m < apk_dict.Count; m++) { pxms.Add(apk_dict.ElementAt(m).Value[0]); } utils.quick_sort_fast<public_xml_model>(ref pxms, 0, pxms.Count - 1, shell_utils.pxm_compare_id_high); apk_public_doc.DocumentElement.RemoveAll(); foreach (public_xml_model pxm in pxms) { foreach (public_xml_model insert_pxm in apk_dict[pxm.type]) { XmlElement insert_element = apk_public_doc.CreateElement("public"); insert_element.SetAttribute("type", insert_pxm.type); insert_element.SetAttribute("name", insert_pxm.name); insert_element.SetAttribute("id", insert_pxm.id); apk_public_doc.DocumentElement.AppendChild(insert_element); } } apk_public_doc.Save(apk_public); } //合并res文件 List<string> sdk_folders = Directory.GetDirectories(m_sdkinfo.in_res).ToList(); List<string> apk_folders = Directory.GetDirectories(m_apkinfo.in_res).ToList(); string sdk_folder_name = string.Empty; string apk_file_name = string.Empty; foreach (string sdk_folder in sdk_folders) { sdk_folder_name = (new DirectoryInfo(sdk_folder)).Name; if (sdk_folder_name.IndexOf("values") != -1) continue; if (!Directory.Exists(m_apkinfo.in_res + @"\" + sdk_folder_name)) { utils.copy_folder(sdk_folder, m_apkinfo.in_res); } else { List<string> sdk_folder_files = Directory.GetFiles(sdk_folder).ToList(); foreach (string sdk_folder_file in sdk_folder_files) { apk_file_name = m_apkinfo.in_res + @"\" + sdk_folder_name + @"\" + Path.GetFileName(sdk_folder_file); if (!File.Exists(apk_file_name)) { File.Copy(sdk_folder_file, apk_file_name); } } } } //合并values List<string> sdk_value_files = Directory.GetFiles(m_sdkinfo.in_res+@"\values").ToList(); List<string> apk_value_files = Directory.GetFiles(m_apkinfo.in_res+@"\values").ToList(); if (sdk_value_files.Count > 0) { foreach (string sdk_value_file in sdk_value_files) { apk_file_name = m_apkinfo.in_res + @"\values\" + Path.GetFileName(sdk_value_file); if (Path.GetFileNameWithoutExtension(sdk_value_file) == "public") continue; if (!File.Exists(apk_file_name)) { File.Copy(sdk_value_file, apk_file_name); } else { XmlDocument sdk_values_doc = new XmlDocument(); sdk_values_doc.Load(sdk_value_file); XmlDocument apk_values_doc = new XmlDocument(); apk_values_doc.Load(apk_file_name); if (sdk_values_doc.DocumentElement.ChildNodes.Count > 0) { bool flag = false; foreach (XmlNode sdk_values_node in sdk_values_doc.DocumentElement.ChildNodes) { flag = false; foreach (XmlNode apk_values_node in apk_values_doc.DocumentElement.ChildNodes) { if (apk_values_node.Attributes["name"].Value == sdk_values_node.Attributes["name"].Value) { flag = true; break; } } if (!flag) { apk_values_doc.DocumentElement.AppendChild(apk_values_doc.ImportNode(sdk_values_node, true)); } } apk_values_doc.Save(apk_file_name); } } } } }