diff --git a/Assets/EFSDK/AutoSetEFSdk.cs b/Assets/EFSDK/AutoSetEFSdk.cs new file mode 100644 index 0000000..8aacbe7 --- /dev/null +++ b/Assets/EFSDK/AutoSetEFSdk.cs @@ -0,0 +1,33 @@ +using UnityEngine; + +namespace EFSDK +{ + public static class AutoSetEFSdk + { + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + public static void SetupCommunicationObject() + { + try + { + GameObject communicationObject = new GameObject("EFSdkAndroid"); + if (communicationObject != null) + { + EFSdkAndroid communicationComponent = communicationObject.AddComponent(); + if (communicationComponent == null) + { + Debug.LogError("Failed to add EFSdkAndroid component to the GameObject."); + } + Object.DontDestroyOnLoad(communicationObject); + } + else + { + Debug.LogError("Failed to create the EFSdkAndroid GameObject."); + } + } + catch (System.Exception e) + { + Debug.LogError($"An error occurred while setting up the communication object: {e.Message}"); + } + } + } +} \ No newline at end of file diff --git a/Assets/EFSDK/AutoSetEFSdk.cs.meta b/Assets/EFSDK/AutoSetEFSdk.cs.meta new file mode 100644 index 0000000..5e19232 --- /dev/null +++ b/Assets/EFSDK/AutoSetEFSdk.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9937d38cb2014e1e94087f6216eacd62 +timeCreated: 1742202739 \ No newline at end of file diff --git a/Assets/EFSDK/EFSdk.cs b/Assets/EFSDK/EFSdk.cs new file mode 100644 index 0000000..d467013 --- /dev/null +++ b/Assets/EFSDK/EFSdk.cs @@ -0,0 +1,433 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace EFSDK +{ + /// + /// TKG Native SDK Android platform interface call + /// + public class EFSdk + { + private static EFSdk _mEfSdk; + private static string mappingInfo = @"{""items"":[{""key"":""_sdk_float_balloon.png"",""value"":""aoa38ay.png""}]}"; + + + public static EFSdk get() + { + if (_mEfSdk == null) + { + _mEfSdk = new EFSdk(); + } + + return _mEfSdk; + } + + + private AndroidJavaObject jo; + + public EFSdk() + { + // java interface class + using (AndroidJavaClass jc = new AndroidJavaClass("com.earn.push._SDK")) + { + jo = jc.GetStatic("INSTANCE"); + } + } + + private T SDKCall(string _method, params object[] _param) + { + try + { + return jo.Call(_method, _param); + } + catch (Exception e) + { + Debug.LogError(e); + } + + return default(T); + } + + private void SDKCall(string _method, params object[] _param) + { + try + { + jo.Call(_method, _param); + } + catch (Exception e) + { + Debug.LogError(e); + } + } + + public enum ActionType + { + COIN_CLICK, //点击金币 + BALLOON_CLICK, //点击气球 + COIN_SHOW, //金币展示出来了 + BOX_SHOW, //气球/宝箱展示出来了 + GAM_LOAD_SUCC, //GAM页面加载成功 + ON_RESUME, //游戏可见时回调, + // CAN_GOBACK, //游戏可见时回调, + } + + public Action ActionCallback; + public Action> ActionSDKEventCallback; + public Action HdH5ImpressionAction; + public Action mCanGobackAction; + public Action mReqNotifyPermissionAction; + + /// + /// 在Init方法之后调用这个方法,设置SDK上报事件回调, 将SDK传过来的事件上报到Firebase,数数等 + /// + /// + /// 事件ID,事件属性 + /// + public void SetSDKEventCallback(Action> eventKeyDict) + { + ActionSDKEventCallback = eventKeyDict; + } + + /// + /// 互动广告展示回调,此时可以计算上报互动广告展示次数和收益 + /// + /// string 是互动广告的url + public void SetHdH5ImpressionCallback(Action callback) + { + HdH5ImpressionAction = callback; + } + + + /// + /// 初始化 + /// + /// ActionType 回调类型 ; string msg + public void Init(Action actionCallbvack) + { + ActionCallback = actionCallbvack; + SDKInit(); + } + + private void SDKInit() + { + // SDKCall("init"); + ActionCallback?.Invoke(ActionType.GAM_LOAD_SUCC, string.Empty); + } + + /// + /// 展示WebView + /// + /// 标签id + /// 网址 + /// + /// + public void ShowWebView(int id, string url, RectTransform pRect, Camera pCam = null) + { + Vector3[] tWorldCorners = new Vector3[4]; + pRect.GetWorldCorners(tWorldCorners); + Vector2 tTopLeft = RectTransformUtility.WorldToScreenPoint(pCam, tWorldCorners[1]); + Vector2 tBottomRight = RectTransformUtility.WorldToScreenPoint(pCam, tWorldCorners[3]); + int tWidth = (int)Mathf.Abs(tBottomRight.x - tTopLeft.x); + int tHeight = (int)Mathf.Abs(tBottomRight.y - tTopLeft.y); + SDKCall("showWebViewToActivity", id, url, (int)tTopLeft.x, (int)(Screen.height - tTopLeft.y), tWidth, + tHeight); + } + + /// + /// 移除所有原生View, 回到游戏时调用 + /// + /// + public void RemoveAll() + { + SDKCall("removeAll"); + } + + /// + /// 刷新当前页面 + /// + /// + public void Refresh() + { + SDKCall("refresh"); + } + + /// + /// 回上一页 + /// + /// + public void GoBack() + { + SDKCall("goBack"); + } + + /// + /// 回首页 + /// + /// + public void GoHome() + { + SDKCall("goHome"); + } + + /// + /// 是否手动控制漂浮道具显示/隐藏 + /// SDK内默认当H5页面加载完成后自动显示漂浮道具 + /// + /// true: 自动显示/隐藏道具 false: 游戏主动控制道具显示/隐藏 + /// + public void AutoShowFloat(bool autoShow) + { + SDKCall("autoShowFloat", autoShow); + } + + /// + /// 飘金币 + /// + /// + /// + public void ShowFloatCoin(int id) + { + SDKCall("showFloatCoin", id); + } + + /// + /// 飘金币 + /// + /// + /// 悬浮金币按钮的图片资源,传字符串 0 或 1 0:金币图 1:红点宝箱图 + /// + public void ShowFloatCoin(int id, String res) + { + SDKCall("showFloatCoin", id, res); + } + + /// + /// 设置悬浮金币按钮的图片资源 + /// + /// 传字符串 0 或 1 0:金币图 1:红点宝箱图 + public void SetFloatCoinRes(String res) + { + SDKCall("setFloatCoinRes", res); + } + + /// + /// 隐藏金币 + /// + /// + public void HideFloatCoin() + { + SDKCall("hideFloatCoin"); + } + + /// + /// 飘气球 + /// + /// + /// + /// + /// + /// + public void ShowBalloon(int startId, int endId, int fly_first_time, int fly_gap_time) + { + SDKCall("showBalloon", startId, endId, fly_first_time, fly_gap_time); + } + + /// + /// 隐藏气球 + /// + /// + public void HideBalloon() + { + SDKCall("hideBalloon"); + } + + /// + /// + /// + /// + public void ShowToast(string message) + { + SDKCall("showToast", message); + } + + /// + /// 判断当前网页是否还能返回上一页, true:可以返回,此时页面不在首页 false: 不能返回了,当前页面就在首页 + /// + public void CanGoback(Action canGobackAction) + { + mCanGobackAction = canGobackAction; + SDKCall("canGoback"); + } + + #region 推送通知 + + /// + /// 满足条件:未领取 R$0.1 的 买量用户, 调用这个方法 + /// + public void SubscribeUnclaimed01() + { + SDKCall("subscribeUnclaimed01"); + } + + /// + /// 不满足条件:未领取 R$0.1 的 买量用户, 调用这个方法 + /// + public void UnSubscribeUnclaimed01() + { + SDKCall("unSubscribeUnclaimed01"); + } + + /// + // 满足条件: 在排队中 且 当日R$1 未领取 的买量用户, 调用这个方法 + /// + public void SubscribePending1() + { + SDKCall("subscribePending1"); + } + + /// + /// 不满足条件: 在排队中 且 当日R$1 未领取 的买量用户, 调用这个方法 + /// + public void UnSubscribePending1() + { + SDKCall("unSubscribePending1"); + } + + /// + /// 订阅Firebase推送主题 + /// + /// 主题名称 + public void SubscribeToTopic(string topic) + { + SDKCall("subscribeToTopic", topic); + } + + /// + /// 取消订阅Firebase推送主题 + /// + /// 主题名称 + public void UnSubscribeToTopic(string topic) + { + SDKCall("UnSubscribeToTopic", topic); + } + + + /// + /// 向SDK上报当前金币总数,每次金币变化都要调用一次 + /// + /// + public void SendTotalGold2SDK(int totalGold) + { + SDKCall("setGoldNum", totalGold.ToString()); + } + + /// + /// 向SDK上报当前要提现的现金额,每次变化都要调用一次 + /// + /// + public void SendCashNum2SDK(double cashNum) + { + SDKCall("setCashNum", cashNum.ToString("0.00")); + } + + /// + /// 向SDK上报 游戏名字(当前语言的),每次语言变化都上报 + /// + /// + public void SetGameName(string gameName) + { + SDKCall("setGameName", gameName); + } + + // /// + // /// 设置推送 消息通知 的文案 + // /// + // /// + // public void SetCommPushMessage(string message) + // { + // SDKCall("setCommPushMessage", message); + // } + + /// + /// 设置当前游戏语言是否是 西班牙语 + /// + /// + /// 西班牙语传 true, 其他的都传 false + public void SetCurrLang(bool isEs) + { + SDKCall("setCurrLang", isEs); + } + + /// + /// 获取当前是否有通知权限 + /// + public bool HasNotifyPermission() + { + return SDKCall("hasNotifyPermission"); + } + + /// + /// 请求获取通知权限 + /// + public void ReqNotifyPermission() + { + SDKCall("reqNotifyPermission"); + } + + /// + /// 请求获取通知权限 + /// 授权弹窗关闭回调 bool:表示用户是否允许了权限 true:有权限 false:无权限 + /// + public void ReqNotifyPermission(Action action) + { + mReqNotifyPermissionAction = action; + SDKCall("reqNotifyPermission"); + } + + /// + /// 设置推送开关, SDK默认关闭通知 + /// + /// + public void SetPushSwitch(bool isOpen) + { + SDKCall("pushSwitch", isOpen); + } + + /// + /// 消息类通知弹出间隔设置为60秒(在线参数控制)-Key: messagenotif Value:60 + /// + /// + public void SetPushMessagenotif(int timeSeconds) + { + SDKCall("setPushMessagenotif", timeSeconds); + } + + /// + /// 持续性通知在进入游戏时弹出的时间间隔设置为300秒(在线参数控制 )-Key:persistentnotif Value:300 + /// + /// + public void SetPushPersistentnotif(int timeSeconds) + { + SDKCall("setPushPersistentnotif", timeSeconds); + } + + + /// + /// 每次回调游戏的onResume的时候都调用一次,获取游戏要跳转的页面 + /// + /// + /// 0 不需要进行任何跳转 + /// 1 进行游戏主页 + /// 2 进入游戏的金币提现界面 + /// 3 进入对应小游戏1界面 + /// 4 进入对应小游戏2界面 + /// + public int GetJumpPage() + { + return SDKCall("getJumpPage"); + } + + #endregion + } +} diff --git a/Assets/EFSDK/EFSdk.cs.meta b/Assets/EFSDK/EFSdk.cs.meta new file mode 100644 index 0000000..8d8c165 --- /dev/null +++ b/Assets/EFSDK/EFSdk.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3cf9c70ade0a42e08c9ea06733912dd2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/EFSDK/EFSdkAndroid.cs b/Assets/EFSDK/EFSdkAndroid.cs new file mode 100644 index 0000000..c15fc56 --- /dev/null +++ b/Assets/EFSDK/EFSdkAndroid.cs @@ -0,0 +1,109 @@ +using System.Collections.Generic; + +namespace EFSDK +{ + using UnityEngine; + + public class EFSdkAndroid : MonoBehaviour + { + private string COIN_CLICK = "coin_click"; + private string BALLOON_CLICK = "balloon_click"; + private string Coin_Show = "Coin_Show"; + private string Box_Show = "Box_Show"; + private string Gam_Load_Succ = "Gam_Load_Succ"; + private string On_Resume = "onResume"; + private string Can_Goback = "canGoback"; + + public void OnReceiverAnd(string message) + { + WLoom.QueueOnMainThread(_ => + { + Debug.Log("Received message from Android: " + message); + if (message.Contains(On_Resume)) + { + EFSdk.get().ActionCallback?.Invoke(EFSdk.ActionType.ON_RESUME, message); + } + if (message.Contains(Can_Goback)) + { + EFSdk.get().mCanGobackAction?.Invoke(bool.Parse(message.Split('#')[1])); + } + + if (BALLOON_CLICK.Equals(message)) + { + //点击气球 + EFSdk.get().ActionCallback?.Invoke(EFSdk.ActionType.BALLOON_CLICK, message); + } + + if (Coin_Show.Equals(message)) + { + //金币展示出来了 + EFSdk.get().ActionCallback?.Invoke(EFSdk.ActionType.COIN_SHOW, message); + } + if (COIN_CLICK.Equals(message)) + { + //金币点击 + EFSdk.get().ActionCallback?.Invoke(EFSdk.ActionType.COIN_CLICK, message); + } + + if (Box_Show.Equals(message)) + { + //宝箱展示出来了 + EFSdk.get().ActionCallback?.Invoke(EFSdk.ActionType.BOX_SHOW, message); + } + + if (message.Contains(Gam_Load_Succ)) + { + //GAM页面加载成功 Gam_Load_Succ@id + string[] parts = message.Split('@'); + EFSdk.get().ActionCallback?.Invoke(EFSdk.ActionType.GAM_LOAD_SUCC, parts[1]); + } + + if (message.StartsWith("reqNotifyPermission#")) + { + string[] flag = message.Split('#'); + EFSdk.get().mReqNotifyPermissionAction?.Invoke(flag[1].Equals("1")); + } + + if (message.StartsWith("Event#")) + { + string[] eventKeys = message.Split('#'); + if (eventKeys.Length > 0) + { + if (message.Contains("hd_h5_impression")) + { + //互动广告展示 + string url = eventKeys[2]; + EFSdk.get().HdH5ImpressionAction?.Invoke(url); + } + else if (eventKeys.Length == 2) + { + // 只有一个事件key + string eventKey = eventKeys[1]; + EFSdk.get().ActionSDKEventCallback?.Invoke(eventKey, null); + } + else if (eventKeys.Length == 3) + { + // key-value事件 + string eventKey = eventKeys[1]; + string value = eventKeys[2]; + } + else + { + //多属性事件 + string eventKey = eventKeys[1]; + Dictionary attrs = new Dictionary(); + for (int i = 2; i < eventKeys.Length - 1; i += 2) + { + string key = eventKeys[i]; + string value = eventKeys[i + 1]; + attrs[key] = value; + } + + EFSdk.get().ActionSDKEventCallback?.Invoke(eventKey, attrs); + } + } + } + }, ""); + } + } +} \ No newline at end of file diff --git a/Assets/EFSDK/EFSdkAndroid.cs.meta b/Assets/EFSDK/EFSdkAndroid.cs.meta new file mode 100644 index 0000000..c8b9b28 --- /dev/null +++ b/Assets/EFSDK/EFSdkAndroid.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 40a70c7c94e6494d947902b87c809b30 +timeCreated: 1742202547 \ No newline at end of file diff --git a/Assets/EFSDK/Editor.meta b/Assets/EFSDK/Editor.meta new file mode 100644 index 0000000..9e42853 --- /dev/null +++ b/Assets/EFSDK/Editor.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e4d0b212325940748840950d8c400f9f +timeCreated: 1756628120 \ No newline at end of file diff --git a/Assets/EFSDK/Editor/AndroidResAarBuilder.cs b/Assets/EFSDK/Editor/AndroidResAarBuilder.cs new file mode 100644 index 0000000..76f4464 --- /dev/null +++ b/Assets/EFSDK/Editor/AndroidResAarBuilder.cs @@ -0,0 +1,162 @@ +using UnityEngine; +using UnityEditor; +using System.IO; +using System.Collections.Generic; +using IOCompression = System.IO.Compression; + +namespace EFSDK +{ + public class AndroidResAarBuilder + { + private static readonly string ResDir = "Assets/StreamingAssets/Android/res"; + private static readonly string OutputDir = "Assets/Plugins/Android"; + private static readonly string TempDir = "Temp/AndroidResAar"; + private static readonly string EFSdk_FILE = "Assets/EFSDK/EFSdk.cs"; + + [MenuItem("EFSDK/Build Android Res AAR")] + public static void BuildAAR() + { + if (!Directory.Exists(ResDir)) + { + Debug.LogError($"Res folder not found: {ResDir}"); + return; + } + + // 清理临时目录 + if (Directory.Exists(TempDir)) Directory.Delete(TempDir, true); + Directory.CreateDirectory(TempDir); + + // 复制资源并重命名 + CopyAndRenameFiles(ResDir, TempDir, out Dictionary mapping); + string manifestPath = Path.Combine(TempDir, "AndroidManifest.xml"); + File.WriteAllText(manifestPath, + @" + + "); + + // 打包 AAR + string aarPath = Path.Combine(OutputDir, "efsdk_res.aar"); + if (!Directory.Exists(OutputDir)) Directory.CreateDirectory(OutputDir); + if (File.Exists(aarPath)) File.Delete(aarPath); + + IOCompression.ZipFile.CreateFromDirectory(TempDir, aarPath, IOCompression.CompressionLevel.Optimal, false); + Debug.Log($"✅ AAR built: {aarPath}"); + + // 生成压缩 JSON (key 只保留文件名) + Dictionary simpleMapping = new Dictionary(); + foreach (var kv in mapping) + { + string fileName = Path.GetFileName(kv.Key); + simpleMapping[fileName] = kv.Value; + } + + string mappingJson = GenerateMappingJson(mapping); + // 更新 mappingInfo + UpdateMappingInEFSdk_LineByLine(mappingJson); + // 映射文件 + string mappingPath = Path.Combine(TempDir, "res_mapping.json"); + File.WriteAllText(mappingPath, mappingJson); + + // 清理临时目录 + Directory.Delete(TempDir, true); + AssetDatabase.Refresh(); + } + + private static void CopyAndRenameFiles(string srcDir, string dstDir, out Dictionary mapping) + { + mapping = new Dictionary(); + foreach (var filePath in Directory.GetFiles(srcDir, "*", SearchOption.AllDirectories)) + { + if (filePath.EndsWith(".meta")) continue; + + string relativePath = filePath.Substring(srcDir.Length + 1).Replace("\\", "/"); + string newName = GenerateRandomAndroidName(Path.GetExtension(filePath)); + mapping[Path.GetFileName(filePath)] = newName; + + string dstPath = Path.Combine(dstDir, newName); + string dstFolder = Path.GetDirectoryName(dstPath); + if (!Directory.Exists(dstFolder)) Directory.CreateDirectory(dstFolder); + + File.Copy(filePath, dstPath); + } + + foreach (var dir in Directory.GetDirectories(srcDir, "*", SearchOption.AllDirectories)) + { + string relativeDir = dir.Substring(srcDir.Length + 1); + string dstSubDir = Path.Combine(dstDir, relativeDir); + if (!Directory.Exists(dstSubDir)) Directory.CreateDirectory(dstSubDir); + } + + Debug.Log("✅ Files copied and renamed"); + } + private static string GenerateMappingJson(Dictionary mapping) + { + var items = new List(); + foreach (var kv in mapping) + { + items.Add(new MappingItem { key = kv.Key, value = kv.Value }); + } + MappingListWrapper wrapper = new MappingListWrapper { items = items }; + return JsonUtility.ToJson(wrapper, false); + } + + [System.Serializable] + private class MappingItem { public string key; public string value; } + + [System.Serializable] + private class MappingListWrapper { public List items; } + private static string GenerateRandomAndroidName(string ext) + { + int len = UnityEngine.Random.Range(6, 12); + string chars = "abcdefghijklmnopqrstuvwxyz0123456789"; + string name = ""; + for (int i = 0; i < len; i++) + { + name += chars[UnityEngine.Random.Range(0, chars.Length)]; + } + + if (!char.IsLetter(name[0])) name = "a" + name.Substring(1); + + return name + ext; + } + + private static void UpdateMappingInEFSdk_LineByLine(string mappingJson) + { + if (!File.Exists(EFSdk_FILE)) + { + Debug.LogError($"EFSdk.cs not found: {EFSdk_FILE}"); + return; + } + + string[] lines = File.ReadAllLines(EFSdk_FILE); + bool updated = false; + for (int i = 0; i < lines.Length; i++) + { + if (lines[i].Contains("mappingInfo")) + { + lines[i] = $" private static string mappingInfo = @\"{mappingJson.Replace("\"", "\"\"")}\";"; + updated = true; + break; // 找到第一行就替换,防止重复 + } + } + + if (!updated) + { + // 如果没有找到 mappingInfo 行,则在 _mEfSdk 后插入 + for (int i = 0; i < lines.Length; i++) + { + if (lines[i].Contains("private static EFSdk _mEfSdk")) + { + lines[i] += $"\n private static string mappingInfo = @\"{mappingJson.Replace("\"", "\"\"")}\";"; + updated = true; + break; + } + } + } + + File.WriteAllLines(EFSdk_FILE, lines); + Debug.Log("✅ mappingInfo updated in EFSdk.cs (line-by-line)"); + } + } +} \ No newline at end of file diff --git a/Assets/EFSDK/Editor/AndroidResAarBuilder.cs.meta b/Assets/EFSDK/Editor/AndroidResAarBuilder.cs.meta new file mode 100644 index 0000000..fa219a9 --- /dev/null +++ b/Assets/EFSDK/Editor/AndroidResAarBuilder.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ff87df6ca3d9445e98929bb62fb10a15 +timeCreated: 1756694090 \ No newline at end of file diff --git a/Assets/EFSDK/Editor/Dependencies.xml b/Assets/EFSDK/Editor/Dependencies.xml new file mode 100644 index 0000000..a93bead --- /dev/null +++ b/Assets/EFSDK/Editor/Dependencies.xml @@ -0,0 +1,13 @@ + + + + + https://repo.dgtverse.cn/repository/maven-public/ + https://android-sdk.is.com/ + https://dl-maven-android.mintegral.com/repository/mbridge_android_sdk_oversea + https://artifact.bytedance.com/repository/pangle/ + + + + + \ No newline at end of file diff --git a/Assets/EFSDK/Editor/Dependencies.xml.meta b/Assets/EFSDK/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..97b4abc --- /dev/null +++ b/Assets/EFSDK/Editor/Dependencies.xml.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 61484455ad49448f839552619a42625a +timeCreated: 1756628147 \ No newline at end of file diff --git a/Assets/EFSDK/Editor/DynamicApplicationClass.cs b/Assets/EFSDK/Editor/DynamicApplicationClass.cs new file mode 100644 index 0000000..ce5e6a7 --- /dev/null +++ b/Assets/EFSDK/Editor/DynamicApplicationClass.cs @@ -0,0 +1,181 @@ +using System.Collections.Generic; +using System.IO; +using Unity.Plastic.Newtonsoft.Json.Linq; +using UnityEditor.Android; +using UnityEngine; + +public class DynamicApplicationClass : IPostGenerateGradleAndroidProject +{ + public int callbackOrder + { + get { return int.MaxValue; } + } + + private string GetRootPath(string path) + { + return Path.Combine(path, "..", ""); + } + + public void OnPostGenerateGradleAndroidProject(string path) + { + var androidManifest = new SDKTool.AndroidManifest(SDKTool.GetManifestPath(path)); + androidManifest.SetStartingActivityAttribute("hardwareAccelerated", "true"); + androidManifest.Save(); + SetGradleConstraints(path); + FixedAddressValueTypeAttribute(path); + ParseConfigFile(path); + } + + private static void SetGradleConstraints(string path) + { + string gradlePath = Path.Combine(path, "../unityLibrary", "build.gradle"); + + if (!File.Exists(gradlePath)) + { + Debug.LogError("未找到unityLibrary模块的build.gradle文件: " + gradlePath); + } + + // var content = " implementation \"androidx.datastore:datastore:1.0.0\"\n constraints {\n implementation(\"androidx.datastore:datastore\") {\n version {\n strictly \"1.0.0\"\n }\n because \"1.0.0版本,避免高版本兼容性问题\"\n }\n }"; + var buildGradleOutLines = new List(); + foreach (var line in File.ReadLines(gradlePath)) + { + if (line.Trim().Contains("com.earn.money:sdk")) + { + Debug.Log("找到com.earn.money:sdk"); + buildGradleOutLines.Add($" implementation ('com.earn.money:sdk:{SDKTool.GetSDKVersion()}')"); + } + else + { + buildGradleOutLines.Add(line); + } + } + + File.WriteAllText(gradlePath, string.Join("\n", buildGradleOutLines.ToArray()) + "\n"); + } + + + private static void FixedAddressValueTypeAttribute(string path) + { + string launcherBuildGradlePath = Path.Combine(path, "../launcher", "build.gradle"); + string content = + " configurations.all {\n resolutionStrategy {\n force \"androidx.appcompat:appcompat:1.6.1\"\n force \"androidx.core:core:1.12.0\"\n }\n }"; + var launcherBuildGradleOutLines = new List(); + foreach (var line in File.ReadLines(launcherBuildGradlePath)) + { + launcherBuildGradleOutLines.Add(line); + if (line.Trim().StartsWith("defaultConfig")) + { + launcherBuildGradleOutLines.Add(content); + } + } + + File.WriteAllText(launcherBuildGradlePath, string.Join("\n", launcherBuildGradleOutLines.ToArray()) + "\n"); + } + + + + private void ParseConfigFile(string path) + { + Dictionary jsonDict = ParseToSimpleDictionary(); + if (jsonDict == null || jsonDict.Count == 0) + { + throw new System.Exception("配置文件中未解析到google-services.json"); + } + + // 获取launcher模块的build.gradle路径 + string gradlePath = Path.Combine(path, "../launcher", "build.gradle"); + + if (!File.Exists(gradlePath)) + { + Debug.LogError("未找到launcher模块的build.gradle文件: " + gradlePath); + } + // 读取文件内容 + string newResValue = $"\n resValue \"string\", \"game_services_project_id\", \"{jsonDict["project_id"]}\"" + + $"\n resValue \"string\", \"project_id\", \"{jsonDict["project_id"]}\"" + + $"\n resValue \"string\", \"google_project_id\", \"{jsonDict["project_id"]}\"" + + $"\n resValue \"string\", \"google_package_name\", \"{jsonDict["package_name"]}\"" + + $"\n resValue \"string\", \"gcm_defaultSenderId\", \"{jsonDict["project_number"]}\"" + + $"\n resValue \"string\", \"google_api_key\", \"{jsonDict["current_key"]}\"" + + $"\n resValue \"string\", \"google_app_id\", \"{jsonDict["mobilesdk_app_id"]}\"" + + $"\n resValue \"string\", \"google_crash_reporting_api_key\", \"{jsonDict["current_key"]}\"" + + $"\n resValue \"string\", \"google_storage_bucket\", \"{jsonDict["storage_bucket"]}\""; + Debug.Log($"DSSdk newResValue: {newResValue}"); + string launcherBuildGradlePath = Path.Combine(path, "../launcher", "build.gradle"); + var launcherBuildGradleOutLines = new List(); + foreach (var line in File.ReadLines(launcherBuildGradlePath)) + { + launcherBuildGradleOutLines.Add(line); + if (line.Trim().StartsWith("defaultConfig")) + { + launcherBuildGradleOutLines.Add(newResValue); + } + } + + File.WriteAllText(launcherBuildGradlePath, string.Join("\n", launcherBuildGradleOutLines.ToArray()) + "\n"); + + } + + public Dictionary ParseToSimpleDictionary() + { + Dictionary simpleDict = new Dictionary(); + + try + { + string filePath = Path.Combine(Application.streamingAssetsPath, "google-services.json"); + if (!File.Exists(filePath)) + { + Debug.LogError("文件不存在: " + filePath); + return simpleDict; + } + + string jsonContent = File.ReadAllText(filePath); + JObject jsonObject = JObject.Parse(jsonContent); + + // 递归解析所有字段 + ParseJToken(jsonObject, simpleDict); + return simpleDict; + } + catch (System.Exception e) + { + Debug.LogError("解析错误: " + e.Message); + return simpleDict; + } + } + + /// + /// 递归解析JToken并提取字段名和值 + /// + private void ParseJToken(JToken token, Dictionary dict) + { + if (token is JObject jObject) + { + foreach (var property in jObject.Properties()) + { + // 如果是对象类型,继续递归解析 + if (property.Value is JObject || property.Value is JArray) + { + ParseJToken(property.Value, dict); + } + else + { + // 基本类型直接添加,相同key会覆盖 + if (dict.ContainsKey(property.Name)) + { + Debug.LogWarning($"字段名重复,已覆盖: {property.Name}"); + } + dict[property.Name] = property.Value.ToString(); + } + } + } + else if (token is JArray jArray) + { + // 解析数组中的每个元素 + foreach (var item in jArray) + { + ParseJToken(item, dict); + } + } + } + + +} \ No newline at end of file diff --git a/Assets/EFSDK/Editor/DynamicApplicationClass.cs.meta b/Assets/EFSDK/Editor/DynamicApplicationClass.cs.meta new file mode 100644 index 0000000..333990c --- /dev/null +++ b/Assets/EFSDK/Editor/DynamicApplicationClass.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e118bf217da84e56846255d208995b6c +timeCreated: 1756628731 \ No newline at end of file diff --git a/Assets/EFSDK/Editor/SDKEditorNetworkTool.cs b/Assets/EFSDK/Editor/SDKEditorNetworkTool.cs new file mode 100644 index 0000000..a55fd60 --- /dev/null +++ b/Assets/EFSDK/Editor/SDKEditorNetworkTool.cs @@ -0,0 +1,45 @@ +using System; +using UnityEngine; +using UnityEngine.Networking; + +public class SDKEditorNetworkTool +{ + public static string GetText(string url) + { + try + { + using (UnityWebRequest www = UnityWebRequest.Get(url)) + { + www.timeout = 10; // 设置超时时间为10秒 + www.SendWebRequest(); // 同步发送请求 + + while (www.isDone == false) + { + } + + if (www.result != UnityWebRequest.Result.Success) + { + Debug.LogError($"Request failed: {www.error}"); + return ""; + } + + + if (www.responseCode != 200) + { + Debug.LogWarning($"Unexpected status code: {www.responseCode}"); + return ""; + } + + return www.downloadHandler.text; + } + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + + + return ""; + } +} \ No newline at end of file diff --git a/Assets/EFSDK/Editor/SDKEditorNetworkTool.cs.meta b/Assets/EFSDK/Editor/SDKEditorNetworkTool.cs.meta new file mode 100644 index 0000000..357d7e1 --- /dev/null +++ b/Assets/EFSDK/Editor/SDKEditorNetworkTool.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 69514595cf674f94bd3e0b15beb30d73 +timeCreated: 1756628731 \ No newline at end of file diff --git a/Assets/EFSDK/Editor/SDKTool.cs b/Assets/EFSDK/Editor/SDKTool.cs new file mode 100644 index 0000000..2078e35 --- /dev/null +++ b/Assets/EFSDK/Editor/SDKTool.cs @@ -0,0 +1,300 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Xml; +using Microsoft.CSharp.RuntimeBinder; +using UnityEditor; +using UnityEditor.Build; +using UnityEngine; + +public class SDKTool +{ + public static string GetPackageName() + { + return PlayerSettings.GetApplicationIdentifier(BuildTargetGroup.Android); + } + + public static string MavenStr = @" + maven { + url 'https://repo.dgtverse.cn/repository/maven-public/' + name 'maven_repo.dgtverse.cn' + } + +"; + public static Hashtable LoadProperties(string file) + { + var ht = new Hashtable(16); + string content = null; + try + { + content = file; + } + catch (Exception e) + { + return null; + } + + var rows = content.Split('\n'); + string[] kv = null; + foreach (var c in rows) + { + if (c.Trim().Length == 0) + continue; + kv = c.Split('='); + ht[kv[0].Trim()] = kv.Length switch + { + 1 => "", + 2 => kv[1].Trim(), + _ => ht[kv[0].Trim()] + }; + } + + return ht; + } + + public static string GetSDKVersion() + { + var xmlText = + SDKEditorNetworkTool.GetText("https://repo.dgtverse.cn/repository/tk_my/com/earn/money/sdk/maven-metadata.xml"); + if (string.IsNullOrEmpty(xmlText)) + { + throw new RuntimeBinderException( + "获取版本号失败 , 接口请求返回为空,或请求不到. https://repo.dgtverse.cn/repository/tk_my/com/earn/money/sdk/maven-metadata.xml"); + } + + try + { + XmlDocument xmlDoc = new XmlDocument(); + xmlDoc.LoadXml(xmlText); + + XmlNodeList versions = xmlDoc.SelectNodes("//versioning/latest"); + if (versions == null) + { + throw new RuntimeBinderException("获取版本号失败"); + } + + if (versions.Count > 0) + { + string latestVersion = versions[0].InnerText; + Debug.Log($"Latest version: {latestVersion}"); + return latestVersion; + } + + throw new RuntimeBinderException("解析xml失败"); + } + catch (Exception e) + { + throw new RuntimeBinderException($"获取版本号失败 : XML parsing error: {e.Message}"); + } + } + + + private void CopyGoogleServices(string path) + { + // var gpPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "SDKConfig" + + // Path.DirectorySeparatorChar + SDKTool.GetPackageName() + Path.DirectorySeparatorChar + + // "google-services.json"; + string gpPath = Path.Combine(Application.streamingAssetsPath, "google-services.json"); + if (!File.Exists(gpPath)) + { + throw new BuildFailedException("Can't find google-services.json"); + } + + var targetPath = path + Path.DirectorySeparatorChar + ".." + Path.DirectorySeparatorChar + "launcher" + + Path.DirectorySeparatorChar + "google-services.json"; + Debug.Log("gpPath : " + gpPath + "\t targetPath : " + targetPath); + if (File.Exists(targetPath)) + { + File.Delete(targetPath); + } + + File.Copy(gpPath, targetPath); + } + + private void AddFirebasePluginToGradle(string path) + { + var filePath = + $"{path}{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}launcher{Path.DirectorySeparatorChar}build.gradle"; + if (File.ReadAllText(filePath).Contains("com.google.gms.google-services")) + { + return; + } + + var newLine = new List + { + "apply plugin: 'com.google.gms.google-services'\n", + "apply plugin: 'com.google.firebase.crashlytics'\n" + }; + newLine.AddRange(File.ReadLines(filePath)); + File.WriteAllLines(filePath, newLine); + } + + private void AddFirebasePlugin(string rootPath) + { + _AddFirebasePlugin($"{rootPath}{Path.DirectorySeparatorChar}build.gradle"); + } + + private void _AddFirebasePlugin(string filePath) + { + if (File.ReadAllText(filePath).Contains("com.google.gms:google-services")) + { + return; + } + + var newLine = new List(); + foreach (var line in File.ReadLines(filePath)) + { + var trim = line.Trim(); + if (trim.Contains("com.google.gms.google-services") && trim.Contains("4.4.2")) + { + continue; + } + + if (trim.Contains("com.google.firebase.crashlytics") && trim.Contains("2.9.4")) + { + continue; + } + + if (trim.Contains("com.google.gms:google-services") && trim.Contains("4.3.10")) + { + continue; + } + + if (trim.Contains("com.google.firebase:firebase-crashlytics-gradle") && trim.Contains("2.9.4")) + { + continue; + } + + newLine.Add(line); + if (trim.StartsWith("google()")) + { + newLine.Add(MavenStr); + } + + if (trim.StartsWith("classpath")) + { + newLine.Add("classpath 'com.google.gms:google-services:4.3.10'\n"); + newLine.Add("classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.4'\n"); + } + + if (trim.StartsWith("id 'com.android.application'")) + { + newLine.Add("id 'com.google.gms.google-services' version '4.4.2' apply false\n"); + newLine.Add("id 'com.google.firebase.crashlytics' version '2.9.4' apply false\n"); + } + } + + File.WriteAllLines(filePath, newLine); + } + + private static string _manifestFilePath; + + public static string GetManifestPath(string basePath) + { + if (string.IsNullOrEmpty(_manifestFilePath)) + { + StringBuilder pathBuilder = new StringBuilder(basePath); + pathBuilder.Append(Path.DirectorySeparatorChar).Append("src"); + pathBuilder.Append(Path.DirectorySeparatorChar).Append("main"); + pathBuilder.Append(Path.DirectorySeparatorChar).Append("AndroidManifest.xml"); + _manifestFilePath = pathBuilder.ToString(); + Debug.Log($"_manifestFilePath = {_manifestFilePath}"); + + } + + return _manifestFilePath; + } + internal class AndroidXmlDocument : XmlDocument + { + private string m_Path; + protected XmlNamespaceManager nsMgr; + public const string AndroidXmlNamespace = "http://schemas.android.com/apk/res/android"; + + public AndroidXmlDocument(string path) + { + m_Path = path; + using (var reader = new XmlTextReader(m_Path)) + { + reader.Read(); + Load(reader); + } + + nsMgr = new XmlNamespaceManager(NameTable); + nsMgr.AddNamespace("android", AndroidXmlNamespace); + } + + public string Save() + { + return SaveAs(m_Path); + } + + public string SaveAs(string path) + { + using (var writer = new XmlTextWriter(path, new UTF8Encoding(false))) + { + writer.Formatting = Formatting.Indented; + Save(writer); + } + + return path; + } + } + internal class AndroidManifest : AndroidXmlDocument + { + private readonly XmlElement ApplicationElement; + + public AndroidManifest(string path) : base(path) + { + ApplicationElement = SelectSingleNode("/manifest/application") as XmlElement; + } + + private XmlAttribute CreateAndroidAttribute(string key, string value, string prefix = "android", string namespaceURI = AndroidXmlNamespace) + { + XmlAttribute attr = CreateAttribute(prefix, key, namespaceURI); + attr.Value = value; + return attr; + } + + internal XmlNode GetActivityWithLaunchIntent() + { + return SelectSingleNode( + "/manifest/application/activity[intent-filter/action/@android:name='android.intent.action.MAIN' and " + + "intent-filter/category/@android:name='android.intent.category.LAUNCHER']", nsMgr); + } + + internal void SetApplicationTheme(string appTheme) + { + ApplicationElement.Attributes.Append(CreateAndroidAttribute("theme", appTheme)); + } + + internal void SetStartingActivityName(string activityName) + { + GetActivityWithLaunchIntent().Attributes.Append(CreateAndroidAttribute("name", activityName)); + } + + internal void SetApplicationAttribute(string key, string value, string prefix = "android", string namespaceURI = AndroidXmlNamespace) + { + ApplicationElement.Attributes.Append(CreateAndroidAttribute(key, value, prefix, namespaceURI)); + } + + internal void RemoveApplicationAttribute(string key) + { + // ApplicationElement.Attributes.Remove(CreateAndroidAttribute(key, key)); + var removeNamedItem = ApplicationElement.Attributes.RemoveNamedItem(key); + Debug.Log($"删除节点 key = {key} value = {removeNamedItem}"); + } + + internal void SetStartingActivityAttribute(string key, string value) + { + XmlNode node = GetActivityWithLaunchIntent(); + Debug.Log($"Main节点 node = {node} key = {key} value = {value}"); + if (node != null) + { + XmlAttributeCollection attributes = node.Attributes; + attributes.Append(CreateAndroidAttribute(key, value)); + } + } + } +} \ No newline at end of file diff --git a/Assets/EFSDK/Editor/SDKTool.cs.meta b/Assets/EFSDK/Editor/SDKTool.cs.meta new file mode 100644 index 0000000..3775e32 --- /dev/null +++ b/Assets/EFSDK/Editor/SDKTool.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 01a2130a27404acabf67d5122908d668 +timeCreated: 1756628731 \ No newline at end of file diff --git a/Assets/EFSDK/WLoom.cs b/Assets/EFSDK/WLoom.cs new file mode 100644 index 0000000..fe0a5c4 --- /dev/null +++ b/Assets/EFSDK/WLoom.cs @@ -0,0 +1,175 @@ +using UnityEngine; +using System.Collections.Generic; +using System; +using System.Threading; +using System.Linq; + +namespace EFSDK +{ + public class WLoom : MonoBehaviour + { + public static int maxThreads = 8; + static int numThreads; + + private static WLoom _current; + + //private int _count; + public static WLoom Current + { + get + { + Initialize(); + return _current; + } + } + + void Awake() + { + _current = this; + initialized = true; + } + + static bool initialized; + + public static void Initialize() + { + if (!initialized) + { + if (!Application.isPlaying) + return; + initialized = true; + var g = new GameObject("Loom"); + _current = g.AddComponent(); + DontDestroyOnLoad(g); + } + } + + public struct NoDelayedQueueItem + { + public Action action; + public object param; + } + + private List _actions = new List(); + + public struct DelayedQueueItem + { + public float time; + public Action action; + public object param; + } + + private List _delayed = new List(); + + List _currentDelayed = new List(); + + public static void QueueOnMainThread(Action taction, object tparam) + { + QueueOnMainThread(taction, tparam, 0f); + } + + public static void QueueOnMainThread(Action taction, object tparam, float time) + { + if (time != 0) + { + lock (Current._delayed) + { + Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = taction, param = tparam }); + } + } + else + { + lock (Current._actions) + { + Current._actions.Add(new NoDelayedQueueItem { action = taction, param = tparam }); + } + } + } + + public static Thread RunAsync(Action a) + { + Initialize(); + while (numThreads >= maxThreads) + { + Thread.Sleep(100); + } + + Interlocked.Increment(ref numThreads); + ThreadPool.QueueUserWorkItem(RunAction, a); + return null; + } + + private static void RunAction(object action) + { + try + { + ((Action)action)(); + } + catch + { + } + finally + { + Interlocked.Decrement(ref numThreads); + } + } + + + void OnDisable() + { + if (_current == this) + { + _current = null; + } + } + + public void ToukaGamesInit() + { + } + + + // Use this for initialization + void Start() + { + } + + List _currentActions = new List(); + + // Update is called once per frame + void Update() + { + if (_actions.Count > 0) + { + lock (_actions) + { + _currentActions.Clear(); + _currentActions.AddRange(_actions); + _actions.Clear(); + } + + for (int i = 0; i < _currentActions.Count; i++) + { + _currentActions[i].action(_currentActions[i].param); + } + } + + if (_delayed.Count > 0) + { + lock (_delayed) + { + _currentDelayed.Clear(); + _currentDelayed.AddRange(_delayed.Where(d => d.time <= Time.time)); + for (int i = 0; i < _currentDelayed.Count; i++) + { + _delayed.Remove(_currentDelayed[i]); + } + } + + for (int i = 0; i < _currentDelayed.Count; i++) + { + _currentDelayed[i].action(_currentDelayed[i].param); + } + } + } + } +} \ No newline at end of file diff --git a/Assets/EFSDK/WLoom.cs.meta b/Assets/EFSDK/WLoom.cs.meta new file mode 100644 index 0000000..292e537 --- /dev/null +++ b/Assets/EFSDK/WLoom.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3aeb3cde9e8947319795ca9d78758647 +timeCreated: 1745562486 \ No newline at end of file diff --git a/Assets/Script/Common/CommonData.cs b/Assets/Script/Common/CommonData.cs deleted file mode 100644 index cd9bed2..0000000 --- a/Assets/Script/Common/CommonData.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Script.Common -{ - [System.Serializable] - public class RevenueAdjItem - { - public string name; - public int rate; - } - - [System.Serializable] - public class RevenueAdj - { - public RevenueAdjItem[] tevenueAdjs; - } -} \ No newline at end of file diff --git a/Assets/Script/Common/IvRulesData.cs b/Assets/Script/Common/IvRulesData.cs new file mode 100644 index 0000000..51d21d4 --- /dev/null +++ b/Assets/Script/Common/IvRulesData.cs @@ -0,0 +1,25 @@ +using System; + +namespace Script.Common +{ + [System.Serializable] + public class IvRulesData + { + public int type; + public int overLevel; //每跳过几次触发 + public int interval; //广告最小时间间隔 + public int skipLevel; //首次安装跳过几次触发不展示广告 + } + + public static class IvRulesKey + { + //首次安装跳过几次触发不展示广告 + public const string KEY_SKIPLEVEL = "KEY_IVRULES_SKIPLEVEL"; + } + + public static class IvRulesConst + { + public static int CurrentOverLevel = 0; //每跳过几次触发 + public static long CurrentInterval = 0; //广告最小时间间隔 + } +} \ No newline at end of file diff --git a/Assets/Script/Common/IvRulesData.cs.meta b/Assets/Script/Common/IvRulesData.cs.meta new file mode 100644 index 0000000..b3aad55 --- /dev/null +++ b/Assets/Script/Common/IvRulesData.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c6b65276a19841fdbf20d1ed0aa81ec4 +timeCreated: 1756695913 \ No newline at end of file diff --git a/Assets/Script/Common/RevenueData.cs b/Assets/Script/Common/RevenueData.cs new file mode 100644 index 0000000..9e3026b --- /dev/null +++ b/Assets/Script/Common/RevenueData.cs @@ -0,0 +1,9 @@ +namespace Script.Common +{ + [System.Serializable] + public class RevenueData + { + public string name; + public int rate; + } +} \ No newline at end of file diff --git a/Assets/Script/Common/CommonData.cs.meta b/Assets/Script/Common/RevenueData.cs.meta similarity index 100% rename from Assets/Script/Common/CommonData.cs.meta rename to Assets/Script/Common/RevenueData.cs.meta diff --git a/Assets/Script/SDKManager/AdjustManager/AdjustTrackEvent.cs b/Assets/Script/SDKManager/AdjustManager/AdjustTrackEvent.cs index e89535f..db74554 100644 --- a/Assets/Script/SDKManager/AdjustManager/AdjustTrackEvent.cs +++ b/Assets/Script/SDKManager/AdjustManager/AdjustTrackEvent.cs @@ -48,7 +48,7 @@ public class AdjustTrackEvent : NormalSingleton { return source; } - var revenueAdjs = JsonConvert.DeserializeObject(json); + var revenueAdjs = JsonConvert.DeserializeObject(json); if (revenueAdjs == null && revenueAdjs.Length == 0) { return source; diff --git a/Assets/Script/SDKManager/AdsSDKManager/AdsSDKManager.cs b/Assets/Script/SDKManager/AdsSDKManager/AdsSDKManager.cs index e71d201..86fd967 100644 --- a/Assets/Script/SDKManager/AdsSDKManager/AdsSDKManager.cs +++ b/Assets/Script/SDKManager/AdsSDKManager/AdsSDKManager.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; +using Firebase.RemoteConfig; +using Newtonsoft.Json; using Script.Common; using Script.SDKManager.AdsSDKManager.AdmobAdsManager; using Script.SDKManager.AdsSDKManager.BigoAdsManager; @@ -292,9 +294,11 @@ public class AdsSDKManager : NormalSingleton { case AdsType.Rewarded: // todo: 刷新激励广告 + KwaiAdsManager.Instance.LoadRewardAd(); break; case AdsType.Interstitial: // todo: 刷新插屏广告 + KwaiAdsManager.Instance.LoadInterstitialAd(); break; default: break; @@ -309,4 +313,68 @@ public class AdsSDKManager : NormalSingleton AdRewardCallback?.Invoke(price); AdRewardCallback = null; } + + /// + /// 根据IvRules判断是否可以展示插屏 + /// + /// + public bool IvRulesShow(IvType ivadType) + { + //1.获取远程配置 + string json = FireBaseRemoteConfigManager.Instance.GetRemoteConfigString("IV_RULES"); + if (string.IsNullOrEmpty(json)) + { + return true; + } + //2.解析配置 + var dates = JsonConvert.DeserializeObject(json); + if (dates == null && dates.Length == 0) + { + return true; + } + //3.获取IVADType对应的配置 + IvRulesData ivRulesData = null; + foreach (var data in dates) + { + if (data.type == (int)ivadType) + { + ivRulesData = data; + } + } + if (ivRulesData == null) + { + return true; + } + //4.判断skip(次安装跳过几次触发不展示广告) + int skipLevel = ivRulesData.skipLevel; + int currentSkipLevel = PlayerPrefsUtils.GetPlayerPrefsInt(IvRulesKey.KEY_SKIPLEVEL, 0); + if (currentSkipLevel < skipLevel) + { + LoggerUtils.Debug($"[SDK] skipLevel limit"); + PlayerPrefsUtils.SavePlayerPrefsInt(IvRulesKey.KEY_SKIPLEVEL, currentSkipLevel + 1); + return false; + } + //5.判断overLevel(没跳过几次触发) + int overLevel = ivRulesData.overLevel; + int currentOverLevel = IvRulesConst.CurrentOverLevel; + if (currentOverLevel < overLevel) + { + LoggerUtils.Debug($"[SDK] overLevel limit"); + IvRulesConst.CurrentOverLevel++; + return false; + } + + //6.判断interval(广告时间间隔) + int interval = ivRulesData.interval; + long currentInterval = IvRulesConst.CurrentInterval; + long localTimestamp = TimeUtils.GetLocalTimestamp(); + + if (localTimestamp < currentInterval + (interval * 1000L)) + { + LoggerUtils.Debug($"[SDK] interval limit"); + return false; + } + + return true; + } } diff --git a/Assets/Script/SDKManager/AppSDKManager.cs b/Assets/Script/SDKManager/AppSDKManager.cs index 9b4a483..aafc3ff 100644 --- a/Assets/Script/SDKManager/AppSDKManager.cs +++ b/Assets/Script/SDKManager/AppSDKManager.cs @@ -1,5 +1,9 @@ +using System; using System.Collections; using System.Collections.Generic; +using Script.Common; +using Script.SDKManager.AdsSDKManager.Constant; +using Script.Utils; using UnityEngine; public class AppSDKManager : MonoBehaviour @@ -17,7 +21,6 @@ public class AppSDKManager : MonoBehaviour AdjustManager.Instance.Init(); ShuShuMangage.Instance.Init(); AdsSDKManager.Instance.InitSDK(); - } /// @@ -28,4 +31,44 @@ public class AppSDKManager : MonoBehaviour { StartCoroutine(coroutine); } + + public void ShowInterstitial(string position, IvType ivadType = IvType.IV1, Action callback = null) + { + //插屏展示逻辑 + bool ivRulesShow = AdsSDKManager.Instance.IvRulesShow(ivadType); + if (ivRulesShow) + { + //是否有缓存 + bool isInterstitialReady = AdsSDKManager.Instance.IsInterstitialReady(); + if (isInterstitialReady) + { + AdsSDKManager.Instance.ShowInterstitialAd(position, ivadType, () => + { + //展示完一个插屏之后调用 + IvRulesConst.CurrentOverLevel = 0; + IvRulesConst.CurrentInterval = TimeUtils.GetLocalTimestamp(); + }); + } + } + } + + public bool IsRewardAdReady() + { + return AdsSDKManager.Instance.IsRewardAdReady();; + } + + public void ShowRewardAd(string position, Action callback = null) + { + bool isRewardAdReady = AdsSDKManager.Instance.IsRewardAdReady(); + if (isRewardAdReady) + { + AdsSDKManager.Instance.ShowRewardAd(position, (isReward) => + { + if (isReward) + { + //callback?.Invoke(); + } + }); + } + } } diff --git a/Assets/Script/SDKManager/FirebaseManager/FireBaseAnalyticsManager.cs b/Assets/Script/SDKManager/FirebaseManager/FireBaseAnalyticsManager.cs index d4f21ef..0938c1b 100644 --- a/Assets/Script/SDKManager/FirebaseManager/FireBaseAnalyticsManager.cs +++ b/Assets/Script/SDKManager/FirebaseManager/FireBaseAnalyticsManager.cs @@ -93,7 +93,7 @@ public class FireBaseAnalyticsManager : NormalSingleton(json); + var revenueAdjs = JsonConvert.DeserializeObject(json); if (revenueAdjs == null && revenueAdjs.Length == 0) { return name; diff --git a/Assets/Script/SDKManager/FirebaseManager/FireBaseRemoteConfigManager.cs b/Assets/Script/SDKManager/FirebaseManager/FireBaseRemoteConfigManager.cs index e12f4c3..9751311 100644 --- a/Assets/Script/SDKManager/FirebaseManager/FireBaseRemoteConfigManager.cs +++ b/Assets/Script/SDKManager/FirebaseManager/FireBaseRemoteConfigManager.cs @@ -50,15 +50,19 @@ public class FireBaseRemoteConfigManager : NormalSingleton