#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(@"", 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
///
/// 递归遍历目录
///
//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