using DG.Tweening.Plugins.Core.PathCore; using System; using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEditor.iOS.Xcode.Custom; using UnityEngine; public class XCodeProjectMod { private const string CODE_SIGN_DEVELOPER = ""; private const string CODE_SIGN_DISTRIBUTION = ""; private const string PROVISIONING_DEVELOPER = ""; private const string PROVISIONING_DISTRIBUTION = ""; private const string TEAM = ""; [UnityEditor.Callbacks.PostProcessBuild(999)] public static void OnPostprocessBuild(BuildTarget buildTarget, string path) { if (buildTarget != BuildTarget.iOS) { return; } DoPBXProject(path); BuildPlist(path); ModifyFile(path); } static void DoPBXProject(string path) { string _projectPath = PBXProject.GetPBXProjectPath(path); PBXProject project = new PBXProject(); project.ReadFromString(File.ReadAllText(_projectPath)); string targetGUID = project.TargetGuidByName(PBXProject.GetUnityTargetName()); string fwTargetGUID = project.TargetGuidByName("UnityFramework"); // BuildSetting里的相关设置 project.SetBuildProperty(project.ProjectGuid(), "ENABLE_BITCODE", "NO"); project.SetBuildProperty(targetGUID, "ENABLE_BITCODE", "NO"); project.SetBuildProperty(targetGUID, "DEVELOPMENT_TEAM", TEAM); project.AddBuildProperty(targetGUID, "OTHER_LDFLAGS", "-ObjC"); project.AddBuildProperty(targetGUID, "GCC_GENERATE_DEBUGGING_SYMBOLS", "NO"); //wkwebview project.AddFrameworkToProject(fwTargetGUID, "WebKit.framework", true); project.AddFrameworkToProject(fwTargetGUID, "SystemConfiguration.framework", true); project.AddFrameworkToProject(fwTargetGUID, "Security.framework", true); project.AddFrameworkToProject(fwTargetGUID, "JavaScriptCore.framework", true); project.AddFrameworkToProject(fwTargetGUID, "Accelerate.framework", true); // fimpfunSDK.framework 添加到工程并设置为 Embed & Sign string fimpfunFrameworkPath = path + "/Frameworks/fimpfunSDK.framework"; if (Directory.Exists(fimpfunFrameworkPath)) { string fileGuid = project.AddFile(fimpfunFrameworkPath, "Frameworks/fimpfunSDK.framework", PBXSourceTree.Source); project.AddFileToBuild(fwTargetGUID, fileGuid); // Embed & Sign: 添加到 main target 的 Embed Frameworks project.AddFileToBuild(targetGUID, fileGuid); } // 处理 库文件 project.AddFileToBuild(fwTargetGUID, project.AddFile("/usr/lib/libz.tbd", "Frameworks/libz.tbd", PBXSourceTree.Sdk)); project.AddFileToBuild(fwTargetGUID, project.AddFile("/usr/lib/libsqlite3.tbd", "Frameworks/libsqlite3.tbd", PBXSourceTree.Sdk)); project.AddFileToBuild(fwTargetGUID, project.AddFile("/usr/lib/libc++.tbd", "Frameworks/libc++.tbd", PBXSourceTree.Sdk)); project.AddFileToBuild(fwTargetGUID, project.AddFile("/usr/lib/libiconv.tbd", "Frameworks/libiconv.tbd", PBXSourceTree.Sdk)); project.AddFileToBuild(fwTargetGUID, project.AddFile("/usr/lib/libresolv.tbd", "Frameworks/libresolv.tbd", PBXSourceTree.Sdk)); //UnityFramework project.AddBuildProperty(fwTargetGUID, "OTHER_LDFLAGS", "-ObjC"); // 添加 GoogleService-Info.plist 和 funshine.plist 到工程 string iosPluginPath = path + "/Libraries/Plugins/iOS/Channel"; string[] configPlists = { "GoogleService-Info.plist", "funshine.plist" }; foreach (var plistName in configPlists) { string srcPath = iosPluginPath + "/" + plistName; if (File.Exists(srcPath)) { string destPath = path + "/" + plistName; File.Copy(srcPath, destPath, true); string fileGuid = project.AddFile(plistName, plistName, PBXSourceTree.Source); project.AddFileToBuild(targetGUID, fileGuid); } } File.WriteAllText(_projectPath, project.WriteToString()); } private static void BuildPlist(string path) { string _plistPath = path + "/Info.plist"; PlistDocument _plist = new PlistDocument(); _plist.ReadFromString(File.ReadAllText(_plistPath)); PlistElementDict _rootDict = _plist.root; PlistElementDict _nsAppTransportSecurity = _rootDict.CreateDict("NSAppTransportSecurity"); _nsAppTransportSecurity.SetBoolean("NSAllowsArbitraryLoads", true); _rootDict.SetString("NSPhotoLibraryAddUsageDescription", "You must grant the photo album permission to take screenshots and save data for users"); _rootDict.SetString("NSCameraUsageDescription", "Please allow application permission access, otherwise the function cannot be started"); _rootDict.SetString("NSUserTrackingUsageDescription", "This guide will display personalized ads specifically for you"); // Adjust (funshine.plist: kAdjustAppToken) _rootDict.SetString("AdjustAppToken", "nbevz727gy68"); // Facebook (funshine.plist: kFacebookAppID / kFacebookAppSecret) _rootDict.SetString("FacebookAppID", "1445747540428317"); _rootDict.SetString("FacebookClientToken", ""); _rootDict.SetString("FacebookDisplayName", "Legend of the Sword Master"); _rootDict.SetBoolean("FacebookAutoLogAppEventsEnabled", true); _rootDict.SetBoolean("FacebookAdvertiserIDCollectionEnabled", true); PlistElementArray nsURLTypes = _rootDict.CreateArray("CFBundleURLTypes"); var dict0 = nsURLTypes.AddDict(); dict0.SetString("CFBundleTypeRole", "Editor"); dict0.SetString("CFBundleURLName", "fb"); var schemesArray = dict0.CreateArray("CFBundleURLSchemes"); schemesArray.AddString("fb1445747540428317"); var array1 = _rootDict.CreateArray("LSApplicationQueriesSchemes"); array1.AddString("fbapi"); array1.AddString("fbapi20130214"); array1.AddString("fbapi20130410"); array1.AddString("fbapi20130702"); array1.AddString("fbapi20131010"); array1.AddString("fbapi20131219"); array1.AddString("fbapi20140410"); array1.AddString("fbapi20140116"); array1.AddString("fbapi20150313"); array1.AddString("fbapi20150629"); array1.AddString("fbapi20160328"); array1.AddString("fbauth"); array1.AddString("fb-messenger-share-api"); array1.AddString("fbauth2"); array1.AddString("fbshareextension"); File.WriteAllText(_plistPath, _plist.WriteToString()); } private static void ModifyFile(string projectPath) { //修改UnityAppController.mm 文件 var _xclass = new XClass(projectPath + "/Classes/UnityAppController.mm"); //引入fimpfunSDK _xclass.WriteBelow("#include \"PluginBase/AppDelegateListener.h\"", "#import \"fimpfunSDK.h\""); //unity交互调用的方法 string newCode = "\n" + "extern \"C\" void IOSUniyMessageHandle(const char* jsonString) {\n" + " [GetAppController().fimpfunBridge HandleGameMessage:[NSString stringWithUTF8String:jsonString]];\n" + "}"; _xclass.WriteBelow("extern \"C\" ScreenOrientation UnityCurrentOrientation() { return GetAppController().unityView.contentOrientation; }", newCode); //初始化fimpfunSDK newCode = "\n" + " _fimpfunBridge = [[FimpfunBridge alloc] init];\n [_fimpfunBridge YngameSDKInit:application didFinishLaunchingWithOptions:launchOptions];"; _xclass.WriteBelow("::printf(\"-> applicationDidFinishLaunching()\\n\");", newCode); // fimpfunSDK 生命周期 _xclass.WriteBelow("- (BOOL)application:(UIApplication*)app openURL:(NSURL*)url options:(NSDictionary*)options\n{", "\n [_fimpfunBridge application:app openURL:url options:options];"); _xclass.WriteBelow("::printf(\"-> applicationDidBecomeActive()\\n\");", "[_fimpfunBridge applicationDidBecomeActive:application];"); //修改UnityAppController.h 文件 _xclass = new XClass(projectPath + "/Classes/UnityAppController.h"); _xclass.WriteBelow("@class DisplayConnection;", "@class FimpfunBridge;"); _xclass.WriteBelow("DisplayConnection* _mainDisplay;", "FimpfunBridge* _fimpfunBridge;"); _xclass.WriteBelow("@property (readonly, copy, nonatomic) DisplayConnection* mainDisplay;", "@property (readonly, copy, nonatomic) FimpfunBridge* fimpfunBridge;"); } private static string GetBuildPath() { string _buildPath = Application.dataPath + "/../IOS_BUILD"; if (!Directory.Exists(_buildPath)) { Directory.CreateDirectory(_buildPath); } return new DirectoryInfo(_buildPath).FullName; } public static string[] GetBuildLevels() { List _sceneNames = new List(); foreach (var _scene in EditorBuildSettings.scenes) { if (_scene == null) { continue; } if (_scene.enabled) { _sceneNames.Add(_scene.path); } } return _sceneNames.ToArray(); } private static bool s_IsAppend = false; public static void BuildIOSProject_Append() { string _buildPath = GetBuildPath(); UnityEngine.Debug.Log(_buildPath); if (string.IsNullOrEmpty(_buildPath)) { return; } s_IsAppend = true; PlayerSettings.SetScriptingBackend(BuildTargetGroup.iOS, ScriptingImplementation.IL2CPP); BuildPipeline.BuildPlayer(ClientPackage.baseLevels, _buildPath, BuildTarget.iOS, BuildOptions.AcceptExternalModificationsToPlayer); } public static void BuildIOSProject_Replace() { s_IsAppend = false; PlayerSettings.SetScriptingBackend(BuildTargetGroup.iOS, ScriptingImplementation.IL2CPP); BuildPipeline.BuildPlayer(ClientPackage.baseLevels, GetBuildPath(), BuildTarget.iOS, BuildOptions.None); } [MenuItem("Build/ipa")] public static void BuildIPA() { var p = new System.Diagnostics.Process(); p.StartInfo.FileName = "osascript"; p.StartInfo.Arguments = string.Format("-e 'tell application \"Terminal\" \n activate \n do script \"cd {0} && sh {1} {2}\" \n end tell'", Application.dataPath + "/../", "buildipa.sh", GetBuildPath()); p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = false; p.Start(); p.WaitForExit(); } }