update: 更新 ReadMe 文档
							parent
							
								
									6023017cc9
								
							
						
					
					
						commit
						fa06ab3f87
					
				|  | @ -1,5 +1,4 @@ | |||
| 
 | ||||
| 
 | ||||
| namespace Guru.Editor | ||||
| { | ||||
|     using UnityEngine; | ||||
|  | @ -12,6 +11,9 @@ namespace Guru.Editor | |||
|      | ||||
|     public class AppBuildParam | ||||
|     { | ||||
|         public const string TargetNameAndroid = "Android"; | ||||
|         public const string TargetNameIOS = "iOS"; | ||||
|          | ||||
|         //------------ Basic ---------------- | ||||
|         public bool IsBuildRelease; // 是否构建发布包体 | ||||
|         public bool IsBuildShowLog; // 是否显示日志 | ||||
|  | @ -19,6 +21,7 @@ namespace Guru.Editor | |||
|         public string BuildVersion = ""; // 构建版本号, 填写后会依据此版本设置应用的 Version | ||||
|         public bool AutoSetBuildNumber = true; // 自动设置构建号, 可参考 Guru的SDK 接入说明文档 | ||||
|         public bool UseGuruCerts = true; // 是否使用 Guru 的证书打包 | ||||
|         public string TargetName = ""; | ||||
|         //------------ Android ---------------- | ||||
|         public bool IsBuildAAB; // 是否构建 AAB 包体 ( GooglePlay 发布专用 ) | ||||
|         public bool IsBuildSymbols = false; // 是否需要构建 Symbols.zip 文件 ( GooglePlay 发布专用 ) | ||||
|  | @ -38,13 +41,14 @@ namespace Guru.Editor | |||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         public static AppBuildParam Build(bool isRelease, AppBuilderType builderType = AppBuilderType.Editor, string version = "", bool autoBuildNumber = true, string companyName = "",  | ||||
|             bool buildShowLog = false, bool useGuruCerts = true,  | ||||
|         public static AppBuildParam Build(bool isRelease, AppBuilderType builderType = AppBuilderType.Editor, string version = "", bool autoBuildNumber = true, string companyName = "",   | ||||
|             string targetName = "", bool buildShowLog = false, bool useGuruCerts = true,  | ||||
|             bool buildSymbols = false,  bool buildAAB = false, bool useMinify = false,  int androidTargetVersion = 0, bool debugWithMono = true, | ||||
|             string iOSTargetVersion = "", string iOSTeamId = "") | ||||
|         { | ||||
|             return new AppBuildParam() | ||||
|             { | ||||
|                 TargetName = targetName, | ||||
|                 IsBuildRelease = isRelease, | ||||
|                 IsBuildShowLog = buildShowLog, | ||||
|                 BuilderType = builderType, | ||||
|  | @ -76,13 +80,15 @@ namespace Guru.Editor | |||
|         /// <param name="androidTargetVersion"></param> | ||||
|         /// <param name="debugWithMono"></param> | ||||
|         /// <returns></returns> | ||||
|         public static AppBuildParam AndroidParam(bool isRelease, string version = "", bool autoBuildNumber = true, AppBuilderType builderType = AppBuilderType.Editor, | ||||
|         public static AppBuildParam AndroidParam(bool isRelease, string version = "", bool autoBuildNumber = true, | ||||
|             AppBuilderType builderType = AppBuilderType.Editor, | ||||
|             string companyName = "", bool useGuruCerts = true, bool useMinify = false, int androidTargetVersion = 0, bool debugWithMono = true) | ||||
|         { | ||||
|             bool buildAAB = isRelease; | ||||
|             bool buildShowLog = isRelease; | ||||
|             bool buildSymbols = isRelease; | ||||
|             return Build(isRelease, builderType, version, autoBuildNumber,companyName, buildShowLog, useGuruCerts, buildSymbols,  buildAAB, useMinify, androidTargetVersion, debugWithMono); | ||||
|             string targetName = TargetNameAndroid;  | ||||
|             return Build(isRelease, builderType, version, autoBuildNumber,companyName, targetName, buildShowLog, useGuruCerts, buildSymbols,  buildAAB, useMinify, androidTargetVersion, debugWithMono); | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -102,7 +108,8 @@ namespace Guru.Editor | |||
|             string companyName = "", bool useGuruCerts = true, string iOSTargetVersion = "", string iOSTeamId = "" ) | ||||
|         { | ||||
|             bool buildShowLog = isRelease; | ||||
|             return Build(isRelease, builderType, version, autoBuildNumber, companyName, buildShowLog, useGuruCerts, iOSTargetVersion:iOSTargetVersion, iOSTeamId:iOSTeamId); | ||||
|             string targetName = TargetNameIOS;  | ||||
|             return Build(isRelease, builderType, version, autoBuildNumber, companyName, targetName, buildShowLog, useGuruCerts, iOSTargetVersion:iOSTargetVersion, iOSTeamId:iOSTeamId); | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
|  |  | |||
|  | @ -21,6 +21,38 @@ namespace Guru.Editor | |||
| 	    public static string KeystorePath => Application.dataPath + $"/Plugins/Android/{KeystoreName}"; | ||||
| 	    public static string ProguardName => $"proguard-user.txt"; | ||||
| 	    public static string ProguardPath => Application.dataPath + $"/Plugins/Android/{ProguardName}"; | ||||
| 	    public static string OutputDirName => "BuildOutput"; | ||||
| 
 | ||||
| 	    #region 构建接口 | ||||
| 
 | ||||
| 	    /// <summary> | ||||
| 	    /// 直接调用 Build 接口 | ||||
| 	    /// </summary> | ||||
| 	    /// <param name="buildParam"></param> | ||||
| 	    /// <returns></returns> | ||||
| 	    public static string Build(AppBuildParam buildParam) | ||||
| 	    { | ||||
| 		    string outputPath = string.Empty; | ||||
| 		    switch (buildParam.TargetName) | ||||
| 		    { | ||||
| 			    case AppBuildParam.TargetNameAndroid: | ||||
| 				    SwitchBuildPlatform(BuildTarget.Android); | ||||
| 				    outputPath = BuildAndroid(buildParam); | ||||
| 				    break; | ||||
| 			    case AppBuildParam.TargetNameIOS: | ||||
| 				    SwitchBuildPlatform(BuildTarget.iOS); | ||||
| 				    outputPath = BuildIOS(buildParam); | ||||
| 				    break; | ||||
| 			    default: | ||||
| 					Debug.Log($"<color=red> Unsupported build target: {buildParam.TargetName}. Skip build...</color>"); | ||||
| 				    break; | ||||
| 		    } | ||||
| 
 | ||||
| 		    return outputPath; | ||||
| 	    } | ||||
| 
 | ||||
| 
 | ||||
| 	    #endregion | ||||
| 	     | ||||
|         #region 构建 Android 接口 | ||||
| 
 | ||||
|  | @ -32,7 +64,7 @@ namespace Guru.Editor | |||
|         public static string BuildAndroid(AppBuildParam buildParam) | ||||
| 	    { | ||||
| 		    //切换平台 | ||||
| 		    BuildSwitchPlatform(BuildTarget.Android); | ||||
| 		    SwitchBuildPlatform(BuildTarget.Android); | ||||
| 		    //打包通用设置 | ||||
| 		    ChangeBuildPlayerCommonSetting(buildParam, BuildTargetGroup.Android); | ||||
| 		     | ||||
|  | @ -77,7 +109,7 @@ namespace Guru.Editor | |||
| 	        string version = Application.version; | ||||
| 	        string extension = buildParam.IsBuildAAB ? ".aab" : ".apk"; | ||||
| 	        if (EditorUserBuildSettings.exportAsGoogleAndroidProject) extension = ""; // 输出工程 | ||||
| 		    string outputDir = Path.GetFullPath($"{Application.dataPath }/../BuildOutput/Android"); | ||||
| 		    string outputDir = Path.GetFullPath($"{Application.dataPath }/../{OutputDirName}/Android"); | ||||
| 	        apkPath = $"{outputDir}/{Application.productName.Replace(" ","_")}_{symbolDefine}_{version}_{buildNumber}{extension}"; | ||||
| 	        if (!Directory.Exists(outputDir)) Directory.CreateDirectory(outputDir); | ||||
| 
 | ||||
|  | @ -136,10 +168,10 @@ namespace Guru.Editor | |||
|          | ||||
|         #region 构建 IOS 接口 | ||||
|          | ||||
|         public static void BuildIOS(AppBuildParam buildParam) | ||||
|         public static string BuildIOS(AppBuildParam buildParam) | ||||
| 	    { | ||||
| 	        //切换平台 | ||||
| 	        BuildSwitchPlatform(BuildTarget.iOS); | ||||
| 	        SwitchBuildPlatform(BuildTarget.iOS); | ||||
| 	        //打包通用设置 | ||||
| 	        ChangeBuildPlayerCommonSetting(buildParam, BuildTargetGroup.iOS); | ||||
| 	         | ||||
|  | @ -169,26 +201,28 @@ namespace Guru.Editor | |||
| 	        } | ||||
| 	         | ||||
| 		    //打包 | ||||
| 	        string xcodePath = Application.dataPath + "/../../xcode"; | ||||
| 	        if (Directory.Exists(xcodePath)) | ||||
| 	        string outputDir = Path.GetFullPath($"{Application.dataPath }/../{OutputDirName}/Xcode"); | ||||
| 	        if (Directory.Exists(outputDir)) | ||||
| 	        { | ||||
| 	            Directory.Delete(xcodePath, true); | ||||
| 	            Directory.Delete(outputDir, true); | ||||
| 	        } | ||||
| 
 | ||||
| 	        // 构建后打开路径 | ||||
| 	        try | ||||
| 	        { | ||||
| 		        BuildOptions opts = isDebug ? BuildOptions.Development : BuildOptions.None; | ||||
| 		        BuildPipeline.BuildPlayer(GetBuildScenes(), xcodePath, BuildTarget.iOS, BuildOptions.None); | ||||
| 		        BuildPipeline.BuildPlayer(GetBuildScenes(), outputDir, BuildTarget.iOS, BuildOptions.None); | ||||
| 		        if (buildParam.BuilderType == AppBuilderType.Editor) | ||||
| 		        { | ||||
| 			        Open(xcodePath); | ||||
| 			        Open(outputDir); | ||||
| 		        } | ||||
| 	        } | ||||
| 	        catch (Exception e) | ||||
| 	        { | ||||
| 		        Debug.LogError(e.Message); | ||||
| 	        } | ||||
| 
 | ||||
| 	        return outputDir; | ||||
| 	    }        | ||||
| 
 | ||||
|         #endregion | ||||
|  | @ -221,7 +255,7 @@ namespace Guru.Editor | |||
| 	    /// 平台切换 | ||||
| 	    /// </summary> | ||||
| 	    /// <param name="targetPlatform"></param> | ||||
| 	    private static void BuildSwitchPlatform(BuildTarget targetPlatform) | ||||
| 	    private static void SwitchBuildPlatform(BuildTarget targetPlatform) | ||||
| 	    { | ||||
| 		    if (EditorUserBuildSettings.activeBuildTarget != targetPlatform) | ||||
| 		    { | ||||
|  |  | |||
|  | @ -0,0 +1,328 @@ | |||
| 
 | ||||
| namespace Guru.Editor | ||||
| { | ||||
|     using System.IO; | ||||
|     using UnityEditor; | ||||
|     using UnityEngine; | ||||
|     using System; | ||||
|      | ||||
|     public class PgyerAPI | ||||
|     { | ||||
|         public const string Version = "1.0.0"; | ||||
| 
 | ||||
|         internal static readonly string DefaultBashPathWin = "C:\\Program Files\\Git\\bin\\bash.exe"; | ||||
|         internal static readonly string DefaultBashPathMac = "/bin/bash"; | ||||
|         internal static readonly string ShellFile = "pgyer_upload.sh"; | ||||
|         private static readonly string GuruAPIKey = "20a3d1106b802abbd84ec687eedf17eb"; | ||||
|         private static readonly string PgyerHost = "https://www.pgyer.com"; | ||||
|         internal static string WorkingDir => $"{Application.dataPath.Replace("Assets", "Library")}/guru_publish"; | ||||
| 
 | ||||
|         public static string GetDownloadUrl(string shortUrl) => $"{PgyerHost}/{shortUrl}"; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// 发布产品到蒲公英平台 | ||||
|         /// </summary> | ||||
|         /// <param name="packagePath"></param> | ||||
|         /// <param name="apiKey"></param> | ||||
|         /// <param name="bashPath"></param> | ||||
|         /// <param name="callback"></param> | ||||
|         public static void PublishToPgyer(string packagePath, string apiKey = "", string bashPath = "", | ||||
|             Action<string> callback = null) | ||||
|         { | ||||
|             if (File.Exists(packagePath)) | ||||
|             { | ||||
|                 Debug.Log($"=== START PUBLISH APP: {packagePath}"); | ||||
|                 CheckWorkingDir(); | ||||
|                 CallPublishShell(packagePath, apiKey, bashPath, callback); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private static void CheckWorkingDir() | ||||
|         { | ||||
|             if (!Directory.Exists(WorkingDir)) | ||||
|             { | ||||
|                 Directory.CreateDirectory(WorkingDir); | ||||
|             } | ||||
| 
 | ||||
|             var file = $"{WorkingDir}/{ShellFile}"; | ||||
|             if (!File.Exists(file)) | ||||
|             { | ||||
|                 var from = GetShellPath(); | ||||
|                 if (File.Exists(from)) | ||||
|                 { | ||||
|                     File.Copy(from, file); | ||||
| #if UNITY_EDITOR_OSX | ||||
|                     RunCmd("chmod", $"+x {file}", workpath: WorkingDir); | ||||
| #endif | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     Debug.LogError($"[Publisher] Source shell file not found :{from}"); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// 获取 CMD 命令路径 | ||||
|         /// </summary> | ||||
|         /// <returns></returns> | ||||
|         private static string GetShellPath() | ||||
|         { | ||||
|             var path = ""; | ||||
|             var guids = AssetDatabase.FindAssets($"{nameof(PgyerAPI)} t:script"); | ||||
|             if (guids.Length > 0) | ||||
|             { | ||||
|                 path = Path.Combine(Directory.GetParent(AssetDatabase.GUIDToAssetPath(guids[0])).FullName, ShellFile); | ||||
|                 return Path.GetFullPath(path); | ||||
|             } | ||||
| 
 | ||||
|             path = Path.GetFullPath( | ||||
|                 $"{Application.dataPath.Replace("Assets", "Packages")}/com.guru.unity.sdk.core/Editor/BuildTool/{ShellFile}"); | ||||
|             return path; | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         private static void RunCmd(string cmd, string args, Action<string> callback = null, string workpath = "") | ||||
|         { | ||||
|             System.Diagnostics.Process process = new System.Diagnostics.Process(); | ||||
|             process.StartInfo.FileName = cmd; | ||||
|             process.StartInfo.Arguments = args; | ||||
|             process.StartInfo.UseShellExecute = false; | ||||
|             process.StartInfo.RedirectStandardOutput = true; | ||||
|             process.StartInfo.RedirectStandardError = true; | ||||
|             process.StartInfo.CreateNoWindow = true; | ||||
|             if (!string.IsNullOrEmpty(workpath)) process.StartInfo.WorkingDirectory = workpath; | ||||
|             process.Start(); | ||||
|             string log = process.StandardOutput.ReadToEnd(); | ||||
|             callback?.Invoke(log); | ||||
|             process.Close(); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// 在 mac 下进行发布 | ||||
|         /// </summary> | ||||
|         /// <param name="packagePath"></param> | ||||
|         /// <param name="apiKey"></param> | ||||
|         /// <param name="bashPath"></param> | ||||
|         /// <param name="callback"></param> | ||||
|         private static void CallPublishShell(string packagePath, string apiKey = "", string bashPath = "", | ||||
|             Action<string> callback = null) | ||||
|         { | ||||
|             if (string.IsNullOrEmpty(bashPath)) | ||||
|             { | ||||
| #if UNITY_EDITOR_OSX | ||||
|                 bashPath = DefaultBashPathMac; | ||||
| #elif UNITY_EDITOR_WIN | ||||
|                 bashPath = DefaultBashPathWin.Replace("\\", "/"); | ||||
| #endif | ||||
|             } | ||||
| 
 | ||||
|             if (!File.Exists(bashPath)) | ||||
|             { | ||||
|                 string msg = $"Error: Bash file not found at path: {bashPath}! skip publishing!"; | ||||
|                 Debug.LogError(msg); | ||||
|                 callback?.Invoke(msg); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             packagePath = packagePath.Replace("\\", "/"); | ||||
|             if (string.IsNullOrEmpty(apiKey)) apiKey = GuruAPIKey; | ||||
|             var args = $"-c \"./{ShellFile} -k {apiKey} {packagePath}\""; | ||||
|             // Debug.Log(bashPath); | ||||
|             // Debug.Log(args); | ||||
|             // Debug.Log(WorkingDir); | ||||
|             RunCmd(bashPath, args, callback, WorkingDir); | ||||
|         } | ||||
|          | ||||
|     } | ||||
|      | ||||
|     /// <summary> | ||||
|     /// Guru 包体上传工具 | ||||
|     /// </summary> | ||||
|     public class GuruPublishHelper | ||||
|     { | ||||
|         // Check Env and Exe files | ||||
|         private static string EvnCheck() | ||||
|         { | ||||
|             if (!Directory.Exists(PgyerAPI.WorkingDir)) | ||||
|                 Directory.CreateDirectory(PgyerAPI.WorkingDir); | ||||
|              | ||||
|             // #1 --- read from cached file with available path | ||||
|             string bash_path = ""; | ||||
|             var envFile = $"{PgyerAPI.WorkingDir}/.env"; | ||||
|             if (File.Exists(envFile)) | ||||
|             { | ||||
|                 bash_path = File.ReadAllText(envFile); | ||||
|                 return bash_path; | ||||
|             } | ||||
| 
 | ||||
|             // #2 --- Try to find bash exe file from default path | ||||
|             bash_path = PgyerAPI.DefaultBashPathMac; | ||||
| #if UNITY_EDITOR_WIN | ||||
|             bash_path = PgyerAPI.DefaultBashPathWin; | ||||
| #endif | ||||
|             if (File.Exists(bash_path)) | ||||
|             { | ||||
|                 bash_path = bash_path.Replace("\\", "/"); | ||||
|                 File.WriteAllText(envFile, bash_path); | ||||
|                 return bash_path; | ||||
|             } | ||||
| 
 | ||||
|             // #3 --- Try to let user select bash exe file from disk | ||||
|             string title = "选择 bash 可执行文件"; | ||||
|             string despath = "/bin"; | ||||
|             string exts = "*"; | ||||
| 
 | ||||
| #if UNITY_EDITOR_WIN | ||||
|             despath = "C:\\Program Files\\"; | ||||
|             title = $"选择 bash 可执行文件, 例如: {despath}\\Git\\bin\\bash.exe"; | ||||
|             exts = "exe"; | ||||
| #endif | ||||
|             bash_path = EditorUtility.OpenFilePanel(title, despath, exts); | ||||
|             if (File.Exists(bash_path)) | ||||
|             { | ||||
|                 File.WriteAllText(envFile, bash_path.Replace("\\", "/")); | ||||
|             } | ||||
|             return bash_path; | ||||
|         } | ||||
|          | ||||
|          | ||||
|         [MenuItem("Guru/Publish/Android APK...")] | ||||
|         private static void EditorPublishAPK() | ||||
|         { | ||||
|             SelectAndPublish(); | ||||
|         } | ||||
|          | ||||
|         // [MenuItem("Guru/Publish/Publish Release AAB...")] | ||||
|         // private static void EditorPublishAAB() | ||||
|         // { | ||||
|         //     SelectAndPublish("aab"); | ||||
|         // } | ||||
| 
 | ||||
| 
 | ||||
|         public static void SelectAndPublish(string extension = "apk", string apiKey = "") | ||||
|         { | ||||
|             string bash_path = EvnCheck(); | ||||
|             if (string.IsNullOrEmpty(bash_path)) | ||||
|             { | ||||
|                 ShowDialog("找不到 Bash 执行文件", $"Bash文件不存在: {bash_path}!"); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             string file = EditorUtility.OpenFilePanel("选择包体", $"~/Downloads", extension); | ||||
| 
 | ||||
|             if (!File.Exists(file)) | ||||
|             { | ||||
|                 ShowDialog("找不到包体文件", $"包体文件不存在: {file}!"); | ||||
|                 return; | ||||
|             } | ||||
|              | ||||
|             PgyerAPI.PublishToPgyer(file, apiKey, bash_path, OnResponse); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Show system dialogs | ||||
|         /// </summary> | ||||
|         /// <param name="title"></param> | ||||
|         /// <param name="body"></param> | ||||
|         /// <param name="callback"></param> | ||||
|         /// <param name="cancelAction"></param> | ||||
|         /// <param name="okName"></param> | ||||
|         /// <param name="cancelName"></param> | ||||
|         private static void ShowDialog(string title, string body, Action callback = null, Action cancelAction = null, string okName= "OK", string cancelName = "") | ||||
|         { | ||||
|             if (EditorUtility.DisplayDialog(title, body, okName, cancelName)) | ||||
|             { | ||||
|                 callback?.Invoke(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 cancelAction?.Invoke(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// On pgyer response callback | ||||
|         /// </summary> | ||||
|         /// <param name="log"></param> | ||||
|         private static void OnResponse(string log) | ||||
|         { | ||||
|             var logPath = $"{PgyerAPI.WorkingDir}/log.txt"; | ||||
|             File.WriteAllText(logPath, log); | ||||
|              | ||||
|             bool success = log.Contains(ResponseObject.HeadTag); | ||||
| 
 | ||||
|             if (success) | ||||
|             { | ||||
|                 var json = log.Substring(log.IndexOf(ResponseObject.HeadTag, StringComparison.Ordinal)); | ||||
|                 var res = ResponseObject.Parse(json); | ||||
|                 if (res != null) | ||||
|                 { | ||||
|                     ShowDialog($"==== 上传成功 ({PgyerAPI.Version}) ====", $"包体 {res.BuildVersion()} ({res.BuildVersionCode()}) 上传成功!", () => | ||||
|                     { | ||||
|                         var url = PgyerAPI.GetDownloadUrl(res.ShortUrl()); | ||||
|                         Application.OpenURL(url); | ||||
|                     }); | ||||
| 
 | ||||
|                     return; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     success = false; | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             ShowDialog($"==== 上传失败 ({PgyerAPI.Version}) ====", $"上传文件失败, 查看详细日志: {logPath}", () => | ||||
|             { | ||||
| #if UNITY_EDITOR_OSX | ||||
|                 EditorUtility.RevealInFinder(PgyerAPI.WorkingDir); | ||||
|                 return; | ||||
| #endif | ||||
|                 Application.OpenURL(PgyerAPI.WorkingDir); | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     [Serializable] | ||||
|     internal class ResponseObject | ||||
|     { | ||||
|         public int code; | ||||
|         public string message; | ||||
|         public PublishData data; | ||||
|          | ||||
|         public static readonly string HeadTag = "{\"code\":"; | ||||
| 
 | ||||
|         public string BuildVersion() => data?.buildVersion ?? "0.0.0"; | ||||
|         public string BuildVersionCode() => data?.buildVersionNo ?? "0"; | ||||
|         public string ShortUrl() => data?.buildShortcutUrl ?? "#"; | ||||
|          | ||||
|          | ||||
|         public static bool IsValid(string json) | ||||
|         { | ||||
|             return json.Contains(HeadTag); | ||||
|         } | ||||
|          | ||||
|         public static ResponseObject Parse(string json) | ||||
|         { | ||||
|             if (string.IsNullOrEmpty(json)) return null; | ||||
|             if (!IsValid(json)) return null; | ||||
|             return JsonUtility.FromJson<ResponseObject>(json); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     [Serializable] | ||||
|     internal class PublishData | ||||
|     { | ||||
|         public string buildIdentifier; | ||||
|         public string buildQRCodeURL; | ||||
|         public string buildShortcutUrl; | ||||
|         public string buildName; | ||||
|         public string buildVersion; | ||||
|         public string buildVersionNo; | ||||
|         public string buildUpdated; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,3 @@ | |||
| fileFormatVersion: 2 | ||||
| guid: 615e8fb3101146048570e17d27bfbb9b | ||||
| timeCreated: 1709605527 | ||||
|  | @ -0,0 +1,147 @@ | |||
| #!/bin/bash | ||||
| # | ||||
| # 通过shell脚本来实现将本地app文件通过API上传到蒲公英 | ||||
| # https://www.pgyer.com/doc/view/api#fastUploadApp | ||||
| # | ||||
| 
 | ||||
| # Display log. 1=enable, 0=disable | ||||
| LOG_ENABLE=1 | ||||
| 
 | ||||
| printHelp() { | ||||
|     echo "Usage: $0 -k <api_key> [OPTION]... file" | ||||
|     echo "Upload iOS or Android app package file to PGYER." | ||||
|     echo "Example: $0 -k xxxxxxxxxxxxxxx /data/app.ipa" | ||||
|     echo "" | ||||
|     echo "Description:" | ||||
|     echo "  -k api_key                       (required) api key from PGYER" | ||||
|     echo "  -t buildInstallType              build install type, 1=public, 2=password, 3=invite" | ||||
|     echo "  -p buildPassword                 build password, required if buildInstallType=2" | ||||
|     echo "  -d buildUpdateDescription        build update description" | ||||
|     echo "  -e buildInstallDate              build install date, 1=buildInstallStartDate~buildInstallEndDate, 2=forever" | ||||
|     echo "  -s buildInstallStartDate         build install start date, format: yyyy-MM-dd" | ||||
|     echo "  -e buildInstallEndDate           build install end date, format: yyyy-MM-dd" | ||||
|     echo "  -c buildChannelShortcut          build channel shortcut" | ||||
|     echo "  -h help                          show this help" | ||||
|     echo "" | ||||
|     echo "Report bugs to: <https://github.com/PGYER/pgyer_api_example/issues>"  | ||||
|     echo "Project home page: <https://github.com/PGYER/pgyer_api_example>"  | ||||
|     exit 1 | ||||
| } | ||||
| 
 | ||||
| while getopts 'k:t:p:d:s:e:c:h' OPT; do | ||||
|     case $OPT in | ||||
|         k) api_key="$OPTARG";; | ||||
|         t) buildInstallType="$OPTARG";; | ||||
|         p) buildPassword="$OPTARG";; | ||||
|         d) buildUpdateDescription="$OPTARG";; | ||||
|         e) buildInstallDate="$OPTARG";; | ||||
|         s) buildInstallStartDate="$OPTARG";; | ||||
|         e) buildInstallEndDate="$OPTARG";; | ||||
|         c) buildChannelShortcut="$OPTARG";; | ||||
|         ?) printHelp;; | ||||
|     esac | ||||
| done | ||||
| 
 | ||||
| shift $(($OPTIND - 1)) | ||||
| readonly file=$1 | ||||
| 
 | ||||
| # check api_key exists | ||||
| if [ -z "$api_key" ]; then | ||||
|     echo "api_key is empty" | ||||
|     printHelp | ||||
| fi | ||||
| 
 | ||||
| # check file exists | ||||
| if [ ! -f "$file" ]; then | ||||
|     echo "file not exists" | ||||
|     printHelp | ||||
| fi | ||||
| 
 | ||||
| # check ext supported | ||||
| buildType=${file##*.} | ||||
| if [ "$buildType" != "ipa" ] && [ "$buildType" != "apk" ]; then | ||||
|     echo "file ext is not supported" | ||||
|     printHelp | ||||
| fi | ||||
| 
 | ||||
| # --------------------------------------------------------------- | ||||
| # functions | ||||
| # --------------------------------------------------------------- | ||||
| 
 | ||||
| log() { | ||||
|     [ $LOG_ENABLE -eq 1 ]  && echo "[$(date +'%Y-%m-%d %H:%M:%S')] $*" | ||||
| } | ||||
| 
 | ||||
| logTitle() { | ||||
|     log "-------------------------------- $* --------------------------------" | ||||
| } | ||||
| 
 | ||||
| execCommand() { | ||||
|     log "$@" | ||||
|     result=$(eval $@) | ||||
| } | ||||
| 
 | ||||
| # --------------------------------------------------------------- | ||||
| # 获取上传凭证 | ||||
| # --------------------------------------------------------------- | ||||
| 
 | ||||
| logTitle "获取凭证" | ||||
| 
 | ||||
| command="curl -s" | ||||
| [ -n "$api_key" ]                && command="${command} --form-string '_api_key=${api_key}'"; | ||||
| [ -n "$buildType" ]              && command="${command} --form-string 'buildType=${buildType}'"; | ||||
| [ -n "$buildInstallType" ]       && command="${command} --form-string 'buildInstallType=${buildInstallType}'"; | ||||
| [ -n "$buildPassword" ]          && command="${command} --form-string 'buildPassword=${buildPassword}'"; | ||||
| [ -n "$buildUpdateDescription" ] && command="${command} --form-string $'buildUpdateDescription=${buildUpdateDescription}'"; | ||||
| [ -n "$buildInstallDate" ]       && command="${command} --form-string 'buildInstallDate=${buildInstallDate}'"; | ||||
| [ -n "$buildInstallStartDate" ]  && command="${command} --form-string 'buildInstallStartDate=${buildInstallStartDate}'"; | ||||
| [ -n "$buildInstallEndDate" ]    && command="${command} --form-string 'buildInstallEndDate=${buildInstallEndDate}'"; | ||||
| [ -n "$buildChannelShortcut" ]   && command="${command} --form-string 'buildChannelShortcut=${buildChannelShortcut}'"; | ||||
| command="${command} http://www.pgyer.com/apiv2/app/getCOSToken"; | ||||
| execCommand $command | ||||
| 
 | ||||
| [[ "${result}" =~ \"endpoint\":\"([\:\_\.\/\\A-Za-z0-9\-]+)\" ]] && endpoint=`echo ${BASH_REMATCH[1]} | sed 's!\\\/!/!g'` | ||||
| [[ "${result}" =~ \"key\":\"([\.a-z0-9]+)\" ]] && key=`echo ${BASH_REMATCH[1]}` | ||||
| [[ "${result}" =~ \"signature\":\"([\=\&\_\;A-Za-z0-9\-]+)\" ]] && signature=`echo ${BASH_REMATCH[1]}` | ||||
| [[ "${result}" =~ \"x-cos-security-token\":\"([\_A-Za-z0-9\-]+)\" ]] && x_cos_security_token=`echo ${BASH_REMATCH[1]}` | ||||
| 
 | ||||
| if [ -z "$key" ] || [ -z "$signature" ] || [ -z "$x_cos_security_token" ] || [ -z "$endpoint" ]; then | ||||
|     log "get upload token failed" | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| # --------------------------------------------------------------- | ||||
| # 上传文件 | ||||
| # --------------------------------------------------------------- | ||||
| 
 | ||||
| logTitle "上传文件" | ||||
| 
 | ||||
| file_name=${file##*/} | ||||
| 
 | ||||
| execCommand "curl -s -o /dev/null -w '%{http_code}' \ | ||||
| --form-string 'key=${key}' \ | ||||
| --form-string 'signature=${signature}' \ | ||||
| --form-string 'x-cos-security-token=${x_cos_security_token}' \ | ||||
| --form-string 'x-cos-meta-file-name=${file_name}' \ | ||||
| -F 'file=@${file}' ${endpoint}" | ||||
| if [ $result -ne 204 ]; then # if http code != 204, upload failed | ||||
|     log "Upload failed" | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| # --------------------------------------------------------------- | ||||
| # 检查结果 | ||||
| # --------------------------------------------------------------- | ||||
| 
 | ||||
| logTitle "检查结果" | ||||
| 
 | ||||
| for i in {1..60}; do | ||||
|     execCommand "curl -s http://www.pgyer.com/apiv2/app/buildInfo?_api_key=${api_key}\&buildKey=${key}" | ||||
|     [[ "${result}" =~ \"code\":([0-9]+) ]] && code=`echo ${BASH_REMATCH[1]}` | ||||
|     if [ $code -eq 0 ]; then | ||||
|         echo $result | ||||
|         break | ||||
|     else | ||||
|         sleep 1 | ||||
|     fi | ||||
| done | ||||
|  | @ -0,0 +1,7 @@ | |||
| fileFormatVersion: 2 | ||||
| guid: 64be73b7342084dd583da03a6730370d | ||||
| DefaultImporter: | ||||
|   externalObjects: {} | ||||
|   userData:  | ||||
|   assetBundleName:  | ||||
|   assetBundleVariant:  | ||||
							
								
								
									
										12
									
								
								README.md
								
								
								
								
							
							
						
						
									
										12
									
								
								README.md
								
								
								
								
							|  | @ -1,5 +1,17 @@ | |||
| # Guru SDK Core | ||||
| 
 | ||||
| **Version 2.2.1** | ||||
| 
 | ||||
| - 更新 Firebase -> Unity 11.7.0  |  FirebaseSDK 10.20.0 (iOS 10.22.0) | ||||
| - 添加 GooglePlay DMA 合规逻辑 (2024 年 3 月 6 日之前升级即可) | ||||
| - 广告渠道 Inmobi 升级 双端版本: Android 10.6.3.0 ,  iOS 10.6.0.0 | ||||
| - 广告渠道 Pubmatic iOS 平台版本指定为 3.2 修复打包报错的问题 | ||||
| - 更新内核的 JsonParser 解析器为 JsonConvert | ||||
| - fix: 修复配置导出功能解析报错的问题 | ||||
| - fix: 修复 ABTestManager 的解析错误. | ||||
| - fix: 修复 Tch 打点在不满足 0.01 的情况下补偿的逻辑 | ||||
| - fix: 修复 GuruConsent 在 iOS 上返回 Purpose 乱码的解析问题, 添加了 TCF 映射规则. | ||||
| 
 | ||||
| 
 | ||||
| **Version 2.1.0** | ||||
| 
 | ||||
|  |  | |||
|  | @ -90,7 +90,7 @@ namespace Guru | |||
|             AdjustThirdPartySharing adjustThirdPartySharing = new AdjustThirdPartySharing(null); | ||||
|             adjustThirdPartySharing.addGranularOption("google_dma", "eea", "1"); | ||||
|             adjustThirdPartySharing.addGranularOption("google_dma", "ad_personalization", $"{result[2]}"); | ||||
|             adjustThirdPartySharing.addGranularOption("google_dma", "ad_user_data", $"{result[3]}"); | ||||
|             adjustThirdPartySharing.addGranularOption("google_dma", "ad_user_data", $"{result[3]}");  // From Haoyi's advice we don't give the value so Adjust will still receive the data as a trick. | ||||
|             Adjust.trackThirdPartySharing(adjustThirdPartySharing); | ||||
|              | ||||
|             //----------- Guru DMA report --------------- | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue