using System; using UnityEngine; #if UNITY_EDITOR using UnityEditor; using UnityEditor.Callbacks; #endif using System.IO; #if UNITY_EDITOR && UNITY_IOS using UnityEditor.iOS.Xcode; #endif public static class XCodePostProcess { #if UNITY_EDITOR && UNITY_IOS [PostProcessBuild(999)] public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject) { if (target != BuildTarget.iOS) { Debug.LogWarning("Target is not iPhone. XCodePostProcess will not run"); return; } Debug.Log("start modify xcode project"); var projPath = PBXProject.GetPBXProjectPath(pathToBuiltProject); PBXProject proj = new PBXProject(); proj.ReadFromString(File.ReadAllText(projPath)); var frameworkTarget = proj.GetUnityFrameworkTargetGuid(); var mainTargetGuid = proj.GetUnityMainTargetGuid(); AddFrameworkSafe(proj, frameworkTarget, "libz.tbd"); AddFrameworkSafe(proj, frameworkTarget, "Security.framework"); AddFrameworkSafe(proj, frameworkTarget, "SystemConfiguration.framework"); AddFrameworkSafe(proj, frameworkTarget, "MetricKit.framework"); AddFrameworkSafe(proj, frameworkTarget, "AuthenticationServices.framework", true); AddFrameworkSafe(proj, frameworkTarget, "AdSupport.framework"); AddFrameworkSafe(proj, frameworkTarget, "AppTrackingTransparency.framework", true); // AIHelper #if SDK_AIHELPER AddBuildPropertySafe(proj, frameworkTarget, "OTHER_LDFLAGS", "-ObjC"); AddBuildPropertySafe(proj, mainTargetGuid, "OTHER_LDFLAGS", "-ObjC"); Debug.Log("AIHelper: Added -ObjC"); #endif // CrashSight #if SDK_CRASHSIGHT SetBuildProperty(proj, mainTargetGuid, "GENERATE_DEBUG_SYMBOLS", "YES"); SetBuildProperty(proj, mainTargetGuid, "DEBUG_INFORMATION_FORMAT", "dwarf-with-dsym"); SetBuildProperty(proj, frameworkTarget, "GENERATE_DEBUG_SYMBOLS", "YES"); SetBuildProperty(proj, frameworkTarget, "DEBUG_INFORMATION_FORMAT", "dwarf-with-dsym"); Debug.Log("CrashSight: dSYM enabled"); #endif // ThingkingData #if SDK_THINKINGDATA // 开启异常 SetBuildProperty(proj, frameworkTarget, "GCC_ENABLE_OBJC_EXCEPTIONS", "YES"); SetBuildProperty(proj, mainTargetGuid, "GCC_ENABLE_OBJC_EXCEPTIONS", "YES"); SetBuildProperty(proj, frameworkTarget, "CLANG_ENABLE_OBJC_EXCEPTIONS", "YES"); SetBuildProperty(proj, mainTargetGuid, "CLANG_ENABLE_OBJC_EXCEPTIONS", "YES"); // sqlite AddFrameworkSafe(proj, frameworkTarget, "libsqlite3.tbd"); AddFrameworkSafe(proj, mainTargetGuid, "libsqlite3.tbd"); // -ObjC AddBuildPropertySafe(proj, frameworkTarget, "OTHER_LDFLAGS", "-ObjC"); AddBuildPropertySafe(proj, mainTargetGuid, "OTHER_LDFLAGS", "-ObjC"); // libc++ AddFrameworkSafe(proj, frameworkTarget, "libc++.tbd"); AddFrameworkSafe(proj, mainTargetGuid, "libc++.tbd"); // 常见依赖 AddFrameworkSafe(proj, frameworkTarget, "CoreTelephony.framework"); AddFrameworkSafe(proj, frameworkTarget, "StoreKit.framework"); Debug.Log("ThinkingData: Config applied"); #endif #if USE_OBFUZ // Obfuscation build settings SetBuildProperty(proj, frameworkTarget, "ENABLE_TESTABILITY", "YES"); SetBuildProperty(proj, mainTargetGuid, "ENABLE_TESTABILITY", "YES"); SetBuildProperty(proj, frameworkTarget, "COPY_PHASE_STRIP", "NO"); SetBuildProperty(proj, mainTargetGuid, "COPY_PHASE_STRIP", "NO"); SetBuildProperty(proj, frameworkTarget, "STRIP_STYLE", "all"); SetBuildProperty(proj, mainTargetGuid, "STRIP_STYLE", "all"); Debug.Log("USE_OBFUZ: Build settings applied"); #endif AddCapability(proj, pathToBuiltProject); proj.WriteToFile(projPath); ModifyInfoPlist(pathToBuiltProject); Debug.Log("end modify xcode project"); } /// /// 安全添加 Framework(防重复) /// /// /// /// /// private static void AddFrameworkSafe(PBXProject proj, string target, string framework, bool weak = false) { proj.AddFrameworkToProject(target, framework, weak); } /// /// 安全添加 BuildProperty(防重复) /// /// /// /// /// private static void AddBuildPropertySafe(PBXProject proj, string target, string key, string value) { var values = proj.GetBuildPropertyForAnyConfig(target, key); if (values == null || !values.Contains(value)) { proj.AddBuildProperty(target, key, value); } } /// /// 设置BuildSetting参数 /// /// /// /// /// private static void SetBuildProperty(PBXProject proj, string target, string key, string value) { proj.SetBuildProperty(target, key, value); } private static void AddCapability(PBXProject project, string pathToBuiltProject) { var target = project.GetUnityMainTargetGuid(); string relativePath = "Unity-iPhone/Unity-iPhone.entitlements"; string fullPath = Path.Combine(pathToBuiltProject, relativePath); project.AddCapability(target, PBXCapabilityType.SignInWithApple, relativePath, true); PlistDocument entitlementDoc = new PlistDocument(); if (File.Exists(fullPath)) { entitlementDoc.ReadFromFile(fullPath); } else { entitlementDoc.Create(); } const string signKey = "com.apple.developer.applesignin"; if (entitlementDoc.root[signKey] == null) { PlistElementArray array = entitlementDoc.root.CreateArray(signKey); array.AddString("Default"); } entitlementDoc.WriteToFile(fullPath); } /// /// 修改 Info.plist /// /// private static void ModifyInfoPlist(string pathToBuiltProject) { string plistPath = pathToBuiltProject + "/Info.plist"; if (!File.Exists(plistPath)) { Debug.LogError("找不到 Info.plist 文件"); return; } PlistDocument plist = new PlistDocument(); plist.ReadFromString(File.ReadAllText(plistPath)); var root = plist.root; // IDFA root.SetString( "NSUserTrackingUsageDescription", "同意我们获取设备标识,将有助于我们数据分析,以更好地优化游戏体验" ); // 相册权限 否则 ITMS-90683 root.SetString( "NSPhotoLibraryUsageDescription", "用于选择图片、上传头像或分享内容" ); // 写入相册权限 和上面搭配食用 root.SetString( "NSPhotoLibraryAddUsageDescription", "用于将图片保存到相册" ); File.WriteAllText(plistPath, plist.WriteToString()); } #endif }