123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- #if UNITY_ANDROID
- //using ICSharpCode.SharpZipLib.Zip;
- using System;
- using System.IO;
- using System.Text;
- using System.Text.RegularExpressions;
- using UnityEditor;
- using UnityEngine;
- namespace XGame.Editor.Build
- {
- public static class ObbUtil
- {
- public static void GenerateObb(string pathToBuiltProject)
- {
- var outputPath = Path.GetDirectoryName(pathToBuiltProject).Replace("\\", "/");
- var obbRoot = $"{outputPath}/obb/";
- var obbAssets = $"{obbRoot}assets";
- //Debug.Log($"directory:{outputPath} obb:{obbRoot}");
- if (!Directory.Exists(obbAssets))
- {
- return;
- }
- string apkFolder = null;
- string manifestPath = null;
- if (EditorUserBuildSettings.exportAsGoogleAndroidProject)
- {
- manifestPath = $"{pathToBuiltProject}/unityLibrary/src/main/AndroidManifest.xml";
- }
- else
- {
- //解压apk
- apkFolder = UnCompressApk(pathToBuiltProject);
- if (!string.IsNullOrEmpty(apkFolder))
- {
- manifestPath = $"{apkFolder}/AndroidManifest.xml";
- }
- }
- if (!string.IsNullOrEmpty(manifestPath))
- {
- //取出Unity的build-id
- Regex regex = new Regex(@"<meta-data android:name=""unity\.build-id"" android:value=""(.+?)""(\s*)/>", RegexOptions.Multiline);
- var manifest = File.ReadAllText(manifestPath);
- var match = regex.Match(manifest);
- if (match.Success)
- {
- BuildLog.Log($"unity.build-id:{match.Groups[1].Value}");
- File.WriteAllText($"{obbAssets}/{match.Groups[1].Value}", "", Encoding.UTF8);
- }
- else
- {
- BuildLog.Error($"找不到unity.build-id ManifestPath:{manifestPath}");
- return;
- }
- try
- {
- //生成新的obb
- var zip = $"{outputPath}/main.{PlayerSettings.Android.bundleVersionCode}.{PlayerSettings.applicationIdentifier}.obb";
- ProcessCommand(SevenZipExePath, "-tZip a " + zip + " " + obbAssets + " -mx0");
- //using (var zipFile = File.Create($"{outputPath}/main.{PlayerSettings.Android.bundleVersionCode}.{PlayerSettings.applicationIdentifier}.obb"))
- //{
- // using (ZipOutputStream zipOutStream = new ZipOutputStream(zipFile))
- // {
- // zipOutStream.SetLevel(0);// 0 - store only to 9 - means best compression
- // ZipCrc32 crc = new ZipCrc32();
- // ZipDirectory(obbRoot, obbAssets, zipOutStream, crc);
- // }
- //}
- }
- catch (Exception ex)
- {
- BuildLog.Error("生成obb文件失败");
- BuildLog.Exception(ex);
- }
- //删除obb文件夹
- UnityEditor.FileUtil.DeleteFileOrDirectory(obbRoot);
- //删除解压的apk文件夹
- if (!string.IsNullOrEmpty(apkFolder))
- {
- UnityEditor.FileUtil.DeleteFileOrDirectory(apkFolder);
- }
- }
- }
- #region 解压apk
- //[MenuItem("Build/UnCompressApk")]
- //public static void _UnCompressApk()
- //{
- // UnCompressApk("D:/WorkSpaces/XGameBuild/output/xbuild.apk");
- //}
- private static string UnCompressApk(string apkPath)
- {
- var apkToolPath = ApkToolPath;
- if (string.IsNullOrEmpty(apkToolPath))
- {
- BuildLog.Error("找不到Apktool!!!!!!!!!");
- return string.Empty;
- }
- //apktool固定解压到工程主目录下
- var apkFolder = Path.GetFullPath($"{Application.dataPath}/../{Path.GetFileNameWithoutExtension(apkPath)}").Replace("\\", "/");
- //先删除旧文件夹
- if (Directory.Exists(apkFolder))
- {
- BuildLog.Log($"存在apk文件夹,先删除。Path:{apkFolder}");
- UnityEditor.FileUtil.DeleteFileOrDirectory(apkFolder);
- }
- ProcessCommand("java.exe", "-jar " + apkToolPath + " d " + apkPath);
- return apkFolder;
- }
- private static readonly string _apktoolRelativePath = "Build/Editor/BuildPlayer/apktool/apktool.jar";
- private static string ApkToolPath
- {
- get
- {
- var guids = AssetDatabase.FindAssets("apktool");
- foreach (var guid in guids)
- {
- var assetPath = AssetDatabase.GUIDToAssetPath(guid);
- if (assetPath.EndsWith(_apktoolRelativePath))
- {
- var path = Path.GetFullPath(assetPath).Replace("\\", "/");
- BuildLog.Log($"ApkToolPath:{path}");
- return path;
- }
- }
- return string.Empty;
- }
- }
- private static readonly string _zipExeRelativePath = "Build/Editor/BuildPlayer/7z/sevenZip.exe";
- private static string SevenZipExePath
- {
- get
- {
- var guids = AssetDatabase.FindAssets("sevenZip");
- foreach (var guid in guids)
- {
- var assetPath = AssetDatabase.GUIDToAssetPath(guid);
- if (assetPath.EndsWith(_zipExeRelativePath))
- {
- var path = Path.GetFullPath(assetPath).Replace("\\", "/");
- BuildLog.Log($"SevenZipExePath:{path}");
- return path;
- }
- }
- return string.Empty;
- }
- }
- private static void ProcessCommand(string command, string argument, bool shell = true)
- {
- var start = new System.Diagnostics.ProcessStartInfo(command)
- {
- Arguments = argument,
- CreateNoWindow = false,
- ErrorDialog = true,
- UseShellExecute = true
- };
- if (start.UseShellExecute)
- {
- start.RedirectStandardOutput = false;
- start.RedirectStandardError = false;
- start.RedirectStandardInput = false;
- }
- else
- {
- start.RedirectStandardOutput = true;
- start.RedirectStandardError = true;
- start.RedirectStandardInput = true;
- start.StandardOutputEncoding = Encoding.UTF8;
- start.StandardErrorEncoding = Encoding.UTF8;
- }
- var process = System.Diagnostics.Process.Start(start);
- if (!start.UseShellExecute)
- {
- BuildLog.Log(process.StandardOutput.ReadToEnd());
- BuildLog.Error(process.StandardError.ReadToEnd());
- }
- process.WaitForExit();
- process.Close();
- }
- #endregion
- #region 打包obb
- /// <summary>
- /// 递归遍历目录
- /// </summary>
- //private static void ZipDirectory(string root, string directoryToZip, ZipOutputStream zipOutput, ZipCrc32 crc)
- //{
- // var filenames = Directory.GetFileSystemEntries(directoryToZip);
- // foreach (string file in filenames)// 遍历所有的文件和目录
- // {
- // if (Directory.Exists(file))// 先当作目录处理如果存在这个目录就递归Copy该目录下面的文件
- // {
- // ZipDirectory(root, file, zipOutput, crc);
- // }
- // else // 否则直接压缩文件
- // {
- // //打开压缩文件
- // using (FileStream fileStream = File.OpenRead(file))
- // {
- // var buffer = new byte[fileStream.Length];
- // fileStream.Read(buffer, 0, buffer.Length);
- // //string fileName = parentPath + file.Substring(file.LastIndexOf("\\") + 1);
- // var entry = new ZipEntry(file.Replace("\\", "/").Replace(root, ""))
- // {
- // DateTime = DateTime.Now,
- // Size = fileStream.Length
- // };
- // fileStream.Close();
- // crc.Reset();
- // crc.Update(buffer);
- // entry.Crc = crc.Value;
- // zipOutput.PutNextEntry(entry);
- // zipOutput.Write(buffer, 0, buffer.Length);
- // }
- // }
- // }
- //}
- #endregion
- }
- }
- #endif
|