using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEditor.iOS.Xcode.Custom; using UnityEditor.iOS.Xcode.Custom.Extensions; using UnityEngine; public class XCodeProjectMod { #if UNITY_IOS 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 = "5X26T385YZ"; [UnityEditor.Callbacks.PostProcessBuild(999)] public static void OnPostprocessBuild(BuildTarget buildTarget, string path) { if (buildTarget != BuildTarget.iOS) { return; } string _projectPath = PBXProject.GetPBXProjectPath(path); PBXProject _project = new PBXProject(); _project.ReadFromString(File.ReadAllText(_projectPath)); string _targetGUID = _project.TargetGuidByName(PBXProject.GetUnityTargetName()); //var _codeSign = Debug.isDebugBuild ? CODE_SIGN_DEVELOPER : CODE_SIGN_DISTRIBUTION; //var _provision = Debug.isDebugBuild ? PROVISIONING_DEVELOPER : PROVISIONING_DISTRIBUTION; // BuildSetting里的相关设置 _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"); // 处理 Framework // FreeSDK _project.AddFrameworkToProject(_targetGUID, "CoreGraphics.framework", true); _project.AddFrameworkToProject(_targetGUID, "Security.framework", true); _project.AddFrameworkToProject(_targetGUID, "CoreTelephony.framework", true); _project.AddFrameworkToProject(_targetGUID, "StoreKit.framework", true); _project.AddFrameworkToProject(_targetGUID, "MobileCoreServices.framework", true); _project.AddFrameworkToProject(_targetGUID, "SystemConfiguration.framework", true); _project.AddFrameworkToProject(_targetGUID, "AdSupport.framework", true); // 极光推送 // JPush _project.AddFrameworkToProject(_targetGUID, "CFNetwork.framework", true); _project.AddFrameworkToProject(_targetGUID, "CoreFoundation.framework", true); _project.AddFrameworkToProject(_targetGUID, "Foundation.framework", true); _project.AddFrameworkToProject(_targetGUID, "UIKit.framework", true); _project.AddFrameworkToProject(_targetGUID, "UserNotifications.framework", true); // 处理 库文件 _project.AddFileToBuild(_targetGUID, _project.AddFile("/usr/lib/libz.tbd", "Frameworks/libz.tbd", PBXSourceTree.Sdk)); _project.AddFileToBuild(_targetGUID, _project.AddFile("/usr/lib/libsqlite3.tbd", "Frameworks/libsqlite3.tbd", PBXSourceTree.Sdk)); _project.AddFileToBuild(_targetGUID, _project.AddFile("/usr/lib/libc++.tbd", "Frameworks/libc++.tbd", PBXSourceTree.Sdk)); _project.AddFileToBuild(_targetGUID, _project.AddFile("/usr/lib/libiconv.tbd", "Frameworks/libiconv.tbd", PBXSourceTree.Sdk)); _project.AddFileToBuild(_targetGUID, _project.AddFile("/usr/lib/libresolv.tbd", "Frameworks/libresolv.tbd", PBXSourceTree.Sdk)); // mr_sdk HandleMrSDK(_project, _targetGUID); // sp_sdk HandleSpSDK(_project, _targetGUID); File.WriteAllText(_projectPath, _project.WriteToString()); var _capabilityMgr = new ProjectCapabilityManager(_projectPath, "game003.entitlements", PBXProject.GetUnityTargetName()); _capabilityMgr.AddInAppPurchase(); _capabilityMgr.AddPushNotifications(true); _capabilityMgr.WriteToFile(); BuildPlist(path); if (!s_IsAppend) { ModifyFile(path); } } 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); PlistElementDict _dict = _nsAppTransportSecurity.CreateDict("Exception Domains"); _dict = _dict.CreateDict("jpush.cn"); _dict.SetBoolean("NSIncludesSubdomains", true); _dict.SetBoolean("NSExceptionAllowsInsecureHTTPLoads", true); _rootDict.SetString("NSMicrophoneUsageDescription", "使用麦克风权限"); _rootDict.SetString("NSPhotoLibraryAddUsageDescription", "使用相册权限,用以存储截屏的账号信息,以防忘记账号密码"); _rootDict.SetString("YLChannelId", "1000"); _rootDict.SetString("YLPlatformId", "1000"); File.WriteAllText(_plistPath, _plist.WriteToString()); } private static void ModifyFile(string projectPath) { bool _isMr = false; string _mrPlistPath = Application.dataPath + "/Plugins/iOS/MyMRSDK/MRSDKInfo.plist"; if (File.Exists(_mrPlistPath)) { _isMr = true; } // -------------- UnityAppController.mm //读取UnityAppController.mm文件 var _xclass = new XClass(projectPath + "/Classes/UnityAppController.mm"); //在指定代码后面增加一行代码 _xclass.WriteBelow("#include \"PluginBase/AppDelegateListener.h\"", "#include \"UniversalSDK.h\"\n#include \"JPushService.h\"\n"); if (_isMr) { _xclass.WriteBelow("#include \"PluginBase/AppDelegateListener.h\"", "#include \"IAPManager.h\"\n"); } string newCode = "\n" + "extern \"C\" void IOSMessageHandle(const char* jsonString) {\n" + " [GetAppController().universalSDK HandleUnityMessage:[NSString stringWithUTF8String:jsonString]];\n" + "}"; _xclass.WriteBelow("extern \"C\" ScreenOrientation UnityCurrentOrientation() { return GetAppController().unityView.contentOrientation; }", newCode); newCode = "\n" + " _universalSDK = [[UniversalSDK alloc] init];\n" + " [_universalSDK JPushInit:launchOptions];"; //在指定代码后面增加一大行代码 _xclass.WriteBelow("[KeyboardDelegate Initialize];", newCode); if (_isMr) { _xclass.WriteBelow("[KeyboardDelegate Initialize];", " [[IAPManager shared] startManager];\n"); } _xclass.WriteBelow("UnitySendDeviceToken(deviceToken);", " [JPUSHService registerDeviceToken:deviceToken];"); if (_isMr) { _xclass.WriteBelow("SensorsCleanup();", " [[IAPManager shared] stopManager];"); } newCode = "UnitySendRemoteNotification(userInfo);\n" + " [JPUSHService handleRemoteNotification:userInfo];\n"; _xclass.Replace("UnitySendRemoteNotification(userInfo);", newCode); newCode = "[application setApplicationIconBadgeNumber:0];\n" + " [application cancelAllLocalNotifications];\n"; _xclass.WriteBelow("::printf(\"-> applicationWillEnterForeground()\\n\");", newCode); _xclass.WriteBelow("::printf(\"-> applicationDidEnterBackground()\\n\");", "[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];\n"); newCode = " CGRect _winSize = [UIScreen mainScreen].bounds;\n" + " if(KIsiPhoneX){\n" + " _winSize.origin.x = 40;\n" + " _winSize.size.width -= 92;\n" + " _winSize.size.height -= 15;\n" + " }\n" + " _window = [[UIWindow alloc] initWithFrame:_winSize];\n"; _xclass.Replace("_window = [[UIWindow alloc] initWithFrame: [UIScreen mainScreen].bounds];", newCode); // -------------- UnityAppController.h _xclass = new XClass(projectPath + "/Classes/UnityAppController.h"); _xclass.WriteBelow("@class DisplayConnection;", "@class UniversalSDK;"); _xclass.WriteBelow("// auto-rotation view contoller goes to index=0", "UniversalSDK* _universalSDK;"); _xclass.WriteBelow("@property (readonly, copy, nonatomic) DisplayConnection* mainDisplay;", "@property (readonly, copy, nonatomic) UniversalSDK* universalSDK;"); _xclass = new XClass(projectPath + "/Classes/UI/UnityView.mm"); _xclass.WriteBelow("#include \"Unity/UnityMetalSupport.h\"", "#include \"UniversalSDK.h\""); _xclass.WriteBelow("_curOrientation = OrientationAfterTransform(_curOrientation, TransformBetweenOrientations(from, to));", @"if(KIsiPhoneX) { CGRect _winSize = [UIScreen mainScreen].bounds; if(to == landscapeLeft){ _winSize.origin.x = 0; _winSize.origin.y = 0; _winSize.size.width = 720; _winSize.size.height = 360; }else if(to == landscapeRight){ _winSize.origin.x = 0; _winSize.origin.y = -15; _winSize.size.width = 720; _winSize.size.height = 360; } [self setFrame:_winSize]; }"); _xclass = new XClass(projectPath + "/Classes/UI/UnityViewControllerBaseiOS.mm"); _xclass.Replace("return res;", "return UIRectEdgeAll;"); } 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; BuildPipeline.BuildPlayer(ClientPackage.baseLevels, _buildPath, BuildTarget.iOS, BuildOptions.Il2CPP | BuildOptions.AcceptExternalModificationsToPlayer); } public static void BuildIOSProject_Replace() { s_IsAppend = false; BuildPipeline.BuildPlayer(ClientPackage.baseLevels, GetBuildPath(), BuildTarget.iOS, BuildOptions.Il2CPP); } [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(); } private static void HandleMrSDK(PBXProject project, string targetGUID) { string _mrPlistPath = Application.dataPath + "/Plugins/iOS/MyMRSDK/MRSDKInfo.plist"; if (File.Exists(_mrPlistPath)) { string _fileGUID = project.AddFile(_mrPlistPath, "Frameworks/Plugins/iOS/MyMRSDK/MRSDKInfo.plist"); project.AddFileToBuild(targetGUID, _fileGUID); } } private static void HandleSpSDK(PBXProject project, string targetGUID) { string _filePath = Application.dataPath + "/Plugins/iOS/SPYOUSDK/GDTActionSDK.framework"; if (Directory.Exists(_filePath)) { string _frameworkGUID = project.FindFileGuidByProjectPath("Frameworks/Plugins/iOS/SPYOUSDK/GDTActionSDK.framework"); PBXProjectExtensions.AddFileToEmbedFrameworks(project, targetGUID, _frameworkGUID); } } #endif }