From fa06ab3f8792b066fc157c9c04012206c0addd80 Mon Sep 17 00:00:00 2001 From: huyufei Date: Wed, 6 Mar 2024 17:43:55 +0800 Subject: [PATCH] =?UTF-8?q?update:=20=E6=9B=B4=E6=96=B0=20ReadMe=20?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Editor/BuildTool/AppBuildParam.cs | 19 +- Editor/BuildTool/AppBuilder.cs | 54 ++- Editor/BuildTool/GuruPublishHelper.cs | 328 ++++++++++++++++++ Editor/BuildTool/GuruPublishHelper.cs.meta | 3 + Editor/BuildTool/pgyer_upload.sh | 147 ++++++++ Editor/BuildTool/pgyer_upload.sh.meta | 7 + README.md | 12 + .../Runtime/Script/Consent/GoogleDMAHelper.cs | 2 +- 8 files changed, 555 insertions(+), 17 deletions(-) create mode 100644 Editor/BuildTool/GuruPublishHelper.cs create mode 100644 Editor/BuildTool/GuruPublishHelper.cs.meta create mode 100755 Editor/BuildTool/pgyer_upload.sh create mode 100644 Editor/BuildTool/pgyer_upload.sh.meta diff --git a/Editor/BuildTool/AppBuildParam.cs b/Editor/BuildTool/AppBuildParam.cs index 3a0e7c0..b82d1a7 100644 --- a/Editor/BuildTool/AppBuildParam.cs +++ b/Editor/BuildTool/AppBuildParam.cs @@ -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 /// /// /// - 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); } } diff --git a/Editor/BuildTool/AppBuilder.cs b/Editor/BuildTool/AppBuilder.cs index 67d1ac2..398b7f9 100644 --- a/Editor/BuildTool/AppBuilder.cs +++ b/Editor/BuildTool/AppBuilder.cs @@ -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 构建接口 + + /// + /// 直接调用 Build 接口 + /// + /// + /// + 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($" Unsupported build target: {buildParam.TargetName}. Skip build..."); + 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 /// 平台切换 /// /// - private static void BuildSwitchPlatform(BuildTarget targetPlatform) + private static void SwitchBuildPlatform(BuildTarget targetPlatform) { if (EditorUserBuildSettings.activeBuildTarget != targetPlatform) { diff --git a/Editor/BuildTool/GuruPublishHelper.cs b/Editor/BuildTool/GuruPublishHelper.cs new file mode 100644 index 0000000..22b2ac4 --- /dev/null +++ b/Editor/BuildTool/GuruPublishHelper.cs @@ -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}"; + + /// + /// 发布产品到蒲公英平台 + /// + /// + /// + /// + /// + public static void PublishToPgyer(string packagePath, string apiKey = "", string bashPath = "", + Action 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}"); + } + } + } + + + + /// + /// 获取 CMD 命令路径 + /// + /// + 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 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(); + } + + /// + /// 在 mac 下进行发布 + /// + /// + /// + /// + /// + private static void CallPublishShell(string packagePath, string apiKey = "", string bashPath = "", + Action 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); + } + + } + + /// + /// Guru 包体上传工具 + /// + 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); + } + + /// + /// Show system dialogs + /// + /// + /// + /// + /// + /// + /// + 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(); + } + } + + /// + /// On pgyer response callback + /// + /// + 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(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; + } +} \ No newline at end of file diff --git a/Editor/BuildTool/GuruPublishHelper.cs.meta b/Editor/BuildTool/GuruPublishHelper.cs.meta new file mode 100644 index 0000000..c1debae --- /dev/null +++ b/Editor/BuildTool/GuruPublishHelper.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 615e8fb3101146048570e17d27bfbb9b +timeCreated: 1709605527 \ No newline at end of file diff --git a/Editor/BuildTool/pgyer_upload.sh b/Editor/BuildTool/pgyer_upload.sh new file mode 100755 index 0000000..62c46fa --- /dev/null +++ b/Editor/BuildTool/pgyer_upload.sh @@ -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 [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: " + echo "Project home page: " + 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 diff --git a/Editor/BuildTool/pgyer_upload.sh.meta b/Editor/BuildTool/pgyer_upload.sh.meta new file mode 100644 index 0000000..effa92a --- /dev/null +++ b/Editor/BuildTool/pgyer_upload.sh.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 64be73b7342084dd583da03a6730370d +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/README.md b/README.md index e5621ae..456f4ce 100644 --- a/README.md +++ b/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** diff --git a/Runtime/GuruConsent/Runtime/Script/Consent/GoogleDMAHelper.cs b/Runtime/GuruConsent/Runtime/Script/Consent/GoogleDMAHelper.cs index 51ab9db..775dbe4 100644 --- a/Runtime/GuruConsent/Runtime/Script/Consent/GoogleDMAHelper.cs +++ b/Runtime/GuruConsent/Runtime/Script/Consent/GoogleDMAHelper.cs @@ -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 ---------------