223 lines
8.5 KiB
C#
Executable File
223 lines
8.5 KiB
C#
Executable File
using UnityEngine;
|
|
using UnityEditor;
|
|
using System.IO;
|
|
using System.Collections.Generic;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using IOCompression = System.IO.Compression;
|
|
|
|
namespace EFSDK
|
|
{
|
|
public class AndroidResAarBuilder
|
|
{
|
|
private static readonly string ResDir = "Assets/EFSDK/Android";
|
|
private static readonly string OutputDir = "Assets/Plugins/Android";
|
|
private static readonly string TempDir = "Temp/AndroidResAar";
|
|
private static readonly string EFSdk_FILE = "Assets/EFSDK/EFSdk.cs";
|
|
|
|
[MenuItem("EFSDK/构建当前包名的推送SDK")]
|
|
public static void BuildPushSdk()
|
|
{
|
|
Debug.Log($"当前包名: {Application.identifier}");
|
|
string result = SDKEditorNetworkTool.HttpGetText(
|
|
$"http://v4.9ms.co:58080/generic-webhook-trigger/invoke?token=pushsdk&target_package_name={Application.identifier}");
|
|
Debug.Log($"{result}\n成功发起推送SDK构建请求,请稍等3分钟之后,重新打包即可");
|
|
}
|
|
|
|
[MenuItem("EFSDK/Build Android Res AAR")]
|
|
public static void BuildAAR()
|
|
{
|
|
if (!Directory.Exists(ResDir))
|
|
{
|
|
Debug.LogError($"Res folder not found: {ResDir}");
|
|
return;
|
|
}
|
|
|
|
// 清理临时目录
|
|
if (Directory.Exists(TempDir)) Directory.Delete(TempDir, true);
|
|
Directory.CreateDirectory(TempDir);
|
|
|
|
// 复制资源并重命名
|
|
CopyAndRenameFiles(ResDir, TempDir, out Dictionary<string, string> mapping);
|
|
string manifestPath = Path.Combine(TempDir, "AndroidManifest.xml");
|
|
File.WriteAllText(manifestPath,
|
|
@$"<manifest xmlns:android=""http://schemas.android.com/apk/res/android""
|
|
package=""com.{GetFirstEightWithUnderscore(GetMD5Hash(Application.identifier + "res"))}"">
|
|
<application/>
|
|
</manifest>");
|
|
|
|
// 打包 AAR
|
|
string aarPath = Path.Combine(OutputDir, "efsdk_res.aar");
|
|
if (!Directory.Exists(OutputDir)) Directory.CreateDirectory(OutputDir);
|
|
if (File.Exists(aarPath)) File.Delete(aarPath);
|
|
|
|
IOCompression.ZipFile.CreateFromDirectory(TempDir, aarPath, IOCompression.CompressionLevel.Optimal, false);
|
|
Debug.Log($"✅ AAR built:"+aarPath);
|
|
|
|
// 生成压缩 JSON (key 只保留文件名)
|
|
Dictionary<string, string> simpleMapping = new Dictionary<string, string>();
|
|
foreach (var kv in mapping)
|
|
{
|
|
string fileName = Path.GetFileName(kv.Key);
|
|
simpleMapping[fileName] = kv.Value;
|
|
}
|
|
|
|
string mappingJson = GenerateMappingJson(mapping);
|
|
// 更新 mappingInfo
|
|
// UpdateMappingInEFSdk_LineByLine(mappingJson);
|
|
// 映射文件
|
|
string mappingPath = Path.Combine(TempDir, "res_mapping.json");
|
|
File.WriteAllText(mappingPath, mappingJson);
|
|
Debug.Log($"✅ AAR 资源文件构建成功! mappingJson:"+mappingJson);
|
|
|
|
// 清理临时目录
|
|
Directory.Delete(TempDir, true);
|
|
AssetDatabase.Refresh();
|
|
}
|
|
|
|
private static void CopyAndRenameFiles(string srcDir, string dstDir, out Dictionary<string, string> mapping)
|
|
{
|
|
mapping = new Dictionary<string, string>();
|
|
|
|
foreach (var filePath in Directory.GetFiles(srcDir, "*", SearchOption.AllDirectories))
|
|
{
|
|
if (filePath.EndsWith(".meta")) continue;
|
|
|
|
// 相对于源目录的路径
|
|
string relativePath = filePath.Substring(srcDir.Length + 1).Replace("\\", "/");
|
|
|
|
// 获取文件夹路径
|
|
string relativeDir = Path.GetDirectoryName(relativePath).Replace("\\", "/");
|
|
|
|
// 生成随机文件名
|
|
string newName = GenerateRandomAndroidName(filePath);
|
|
|
|
// 保存映射关系 (相对路径 + 原始文件名 -> 随机名)
|
|
string key = Path.GetFileNameWithoutExtension(relativePath); // 可以保留目录信息
|
|
string value = string.IsNullOrEmpty(relativeDir) ? newName : $"{relativeDir}/{newName}";
|
|
string fileNameWithoutExt = Path.GetFileNameWithoutExtension(value);
|
|
// mapping[key] = fileNameWithoutExt;
|
|
mapping.Add(key, fileNameWithoutExt);
|
|
// 目标路径
|
|
string dstPath = Path.Combine(dstDir, value.Replace("/", Path.DirectorySeparatorChar.ToString()));
|
|
|
|
// 确保目录存在
|
|
string dstFolder = Path.GetDirectoryName(dstPath);
|
|
if (!Directory.Exists(dstFolder)) Directory.CreateDirectory(dstFolder);
|
|
|
|
// 复制文件
|
|
File.Copy(filePath, dstPath);
|
|
}
|
|
|
|
Debug.Log("✅ Files copied and renamed (directory structure preserved)");
|
|
}
|
|
|
|
private static string GenerateMappingJson(Dictionary<string, string> mapping)
|
|
{
|
|
var items = new List<MappingItem>();
|
|
foreach (var kv in mapping)
|
|
{
|
|
items.Add(new MappingItem { key = kv.Key, value = kv.Value });
|
|
}
|
|
|
|
MappingListWrapper wrapper = new MappingListWrapper { items = items };
|
|
return JsonUtility.ToJson(wrapper, false);
|
|
}
|
|
|
|
[System.Serializable]
|
|
private class MappingItem
|
|
{
|
|
public string key;
|
|
public string value;
|
|
}
|
|
|
|
[System.Serializable]
|
|
private class MappingListWrapper
|
|
{
|
|
public List<MappingItem> items;
|
|
}
|
|
|
|
private static string GenerateRandomAndroidName(string filePath)
|
|
{
|
|
string ext = Path.GetExtension(filePath);
|
|
string oriFileName = Path.GetFileNameWithoutExtension(filePath);
|
|
if (filePath.EndsWith(".9.png"))
|
|
{
|
|
ext = ".9.png";
|
|
oriFileName = Path.GetFileName(filePath).Replace(".9.png","");
|
|
}
|
|
string md5Str = GetFirstEightWithUnderscore(GetMD5Hash(Application.identifier + oriFileName + oriFileName));
|
|
|
|
Debug.Log($"原名:{oriFileName} 后缀:{ext} 生成文件名:{md5Str + ext}");
|
|
return md5Str + ext;
|
|
}
|
|
|
|
static string GetFirstEightWithUnderscore(string str)
|
|
{
|
|
if (string.IsNullOrEmpty(str)) return str;
|
|
string sub = str.Length <= 8 ? str : str.Substring(0, 8);
|
|
if (char.IsDigit(sub[0]))
|
|
{
|
|
sub = "a" + sub;
|
|
}
|
|
|
|
return sub;
|
|
}
|
|
|
|
public static string GetMD5Hash(string input)
|
|
{
|
|
using (var md5 = MD5.Create())
|
|
{
|
|
var inputBytes = Encoding.ASCII.GetBytes(input);
|
|
var hashBytes = md5.ComputeHash(inputBytes);
|
|
|
|
var builder = new StringBuilder();
|
|
foreach (var t in hashBytes)
|
|
{
|
|
builder.Append(t.ToString("x2")); // Convert byte to hexadecimal string
|
|
}
|
|
|
|
return builder.ToString();
|
|
}
|
|
}
|
|
|
|
private static void UpdateMappingInEFSdk_LineByLine(string mappingJson)
|
|
{
|
|
if (!File.Exists(EFSdk_FILE))
|
|
{
|
|
Debug.LogError($"EFSdk.cs not found: {EFSdk_FILE}");
|
|
return;
|
|
}
|
|
|
|
string[] lines = File.ReadAllLines(EFSdk_FILE);
|
|
bool updated = false;
|
|
for (int i = 0; i < lines.Length; i++)
|
|
{
|
|
if (lines[i].Contains("mappingInfo"))
|
|
{
|
|
lines[i] = $" private static string mappingInfo = @\"{mappingJson.Replace("\"", "\"\"")}\";";
|
|
updated = true;
|
|
break; // 找到第一行就替换,防止重复
|
|
}
|
|
}
|
|
|
|
if (!updated)
|
|
{
|
|
// 如果没有找到 mappingInfo 行,则在 _mEfSdk 后插入
|
|
for (int i = 0; i < lines.Length; i++)
|
|
{
|
|
if (lines[i].Contains("private static EFSdk _mEfSdk"))
|
|
{
|
|
lines[i] +=
|
|
$"\n private static string mappingInfo = @\"{mappingJson.Replace("\"", "\"\"")}\";";
|
|
updated = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
File.WriteAllLines(EFSdk_FILE, lines);
|
|
Debug.Log("✅ mappingInfo updated in EFSdk.cs (line-by-line)");
|
|
}
|
|
}
|
|
} |