using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;//编辑器模式下管理场景
using System.IO;
using System;
using System.Diagnostics;
using UnityEditor;
//服务器类型
public enum ServerType
{
Local,
QA,
Alpha,
Real,
RealQA,
OutDev
}
public class IOSBuilder : MonoBehaviour {
static bool openExplorer = true;
static string[] SCENES = FindEnabledEditorScenes();
#region Build IOS IPA
//Unity编辑器扩展-菜单项
[MenuItem("Tools/BuildIOS/测试包")]
static void MenuItemBulidIOS()
{
BuildIOS(true,true,"",ServerType.QA,true);
}
#endregion
/// <summary>
/// IOS本打包处理
/// </summary>
/// <param name="offlineMode">是否支持离线模式</param>
/// <param name="projectOnly">仅导出工程不打包</param>
/// <param name="platform">具体渠道</param>
/// <param name="type">服务器类型</param>
static void BuildIOS(bool offlineMode, bool projectOnly, string platform = "", ServerType type = ServerType.Alpha, bool svnUpdate = true)
{
// 更新并获取SVN版本号
string applicationPath = Application.dataPath.Replace("/Assets", "");
//更新svn
// if (svnUpdate)
// {
// SVNUpdate(applicationPath);
// }
// string version = GetSVNVersion(applicationPath);
// string svnVersionFilePath = applicationPath + "/Shells/svn_ver.txt";
// FileStream svnVersionFile = new FileStream(svnVersionFilePath, FileMode.Create);
// StreamWriter writer = new StreamWriter(svnVersionFile);
// writer.Write(version);
// writer.Flush();
// writer.Close();
// svnVersionFile.Close();
//游戏版本号
string version = "1.0.0";
// 获取游戏版本号
string versionFilePath = applicationPath + "/version.txt";
FileStream versionFile = new FileStream(versionFilePath, FileMode.Open);
StreamReader reader = new StreamReader(versionFile);
string bundleVersion = reader.ReadLine();
string shortVersion = bundleVersion.Substring(0, bundleVersion.LastIndexOf("."));
reader.Close();
versionFile.Close();
// 修改NetworkController中的版本号
// string prefabPath = "Assets/Prefabs/Common/NetworkController.prefab";
// GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath) as GameObject;
// NetworkController netCtrl = prefab.GetComponent<NetworkController>();
// if (netCtrl._clientVersion != bundleVersion)
// {
// netCtrl._clientVersion = bundleVersion;
// EditorUtility.SetDirty(prefab);
// AssetDatabase.SaveAssets();
// }
// 设置输出目录名
string dir_name = "xiaoxiong";
dir_name = dir_name + (projectOnly ? "_proj" : "_ipa");
dir_name = dir_name + (offlineMode ? "_offline" : "");
switch (type)
{
case ServerType.Local:
dir_name = dir_name + "_local";
break;
case ServerType.QA:
dir_name = dir_name + "_qa";
break;
case ServerType.Real:
case ServerType.RealQA:
dir_name = dir_name + "_release";
break;
}
dir_name = dir_name + "_" + version;
dir_name = dir_name + (platform.Length > 0 ? "_" + platform : "");
// 重设宏定义
string macroDefine = "EXCEPT_LINE";
macroDefine += ";ENCRYPT";
// 设置应用信息
PlayerSettings.companyName = "LongtuGame";
PlayerSettings.productName = "小熊爱消除";
switch (platform)
{
case "lemon":
if(type != ServerType.Real){
PlayerSettings.applicationIdentifier = "com.longtugame.xxaxc.cj";
}else{
PlayerSettings.applicationIdentifier = "com.longtugame.xxaxc";
}
macroDefine += ";PLATFORM_LemonAppStore";
break;
default:
PlayerSettings.applicationIdentifier = "com.longtugame.xxaxc";
break;
}
// 设置SDK测试平台信息
//PlayerSettings.iOS.sdkVersion = projectOnly ? iOSSdkVersion.SimulatorSDK : iOSSdkVersion.DeviceSDK;
//(为真机测试平台,否则打开上一句代码)
PlayerSettings.iOS.sdkVersion = iOSSdkVersion.DeviceSDK;
PlayerSettings.iOS.targetOSVersion = iOSTargetOSVersion.iOS_7_0;
// 设置版本号(注意这里与安卓不同)
#if UNITY_5
PlayerSettings.bundleVersion = bundleVersion;
PlayerSettings.iOS.buildNumber = version;
#else
PlayerSettings.bundleVersion = version;
PlayerSettings.shortBundleVersion = bundleVersion;
#endif
// 设置编译平台
string target_dir = applicationPath + "/Packages/Xcode";
BuildTarget buildTarget = BuildTarget.iOS;
BuildTargetGroup targetGroup = BuildTargetGroup.iOS;
// 创建目标目录
if (!Directory.Exists(target_dir))
{
Directory.CreateDirectory(target_dir);
}
// 删除已有工程
string target_path = target_dir + "/" + dir_name;
DeleteDirectory(target_path);
switch (type)
{
case ServerType.Local:
macroDefine += ";PLATFORM_LOCAL";
break;
case ServerType.QA:
macroDefine += ";PLATFORM_QA";
break;
case ServerType.Real:
case ServerType.RealQA:
macroDefine += ";RELEASE_MODE";
break;
default:
break;
}
if(type != ServerType.Real){
#if (UNITY_IOS || UNITY_IPHONE)
UnityEngine.Debug.Log("-------Enabling USE_TestXG...");
PlayerSettings.iOS.appleDeveloperTeamID = "SVH5KV22E6";
#endif
}else{
#if (UNITY_IOS || UNITY_IPHONE)
PlayerSettings.iOS.appleDeveloperTeamID = "UC3LC49W33";
#endif
#if UNITY_5
PlayerSettings.iOS.buildNumber = string.Format("{0}1", bundleVersion);
#else
PlayerSettings.bundleVersion = string.Format("{0}1", bundleVersion);
#endif
}
// 离线模式处理
if (offlineMode)
{
// 设置离线模式支持
macroDefine += ";OFFLINE_SUPPORT";
}
macroDefine += ";HOTFIX_ENABLE";
// 刷新工程内的文件
AssetDatabase.Refresh();
// 设置宏定义
PlayerSettings.SetScriptingDefineSymbolsForGroup(targetGroup, macroDefine);
// 开始Build场景
GenericBuild(SCENES, target_path, buildTarget, BuildOptions.None);
// 重设宏定义
PlayerSettings.SetScriptingDefineSymbolsForGroup(targetGroup, "EXCEPT_LINE");
// 提交版本号文件
if (isSVNFileModified(versionFilePath))
{
string logMsg = "update client version number to " + bundleVersion;
SVNCommit(new string[] { versionFilePath }, logMsg);
}
// 打开输出目录
if (projectOnly)
{
if (openExplorer)
{
Process.Start("open", target_path);
}
return;
}
// 创建IPA输出目录
string outputDir = applicationPath + "/Packages/IOS/" + version + "/";
if (!Directory.Exists(outputDir))
{
Directory.CreateDirectory(outputDir);
}
// 生成app的指令
string iossdk = "iphoneos";
//string command = "cd " + target_path + "\n";
string appPath = "";
string command = "";
string archiveName = dir_name + ".xcarchive";
if (type == ServerType.Real)
{
//command += "xcodebuild clean -configuration Release -quiet || exit";
//command += "xcodebuild clean build -sdk " + iossdk + " -target Unity-iPhone -configuration Release\n";
// 生成ipa的指令
//有可能需要修改app的路径名称
//appPath = "build/Release-iphoneos/xxaxc.app";
command = "build_ios_real.sh " + target_path + " " + outputDir + " " + archiveName;
}
else
{
//command += "xcodebuild clean -configuration Debug -quiet || exit";
//command += "xcodebuild clean build -sdk " + iossdk + " -target Unity-iPhone -configuration Debug\n";
// 生成ipa的指令
//有可能需要修改app的路径名称
//appPath = "build/Debug-iphoneos/xxaxc.app";
command = "build_ios_qa_qa.sh " + target_path + " " + outputDir + " " + archiveName;
}
/*
string ipaPath = ipaDir + "xiaoxiong";
ipaPath = ipaPath + "_" + bundleVersion;
ipaPath = ipaPath + (version.Length > 0 ? "." + version : "");
ipaPath = ipaPath + (offlineMode ? "_offline" : "");
switch (type)
{
case ServerType.Local:
ipaPath = ipaPath + "_local";
break;
case ServerType.QA:
ipaPath = ipaPath + "_qa";
break;
case ServerType.Real:
ipaPath = ipaPath + "_release";
break;
default:
break;
}
ipaPath = ipaPath + (platform.Length > 0 ? "_" + platform : "");
ipaPath = ipaPath + "_" + version;
ipaPath = ipaPath + ".ipa";
command += "xcrun -sdk " + iossdk + " PackageApplication -v " + appPath + " -o " + ipaPath + "\n";
// 打开输出目录
if (openExplorer)
{
command += "open " + ipaDir + "\n";
}
// 写入脚本文件增加权限
string shellPath = applicationPath + "/Packages/packIOS.sh";
WriteText(shellPath, command);
executeCommand("chmod", "+x " + shellPath);
*/
// 重设宏定义
PlayerSettings.SetScriptingDefineSymbolsForGroup(targetGroup, "EXCEPT_LINE;OFFLINE_SUPPORT;ENCRYPT;HOTFIX_ENABLE");
// 重设包名
PlayerSettings.applicationIdentifier = "com.longtugame.xiaoxiongaixiaochu";
// 打开命令行执行脚本
//executeCommand("/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal", shellPath, false);
//executeCommand("/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal", command, true);
}
private static void executeCommand(string exe, string param, bool wait=true)
{
UnityEngine.Debug.Log("executeCommand " + param);
using (Process process = Process.Start(exe, param))
{
if (wait)
process.WaitForExit();
}
}
/// <summary>
/// 递归删除目录
/// </summary>
/// <param name="path">目录路径</param>
private static void DeleteDirectory(string path)
{
if (!Directory.Exists(path))
{
return;
}
DirectoryInfo dirInfo = new DirectoryInfo(path);
foreach (DirectoryInfo subInfo in dirInfo.GetDirectories())
{
DeleteDirectory(subInfo.FullName);
}
foreach (FileInfo fileInfo in dirInfo.GetFiles("*.*"))
{
fileInfo.Delete();
}
Directory.Delete(path, true);
}
/// <summary>
/// 递归复制目录
/// </summary>
/// <param name="source">源路径</param>
/// <param name="target">目标路径</param>
/// <returns>复制的文件+创建的目录列表</returns>
private static List<string> CopyDirectory(string source, string target)
{
List<string> modifiedPath = new List<string>();
if (!Directory.Exists(target))
{
Directory.CreateDirectory(target);
modifiedPath.Insert(0, target);
}
DirectoryInfo dirInfo = new DirectoryInfo(source);
foreach (DirectoryInfo subInfo in dirInfo.GetDirectories())
{
List<string> paths = CopyDirectory(source + "/" + subInfo.Name, target + "/" + subInfo.Name);
modifiedPath.InsertRange(0, paths);
}
foreach (FileInfo fileInfo in dirInfo.GetFiles("*.*"))
{
File.Copy(fileInfo.FullName, target + "/" + fileInfo.Name, true);
modifiedPath.Insert(0, target + "/" + fileInfo.Name);
}
return modifiedPath;
}
/// <summary>
/// 取得SVN版本号
/// </summary>
/// <param name="path">SVN文件夹路径</param>
/// <returns></returns>
private static string GetSVNVersion(string path)
{
if (EditorUserBuildSettings.selectedStandaloneTarget != BuildTarget.StandaloneWindows
&& EditorUserBuildSettings.selectedStandaloneTarget != BuildTarget.StandaloneWindows64)
{
using (Process process = new Process())
{
process.StartInfo.FileName = "svn";
process.StartInfo.Arguments = "info " + path;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
process.Close();
string version = string.Empty;
string matchStr = "Revision: ";
int len = matchStr.Length;
int index1 = output.IndexOf(matchStr);
int index2 = output.IndexOf("\n", index1);
if (index1 > 0 && index2 > index1)
{
version = output.Substring(index1 + len, index2 - index1 - len);
}
return version;
}
}
else
{
using (Process process = new Process())
{
process.StartInfo.FileName = "SubWCRev.exe";
process.StartInfo.Arguments = "\"" + path + "\"";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
process.Close();
string version = string.Empty;
string matchStr = "to revision ";
int len = matchStr.Length;
int index1 = output.IndexOf(matchStr);
int index2 = output.IndexOf("\r\n", index1);
if (index1 > 0 && index2 > index1)
{
version = output.Substring(index1 + len, index2 - index1 - len);
}
//string version = @"2000";
return version;
}
}
}
/// <summary>
/// 判断文件相对于SVN是否有修改
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
private static bool isSVNFileModified(string path)
{
if (EditorUserBuildSettings.selectedStandaloneTarget != BuildTarget.StandaloneWindows
&& EditorUserBuildSettings.selectedStandaloneTarget != BuildTarget.StandaloneWindows64)
{
using (Process process = new Process())
{
process.StartInfo.FileName = "svn";
process.StartInfo.Arguments = "st " + path;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
process.Close();
return output.IndexOf("M ") == 0;
}
}
else
{
using (Process process = new Process())
{
process.StartInfo.FileName = "SubWCRev.exe";
process.StartInfo.Arguments = "\"" + path + "\"";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
process.Close();
return output.IndexOf("Local modifications found") > 0;
//return false;
}
}
}
private static void SVNUpdate(string path)
{
if (EditorUserBuildSettings.selectedStandaloneTarget != BuildTarget.StandaloneWindows
&& EditorUserBuildSettings.selectedStandaloneTarget != BuildTarget.StandaloneWindows64)
{
using (var process = new Process())
{
process.StartInfo.FileName = "svn";
process.StartInfo.Arguments = "update " + Application.dataPath.Replace("/Assets", "");
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
using (StreamReader reader = process.StandardOutput)
{
string line = reader.ReadLine();
while (line != null && line.Length > 0)
{
UnityEngine.Debug.Log(line);
line = reader.ReadLine();
}
}
process.WaitForExit();
}
}
else
{
string arguments = "/command:update /path:\"" + path + "\" /closeonend:2";
Process process = Process.Start("TortoiseProc.exe", arguments);
process.WaitForExit();
}
AssetDatabase.Refresh();
}
private static void SVNCommit(string[] filelist, string logmsg)
{
Process process = null;
if (EditorUserBuildSettings.selectedStandaloneTarget != BuildTarget.StandaloneWindows
&& EditorUserBuildSettings.selectedStandaloneTarget != BuildTarget.StandaloneWindows64)
{
string pathlist = string.Empty;
for (int n = 0; n < filelist.Length; n++)
{
pathlist += "\"" + filelist[n] + "\" ";
}
string arguments = "commit -m \"" + logmsg + "\" " + pathlist;
UnityEngine.Debug.Log(arguments);
process = Process.Start("svn", arguments);
}
else
{
string pathlist = string.Empty;
for (int n = 0; n < filelist.Length; n++)
{
if (n > 0) pathlist += "*";
pathlist += filelist[n];
}
string arguments = "/command:commit /path:\"" + pathlist + "\"";
arguments += " /logmsg:\"" + logmsg + "\" /closeonend:2";
process = Process.Start("TortoiseProc.exe", arguments);
}
process.WaitForExit();
}
private static void ReplaceInFile(string filePath, string origin, string dest)
{
FileStream fileStream = new FileStream(filePath, FileMode.Open);
byte[] buffer = new byte[fileStream.Length];
fileStream.Read(buffer, 0, (int)fileStream.Length);
fileStream.Close();
string fileContent = System.Text.Encoding.Default.GetString(buffer);
fileContent = fileContent.Replace(origin, dest);
buffer = System.Text.Encoding.Default.GetBytes(fileContent);
fileStream = new FileStream(filePath, FileMode.Truncate);
fileStream.Write(buffer, 0, buffer.Length);
fileStream.Close();
}
private static void WriteText(string filePath, string content)
{
byte[] buffer = System.Text.Encoding.Default.GetBytes(content);
FileStream fileStream = File.Exists(filePath)
? new FileStream(filePath, FileMode.Truncate)
: new FileStream(filePath, FileMode.OpenOrCreate);
fileStream.Write(buffer, 0, buffer.Length);
fileStream.Close();
}
private static string[] FindEnabledEditorScenes()
{
List<string> EditorScenes = new List<string>();
foreach (EditorBuildSettingsScene scene in EditorBuildSettings.scenes)
{
if (!scene.enabled) continue;
EditorScenes.Add(scene.path);
}
return EditorScenes.ToArray();
}
static void GenericBuild(string[] scenes, string target_dir, BuildTarget build_target, BuildOptions build_options)
{
if (EditorUserBuildSettings.activeBuildTarget != build_target)
{
EditorUserBuildSettings.SwitchActiveBuildTarget(build_target);
}
string res = BuildPipeline.BuildPlayer(scenes, target_dir, build_target, BuildOptions.None);
if (res.Length > 0)
{
throw new Exception("BuildPlayer failure: " + res);
}
}
}
ios
最新推荐文章于 2024-09-11 09:50:55 发布
本文深入探讨了iOS开发中的关键技术点,包括Swift语言特性、UIKit框架应用、App性能优化及实战项目经验分享,帮助开发者提升iOS应用开发能力。
摘要由CSDN通过智能技术生成