using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Reflection; using System.Runtime.InteropServices; using System.Threading.Tasks; using UnityEngine; using LC.Newtonsoft.Json; using TapTap.Common.Internal.Http; namespace TapTap.Common { public class TapCommonImpl : ITapCommon { private static readonly string TAP_COMMON_SERVICE = "TDSCommonService"; private readonly AndroidJavaObject _proxyServiceImpl; private readonly ConcurrentDictionary _propertiesProxies; public TapHttpClient HttpClient { get; private set; } private TapCommonImpl() { EngineBridge.GetInstance().Register("com.tds.common.wrapper.TDSCommonService", "com.tds.common.wrapper.TDSCommonServiceImpl"); _proxyServiceImpl = new AndroidJavaObject("com.tds.common.wrapper.TDSCommonServiceImpl"); _propertiesProxies = new ConcurrentDictionary(); } private static volatile TapCommonImpl _sInstance; private static readonly object Locker = new object(); public static TapCommonImpl GetInstance() { lock (Locker) { if (_sInstance == null) { _sInstance = new TapCommonImpl(); } } return _sInstance; } public void Init(TapConfig config) { var commandBuilder = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("initWithConfig") .Args("initWithConfig", JsonConvert.SerializeObject(config.ToDict())) .Args("versionName", Assembly.GetExecutingAssembly().GetName().Version.ToString()); var command = commandBuilder.CommandBuilder(); EngineBridge.GetInstance().CallHandler(command); HttpClient = new TapHttpClient(config.ClientID, config.ClientToken, config.ServerURL); } public void SetXua() { try { var xua = new Dictionary { {Constants.VersionKey, Assembly.GetExecutingAssembly().GetName().Version.ToString()}, {Constants.PlatformKey, "Unity"} }; var command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("setXUA") .Args("setXUA", Json.Serialize(xua)).CommandBuilder(); EngineBridge.GetInstance().CallHandler(command); } catch (Exception e) { Debug.Log($"exception:{e}"); } } public void GetRegionCode(Action callback) { var command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("getRegionCode").Callback(true) .OnceTime(true) .CommandBuilder(); EngineBridge.GetInstance().CallHandler(command, (result) => { if (result.code != Result.RESULT_SUCCESS) { return; } if (string.IsNullOrEmpty(result.content)) { return; } var wrapper = new CommonRegionWrapper(result.content); callback(wrapper.isMainland); }); } public void IsTapTapInstalled(Action callback) { var command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("isTapTapInstalled") .Callback(true) .OnceTime(true) .CommandBuilder(); EngineBridge.GetInstance().CallHandler(command, (result) => { if (result.code != Result.RESULT_SUCCESS) { callback(false); return; } if (string.IsNullOrEmpty(result.content)) { callback(false); return; } var dlc = Json.Deserialize(result.content) as Dictionary; callback(SafeDictionary.GetValue(dlc, "isTapTapInstalled")); }); } public void IsTapTapGlobalInstalled(Action callback) { var command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("isTapGlobalInstalled") .Callback(true) .OnceTime(true) .CommandBuilder(); EngineBridge.GetInstance().CallHandler(command, (result) => { if (result.code != Result.RESULT_SUCCESS) { callback(false); return; } if (string.IsNullOrEmpty(result.content)) { callback(false); return; } var dlc = Json.Deserialize(result.content) as Dictionary; callback(SafeDictionary.GetValue(dlc, "isTapGlobalInstalled")); }); } public void UpdateGameInTapTap(string appId, Action callback) { var command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("updateGameInTapTap") .Args("appId", appId) .Callback(true) .OnceTime(true) .CommandBuilder(); EngineBridge.GetInstance().CallHandler(command, (result) => { if (result.code != Result.RESULT_SUCCESS) { callback(false); return; } if (string.IsNullOrEmpty(result.content)) { callback(false); return; } var dlc = Json.Deserialize(result.content) as Dictionary; callback(SafeDictionary.GetValue(dlc, "updateGameInTapTap")); }); } public void UpdateGameInTapGlobal(string appId, Action callback) { var command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("updateGameInTapGlobal") .Args("appId", appId) .Callback(true) .OnceTime(true) .CommandBuilder(); EngineBridge.GetInstance().CallHandler(command, result => { if (result.code != Result.RESULT_SUCCESS) { callback(false); return; } if (string.IsNullOrEmpty(result.content)) { callback(false); return; } var dlc = Json.Deserialize(result.content) as Dictionary; callback(SafeDictionary.GetValue(dlc, "updateGameInTapGlobal")); }); } public void OpenReviewInTapTap(string appId, Action callback) { var command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("openReviewInTapTap") .Args("appId", appId) .Callback(true) .OnceTime(true) .CommandBuilder(); EngineBridge.GetInstance().CallHandler(command, result => { if (result.code != Result.RESULT_SUCCESS) { callback(false); return; } if (string.IsNullOrEmpty(result.content)) { callback(false); return; } var dlc = Json.Deserialize(result.content) as Dictionary; callback(SafeDictionary.GetValue(dlc, "openReviewInTapTap")); }); } public void OpenReviewInTapGlobal(string appId, Action callback) { var command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("openReviewInTapGlobal") .Args("appId", appId) .Callback(true) .OnceTime(true) .CommandBuilder(); EngineBridge.GetInstance().CallHandler(command, result => { if (result.code != Result.RESULT_SUCCESS) { callback(false); return; } if (string.IsNullOrEmpty(result.content)) { callback(false); return; } var dlc = Json.Deserialize(result.content) as Dictionary; callback(SafeDictionary.GetValue(dlc, "openReviewInTapGlobal")); }); } public void SetLanguage(TapLanguage language) { var command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("setPreferredLanguage") .Args("preferredLanguage", (int) language) .CommandBuilder(); EngineBridge.GetInstance().CallHandler(command); } public void RegisterProperties(string key, ITapPropertiesProxy proxy) { if (Platform.IsAndroid()) { _proxyServiceImpl?.Call("registerProperties", key, new TapPropertiesProxy(proxy)); } else if (Platform.IsIOS()) { #if UNITY_IOS if (_propertiesProxies.TryAdd(key, proxy)) { Debug.Log($"register Properties:{Json.Serialize(_propertiesProxies)}"); registerProperties(key, TapPropertiesDelegateProxy); } #endif } Debug.Log($"registerProperty:{key == null} value:{proxy == null}"); } public void UseNativeDataInCore(bool enable) { try { var command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("useNativeDataInCore") .Args("useNativeDataInCore", enable) .OnceTime(true) .CommandBuilder(); EngineBridge.GetInstance().CallHandler(command); command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("setDurationStatisticsEnabled") .Args("setDurationStatisticsEnabled", enable) .OnceTime(true) .CommandBuilder(); EngineBridge.GetInstance().CallHandler(command); } catch (System.Exception e) { Debug.LogErrorFormat("useNativeDataInCore & setDurationStatisticsEnabled error:{0}\n{1}", e.Message, e.StackTrace); } } public void SetDurationStatisticsEnabled(bool enable) { Debug.Log($"SetDurationStatisticsEnabled:{enable}"); TapTap.Common.TapCommon.DisableDurationStatistics = !enable; } #if UNITY_IOS private delegate string TapPropertiesDelegate(string key); [AOT.MonoPInvokeCallbackAttribute(typeof(TapPropertiesDelegate))] private static string TapPropertiesDelegateProxy(string key) { Debug.Log($"key:{key} register Properties:{Json.Serialize(_sInstance._propertiesProxies)}"); var proxy = _sInstance._propertiesProxies[key]; return proxy?.GetProperties(); } [DllImport("__Internal")] private static extern void registerProperties(string key, TapPropertiesDelegate propertiesDelegate); #endif public void AddHost(string host, string replaceHost) { Debug.LogFormat($"addHost host:{host} replaceHost:{replaceHost}"); var command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("addReplacedHostPair") .Args("hostToBeReplaced", host) .Args("replacedHost", replaceHost) .CommandBuilder(); EngineBridge.GetInstance().CallHandler(command); } private static void CheckPlatformSupport() { if (Platform.IsIOS()) { throw new TapException(-1, "iOS Platform dont support current func"); } } private static void CheckResult(Result result) { if (!EngineBridge.CheckResult(result)) { throw new TapException(-1, $"TapBridge dont support this Command:{result.message}"); } } public async Task UpdateGameAndFailToWebInTapTap(string appId) { CheckPlatformSupport(); var command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("updateGameAndFailToWebInTapTap") .Args("appId", appId) .Callback(true) .OnceTime(true) .CommandBuilder(); var result = await EngineBridge.GetInstance().Emit(command); CheckResult(result); var dic = Json.Deserialize(result.content) as Dictionary; return SafeDictionary.GetValue(dic, "result"); } public async Task UpdateGameAndFailToWebInTapGlobal(string appId) { CheckPlatformSupport(); var command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("updateGameAndFailToWebInTapGlobal") .Args("appId", appId) .Callback(true) .OnceTime(true) .CommandBuilder(); var result = await EngineBridge.GetInstance().Emit(command); CheckResult(result); var dic = Json.Deserialize(result.content) as Dictionary; return SafeDictionary.GetValue(dic, "result"); } public async Task UpdateGameAndFailToWebInTapTap(string appId, string webUrl) { CheckPlatformSupport(); var command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("updateGameAndFailToWebInTapTapWithWebUrl") .Args("appId", appId) .Args("webUrl", webUrl) .Callback(true) .OnceTime(true) .CommandBuilder(); var result = await EngineBridge.GetInstance().Emit(command); CheckResult(result); var dic = Json.Deserialize(result.content) as Dictionary; return SafeDictionary.GetValue(dic, "result"); } public async Task UpdateGameAndFailToWebInTapGlobal(string appId, string webUrl) { CheckPlatformSupport(); var command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("updateGameAndFailToWebInTapGlobalWithWebUrl") .Args("appId", appId) .Args("webUrl", webUrl) .Callback(true) .OnceTime(true) .CommandBuilder(); var result = await EngineBridge.GetInstance().Emit(command); CheckResult(result); var dic = Json.Deserialize(result.content) as Dictionary; return SafeDictionary.GetValue(dic, "result"); } public async Task OpenWebDownloadUrlOfTapTap(string appId) { CheckPlatformSupport(); var command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("openWebDownloadUrlOfTapTap") .Args("appId", appId) .Callback(true) .OnceTime(true) .CommandBuilder(); var result = await EngineBridge.GetInstance().Emit(command); CheckResult(result); var dic = Json.Deserialize(result.content) as Dictionary; return SafeDictionary.GetValue(dic, "result"); } public async Task OpenWebDownloadUrlOfTapGlobal(string appId) { CheckPlatformSupport(); var command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("openWebDownloadUrlOfTapGlobal") .Args("appId", appId) .Callback(true) .OnceTime(true) .CommandBuilder(); var result = await EngineBridge.GetInstance().Emit(command); CheckResult(result); var dic = Json.Deserialize(result.content) as Dictionary; return SafeDictionary.GetValue(dic, "result"); } public async Task OpenWebDownloadUrl(string url) { CheckPlatformSupport(); var command = new Command.Builder() .Service(TAP_COMMON_SERVICE) .Method("openWebDownloadUrl") .Args("appId", url) .Callback(true) .OnceTime(true) .CommandBuilder(); var result = await EngineBridge.GetInstance().Emit(command); CheckResult(result); var dic = Json.Deserialize(result.content) as Dictionary; return SafeDictionary.GetValue(dic, "result"); } private class TapPropertiesProxy : AndroidJavaProxy { private readonly ITapPropertiesProxy _properties; public TapPropertiesProxy(ITapPropertiesProxy properties) : base(new AndroidJavaClass("com.tds.common.wrapper.TapPropertiesProxy")) { _properties = properties; } public override AndroidJavaObject Invoke(string methodName, object[] args) { return _properties != null ? new AndroidJavaObject("java.lang.String", _properties.GetProperties()) : base.Invoke(methodName, args); } } } }