using System; using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEngine; #if UNITY_EDITOR_OSX && UNITY_IOS using UnityEditor.iOS.Xcode; public class Package { [UnityEditor.Callbacks.PostProcessBuildAttribute(100)] public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject) { if (target != BuildTarget.iOS) { Debug.LogWarning("Target is not iPhone. XCodePostProcess will not run"); return; } // Create a new project object from build target UnityEditor.iOS.Xcode.PBXProject project = new UnityEditor.iOS.Xcode.PBXProject(); string configFilePath = UnityEditor.iOS.Xcode.PBXProject.GetPBXProjectPath(pathToBuiltProject); project.ReadFromFile(configFilePath); string targetGuid = project.GetUnityMainTargetGuid(); string targetGuid_Framework = project.GetUnityFrameworkTargetGuid(); string debug = project.BuildConfigByName(targetGuid, "Debug"); string release = project.BuildConfigByName(targetGuid, "Release"); project.AddBuildPropertyForConfig(debug, "CODE_SIGN_RESOURCE_RULES_PATH", "$(SDKROOT)/ResourceRules.plist"); project.AddBuildPropertyForConfig(release, "CODE_SIGN_RESOURCE_RULES_PATH", "$(SDKROOT)/ResourceRules.plist"); #region string projPath = Path.GetFullPath(pathToBuiltProject); //添加推送和其他的有点不一样,需要添加一个文件。这个文件只能考进去。或者事先准备好了Base.entitlements 文件,文件类容 就是你手动添加进去的内容,你手动添加完成后生成的那个文件 string entitlement = Application.dataPath + "/Editor/entitlement.entitlements"; File.Copy (entitlement, pathToBuiltProject + "/Unity-iPhone/entitlement.entitlements"); //Max Ad Review service File.Copy(Application.dataPath + "/ThirdParty/MaxSdk/AppLovin/Editor/AppLovinQualityServiceSetup-ios.rb", pathToBuiltProject + "/AppLovinQualityServiceSetup-ios.rb"); project.AddCapability(targetGuid, PBXCapabilityType.AssociatedDomains, pathToBuiltProject + "/Unity-iPhone/entitlement.entitlements", true); // Enable Push Notifications project.AddFrameworkToProject (targetGuid_Framework, "UserNotifications.framework", false); // Enable background mode // project.AddCapability (targetGuid, PBXCapabilityType.BackgroundModes); #region google service plist file // google service string googleServicePath = Application.dataPath + "/Plugins/iOS/GoogleService-Info.plist"; File.Copy(googleServicePath, pathToBuiltProject + "/GoogleService-Info.plist"); project.AddFileToBuild(targetGuid, project.AddFile("GoogleService-Info.plist", "GoogleService-Info.plist", PBXSourceTree.Source)); #endregion // Add background modes string plistPath = pathToBuiltProject + "/Info.plist"; PlistDocument plist = new PlistDocument(); plist.ReadFromString(File.ReadAllText(plistPath)); PlistElementDict rootDict = plist.root; //在playersetting里设置iosUseCustomAppBackgroundBehavior 和 iOSBackgroundModes // PlistElementArray arr = rootDict.CreateArray ("UIBackgroundModes"); // arr.AddString ("remote-notification"); // arr.AddString ("fetch"); //解决错误:ITMS-90339 string exitsOnSuspendKey = "UIApplicationExitsOnSuspend"; if (rootDict.values.ContainsKey(exitsOnSuspendKey)) { rootDict.values.Remove(exitsOnSuspendKey); } File.WriteAllText(plistPath, plist.WriteToString()); #endregion // 根据实际需要添加framework或者tbd // project.AddFrameworkToProject(targetGuid_Framework, "libz.tbd", false); project.AddFrameworkToProject(targetGuid_Framework, "libsqlite3.tbd", false); project.AddFrameworkToProject(targetGuid_Framework, "WebKit.framework", false); // project.AddFrameworkToProject(targetGuid, "UnityFramework.framework", false); // keychain project.AddFrameworkToProject(targetGuid_Framework, "Security.framework", false); // project.AddFrameworkToProject(targetGuid_Framework, "CoreTelephony.framework", false); // AF project.AddFrameworkToProject(targetGuid_Framework, "AdSupport.framework", false); project.AddFrameworkToProject(targetGuid_Framework, "iAd.framework", false); // AF END */ // adjust project.AddFrameworkToProject(targetGuid_Framework, "AdServices.framework", false); // ATT project.AddFrameworkToProject(targetGuid_Framework, "AppTrackingTransparency.framework", false); // ATT END // 苹果登录 project.AddFrameworkToProject(targetGuid_Framework, "AuthenticationServices.framework", true); // end project.SetBuildProperty(targetGuid_Framework, "GCC_ENABLE_OBJC_EXCEPTIONS", "YES"); project.SetBuildProperty(targetGuid, "GCC_ENABLE_OBJC_EXCEPTIONS", "YES"); project.SetBuildProperty(targetGuid, "ENABLE_BITCODE", "NO"); //处理iOS编译报错,大量Undefined symbol Swift.XXX // project.SetBuildProperty(targetGuid_Framework, "SWIFT_OBJC_BRIDGING_HEADER", "Libraries/Plugins/iOS/Unity-iPhone-Bridging-Header.h"); // project.SetBuildProperty(targetGuid_Framework, "SWIFT_VERSION", "5.0"); // project.AddBuildProperty(targetGuid_Framework, "LD_RUNPATH_SEARCH_PATHS", "@executable_path/Frameworks"); //报错内容为:Please provide an auth token with USYM_UPLOAD_AUTH_TOKEN environment // project.SetBuildProperty(targetGuid, "USYM_UPLOAD_AUTH_TOKEN", "FakeToken"); // project.SetBuildProperty(targetGuid_Framework, "USYM_UPLOAD_AUTH_TOKEN", "FakeToken"); //ITMS-90206,UnityFramework包含Framework问题 project.SetBuildProperty(targetGuid_Framework, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "NO"); project.WriteToFile(configFilePath); // 编辑plist 文件 EditorPlist(Path.GetFullPath(pathToBuiltProject)); CopyDirectory(Application.dataPath + "../BFVersions/ios/ios_common", Path.GetFullPath(pathToBuiltProject), true); } static void CopyDirectory(string sourceDir, string destinationDir, bool recursive) { // Get information about the source directory var dir = new DirectoryInfo(sourceDir); // Check if the source directory exists if (!dir.Exists) throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}"); // Cache directories before we start copying DirectoryInfo[] dirs = dir.GetDirectories(); // Create the destination directory Directory.CreateDirectory(destinationDir); // Get the files in the source directory and copy to the destination directory foreach (FileInfo file in dir.GetFiles()) { string targetFilePath = Path.Combine(destinationDir, file.Name); file.CopyTo(targetFilePath); } // If recursive and copying subdirectories, recursively call this method if (recursive) { foreach (DirectoryInfo subDir in dirs) { string newDestinationDir = Path.Combine(destinationDir, subDir.Name); CopyDirectory(subDir.FullName, newDestinationDir, true); } } } private static void EditorPlist(string filePath) { XCPlist list = new XCPlist(filePath); string ITSAppUsesNonExemptEncryption = @" ITSAppUsesNonExemptEncryption "; //在plist里面增加ITSAppUsesNonExemptEncryption,解决上架AppStore提示缺少出口合规证明 list.AddKey(ITSAppUsesNonExemptEncryption); // string AppsFlyerShouldSwizzle = @" // AppsFlyerShouldSwizzle // "; // //appFlyer 设置 AppsFlyerShouldSwizzle,解决UnityAppController冲突, // //记得AppsFlyerAppController.mm 注释掉//IMPL_APP_CONTROLLER_SUBCLASS(AppsFlyerAppController) // list.AddKey(AppsFlyerShouldSwizzle); // 跟踪权限请求描述(ATT) TODO... string NSUserTrackingUsageDescription = @" NSUserTrackingUsageDescription Your data will help us to provide a more personalized experience and offers."; list.AddKey(NSUserTrackingUsageDescription); string NSLocationWhenInUseUsageDescription = @" NSLocationWhenInUseUsageDescription We need to use location information to provide you with better network services"; list.AddKey(NSLocationWhenInUseUsageDescription); //iOS 设置状态栏的背景颜色方法 // string StatusBar = @" // UIViewControllerBasedStatusBarAppearance // "; // list.AddKey(StatusBar); //admob ironsource那里设置了 // string GADApplicationIdentifier = @" // GADApplicationIdentifier // "; // list.AddKey(GADApplicationIdentifier); //*/ //google Ads 使用 wkwebview // string gad_preferred_webview = @" // gad_preferred_webview // wkwebview"; // list.AddKey(gad_preferred_webview); // string UnityNotificationRequestAuthorizationOnAppLaunch = @" // UnityNotificationRequestAuthorizationOnAppLaunch // "; // list.AddKey(UnityNotificationRequestAuthorizationOnAppLaunch); string SKAdNetworkIdentifiers = @" SKAdNetworkItems SKAdNetworkIdentifier 2fnua5tdw4.skadnetwork SKAdNetworkIdentifier 2u9pt9hc89.skadnetwork SKAdNetworkIdentifier 3qcr597p9d.skadnetwork SKAdNetworkIdentifier 3qy4746246.skadnetwork SKAdNetworkIdentifier 3sh42y64q3.skadnetwork SKAdNetworkIdentifier 424m5254lk.skadnetwork SKAdNetworkIdentifier 4468km3ulz.skadnetwork SKAdNetworkIdentifier 4dzt52r2t5.skadnetwork SKAdNetworkIdentifier 4fzdc2evr5.skadnetwork SKAdNetworkIdentifier 578prtvx9j.skadnetwork SKAdNetworkIdentifier 5a6flpkh64.skadnetwork SKAdNetworkIdentifier 7ug5zh24hu.skadnetwork SKAdNetworkIdentifier 8c4e2ghe7u.skadnetwork SKAdNetworkIdentifier 8s468mfl3y.skadnetwork SKAdNetworkIdentifier 9rd848q2bz.skadnetwork SKAdNetworkIdentifier 9t245vhmpl.skadnetwork SKAdNetworkIdentifier av6w8kgt66.skadnetwork SKAdNetworkIdentifier c6k4g5qg8m.skadnetwork SKAdNetworkIdentifier cstr6suwn9.skadnetwork SKAdNetworkIdentifier e5fvkxwrpn.skadnetwork SKAdNetworkIdentifier f38h382jlk.skadnetwork SKAdNetworkIdentifier hs6bdukanm.skadnetwork SKAdNetworkIdentifier kbd757ywx3.skadnetwork SKAdNetworkIdentifier klf5c3l5u5.skadnetwork SKAdNetworkIdentifier n6fk4nfna4.skadnetwork SKAdNetworkIdentifier p78axxw29g.skadnetwork SKAdNetworkIdentifier ppxm28t8ap.skadnetwork SKAdNetworkIdentifier prcb7njmu6.skadnetwork SKAdNetworkIdentifier s39g8k73mm.skadnetwork SKAdNetworkIdentifier t38b2kh725.skadnetwork SKAdNetworkIdentifier uw77j35x4d.skadnetwork SKAdNetworkIdentifier v4nxqhlyqp.skadnetwork SKAdNetworkIdentifier v72qych5uu.skadnetwork SKAdNetworkIdentifier wzmmz9fp6w.skadnetwork SKAdNetworkIdentifier yclnxrl5pm.skadnetwork SKAdNetworkIdentifier ydx93a7ass.skadnetwork SKAdNetworkIdentifier zq492l623r.skadnetwork SKAdNetworkIdentifier 22mmun2rn5.skadnetwork SKAdNetworkIdentifier 24t9a8vw3c.skadnetwork SKAdNetworkIdentifier 275upjj5gd.skadnetwork SKAdNetworkIdentifier 294l99pt4k.skadnetwork SKAdNetworkIdentifier 32z4fx6l9h.skadnetwork SKAdNetworkIdentifier 3l6bd9hu43.skadnetwork SKAdNetworkIdentifier 3rd42ekr43.skadnetwork SKAdNetworkIdentifier 4pfyvq9l8r.skadnetwork SKAdNetworkIdentifier 523jb4fst2.skadnetwork SKAdNetworkIdentifier 52fl2v3hgk.skadnetwork SKAdNetworkIdentifier 54nzkqm89y.skadnetwork SKAdNetworkIdentifier 5l3tpt7t6e.skadnetwork SKAdNetworkIdentifier 5lm9lj6jb7.skadnetwork SKAdNetworkIdentifier 5tjdwbrq8w.skadnetwork SKAdNetworkIdentifier 6g9af3uyq4.skadnetwork SKAdNetworkIdentifier 6xzpu9s2p8.skadnetwork SKAdNetworkIdentifier 79pbpufp6p.skadnetwork SKAdNetworkIdentifier 7rz58n8ntl.skadnetwork SKAdNetworkIdentifier 9b89h5y424.skadnetwork SKAdNetworkIdentifier 9nlqeag3gk.skadnetwork SKAdNetworkIdentifier 9yg77x724h.skadnetwork SKAdNetworkIdentifier a8cz6cu7e5.skadnetwork SKAdNetworkIdentifier c3frkrj4fj.skadnetwork SKAdNetworkIdentifier cg4yq2srnc.skadnetwork SKAdNetworkIdentifier cj5566h2ga.skadnetwork SKAdNetworkIdentifier dkc879ngq3.skadnetwork SKAdNetworkIdentifier ejvt5qm6ak.skadnetwork SKAdNetworkIdentifier feyaarzu9v.skadnetwork SKAdNetworkIdentifier g28c52eehv.skadnetwork SKAdNetworkIdentifier ggvn48r87g.skadnetwork SKAdNetworkIdentifier glqzh8vgby.skadnetwork SKAdNetworkIdentifier gta9lk7p23.skadnetwork SKAdNetworkIdentifier k674qkevps.skadnetwork SKAdNetworkIdentifier kbmxgpxpgc.skadnetwork SKAdNetworkIdentifier ludvb6z3bs.skadnetwork SKAdNetworkIdentifier m5mvw97r93.skadnetwork SKAdNetworkIdentifier m8dbw4sv7c.skadnetwork SKAdNetworkIdentifier mlmmfzh3r3.skadnetwork SKAdNetworkIdentifier mtkv5xtk9e.skadnetwork SKAdNetworkIdentifier n66cz3y3bx.skadnetwork SKAdNetworkIdentifier n9x2a789qt.skadnetwork SKAdNetworkIdentifier nzq8sh4pbs.skadnetwork SKAdNetworkIdentifier pwa73g5rt2.skadnetwork SKAdNetworkIdentifier qqp299437r.skadnetwork SKAdNetworkIdentifier r45fhb6rf7.skadnetwork SKAdNetworkIdentifier rvh3l7un93.skadnetwork SKAdNetworkIdentifier tl55sbb4fm.skadnetwork SKAdNetworkIdentifier vcra2ehyfk.skadnetwork SKAdNetworkIdentifier wg4vff78zm.skadnetwork SKAdNetworkIdentifier x44k69ngh6.skadnetwork SKAdNetworkIdentifier x5l83yy675.skadnetwork SKAdNetworkIdentifier x8jxxk4ff5.skadnetwork SKAdNetworkIdentifier x8uqf25wch.skadnetwork SKAdNetworkIdentifier xy9t38ct57.skadnetwork SKAdNetworkIdentifier zmvfpc5aq8.skadnetwork SKAdNetworkIdentifier 44jx6755aq.skadnetwork SKAdNetworkIdentifier 44n7hlldy6.skadnetwork SKAdNetworkIdentifier 4w7y6s5ca2.skadnetwork SKAdNetworkIdentifier 6964rsfnh4.skadnetwork SKAdNetworkIdentifier 6p4ks3rnbw.skadnetwork SKAdNetworkIdentifier 737z793b9f.skadnetwork SKAdNetworkIdentifier 74b6s63p6l.skadnetwork SKAdNetworkIdentifier 84993kbrcf.skadnetwork SKAdNetworkIdentifier 97r2b46745.skadnetwork SKAdNetworkIdentifier a2p9lx4jpn.skadnetwork SKAdNetworkIdentifier a7xqa6mtl2.skadnetwork SKAdNetworkIdentifier b9bk5wbcq9.skadnetwork SKAdNetworkIdentifier bxvub5ada5.skadnetwork SKAdNetworkIdentifier dzg6xy7pwj.skadnetwork SKAdNetworkIdentifier f73kdq92p3.skadnetwork SKAdNetworkIdentifier g2y4y55b64.skadnetwork SKAdNetworkIdentifier hdw39hrw9y.skadnetwork SKAdNetworkIdentifier krvm3zuq6h.skadnetwork SKAdNetworkIdentifier lr83yxwka7.skadnetwork SKAdNetworkIdentifier mls7yz5dvl.skadnetwork SKAdNetworkIdentifier mp6xlyr22a.skadnetwork SKAdNetworkIdentifier pwdxu55a5a.skadnetwork SKAdNetworkIdentifier rx5hdcabgc.skadnetwork SKAdNetworkIdentifier s69wq72ugq.skadnetwork SKAdNetworkIdentifier su67r6k2v3.skadnetwork SKAdNetworkIdentifier u679fj5vs4.skadnetwork SKAdNetworkIdentifier w9q455wk68.skadnetwork SKAdNetworkIdentifier y45688jllp.skadnetwork SKAdNetworkIdentifier n38lu8286q.skadnetwork SKAdNetworkIdentifier v9wttpbfk9.skadnetwork SKAdNetworkIdentifier 252b5q8x7y.skadnetwork SKAdNetworkIdentifier 9g2aggbj52.skadnetwork SKAdNetworkIdentifier 238da6jt44.skadnetwork SKAdNetworkIdentifier x2jnk7ly8j.skadnetwork SKAdNetworkIdentifier 488r3q3dtq.skadnetwork SKAdNetworkIdentifier f7s53z58qe.skadnetwork SKAdNetworkIdentifier v79kvwwj4g.skadnetwork SKAdNetworkIdentifier ecpz2srf59.skadnetwork SKAdNetworkIdentifier gvmwg8q7h5.skadnetwork SKAdNetworkIdentifier pu4na253f3.skadnetwork SKAdNetworkIdentifier yrqqpx2mcb.skadnetwork SKAdNetworkIdentifier z4gj7hsk7h.skadnetwork "; list.AddKey(SKAdNetworkIdentifiers); ///*/facebook 深度连接 string facebookStr = @" CFBundleURLTypes CFBundleURLSchemes fb277827051329111 FacebookAppID 277827051329111 FacebookClientToken cd6be8cc57dff789f3476ee1b25e2410 FacebookDisplayName Knights Combo LSApplicationQueriesSchemes fb fbapi fb-messenger-share-api fbauth2 fbshareextension fbapi20130214 fbapi20130410 fbapi20130702 fbapi20131010 fbapi20131219 fbapi20140410 fbapi20140116 fbapi20150313 fbapi20150629 fbapi20160328 fbauth "; list.AddKey(facebookStr); //*/ //保存 list.Save(); } } public partial class XClassExt : System.IDisposable { private string filePath; public XClassExt(string fPath) { filePath = fPath; if (!System.IO.File.Exists(filePath)) { Debug.LogError(filePath + "not found in path."); return; } } public void WriteBelow(string below, string text) { StreamReader streamReader = new StreamReader(filePath); string text_all = streamReader.ReadToEnd(); streamReader.Close(); int beginIndex = text_all.IndexOf(below); if (beginIndex == -1) { Debug.LogError(filePath + " not found sign in " + below); return; } int endIndex = text_all.LastIndexOf("\n", beginIndex + below.Length); text_all = text_all.Substring(0, endIndex) + "\n" + text + "\n" + text_all.Substring(endIndex); StreamWriter streamWriter = new StreamWriter(filePath); streamWriter.Write(text_all); streamWriter.Close(); } public void Replace(string below, string newText) { StreamReader streamReader = new StreamReader(filePath); string text_all = streamReader.ReadToEnd(); streamReader.Close(); int beginIndex = text_all.IndexOf(below); if (beginIndex == -1) { // Debug.LogError(filePath + " not found sign in " + below); return; } text_all = text_all.Replace(below, newText); StreamWriter streamWriter = new StreamWriter(filePath); streamWriter.Write(text_all); streamWriter.Close(); } public void Dispose() { } } public partial class XCPlist : System.IDisposable { private string filePath; List contents = new List(); List removeContents = new List(); public XCPlist(string fPath) { filePath = Path.Combine(fPath, "info.plist"); if (!System.IO.File.Exists(filePath)) { Debug.LogError(filePath + "路径下文件不存在"); return; } FileInfo projectFileInfo = new FileInfo(filePath); StreamReader sr = projectFileInfo.OpenText(); while (sr.Peek() >= 0) { contents.Add(sr.ReadLine()); } sr.Close(); } public void AddKey(string key) { if (contents.Count < 2) return; contents.Insert(contents.Count - 2, key); } public void ReplaceKey(string key, string replace) { for (int i = 0; i < contents.Count; i++) { if (contents[i].IndexOf(key) != -1) { contents[i] = contents[i].Replace(key, replace); } } } public void RemoveKey(string contents) { removeContents.Add(contents); } public void Save() { StreamWriter saveFile = File.CreateText(filePath); foreach (string line in contents) saveFile.WriteLine(line); saveFile.Close(); var texts = File.ReadAllText(filePath); foreach (string content in removeContents) { texts = texts.Replace(content, ""); }; File.WriteAllText(filePath, texts); } public void Dispose() { } } #endif