AnalyticsServiceInstance.cs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. using System;
  2. using System.Threading.Tasks;
  3. using Unity.Services.Analytics.Data;
  4. using Unity.Services.Analytics.Internal;
  5. using Unity.Services.Analytics.Platform;
  6. using Unity.Services.Authentication.Internal;
  7. using Unity.Services.Core.Device.Internal;
  8. using UnityEngine;
  9. using Event = Unity.Services.Analytics.Internal.Event;
  10. namespace Unity.Services.Analytics
  11. {
  12. partial class AnalyticsServiceInstance : IAnalyticsService
  13. {
  14. public string PrivacyUrl => "https://unity3d.com/legal/privacy-policy";
  15. const string k_CollectUrlPattern = "https://collect.analytics.unity3d.com/api/analytics/collect/v1/projects/{0}/environments/{1}";
  16. const string k_ForgetCallingId = "com.unity.services.analytics.Events." + nameof(OptOut);
  17. internal IPlayerId PlayerId { get; private set; }
  18. internal IInstallationId InstallId { get; private set; }
  19. internal string CustomAnalyticsId { get; private set; }
  20. internal IBuffer dataBuffer = new Internal.Buffer();
  21. internal IDataGenerator dataGenerator = new DataGenerator();
  22. internal IDispatcher dataDispatcher { get; set; }
  23. string m_CollectURL;
  24. readonly string m_SessionID;
  25. readonly StdCommonParams m_CommonParams = new StdCommonParams();
  26. readonly string m_StartUpCallingId = "com.unity.services.analytics.Events.Startup";
  27. internal IIDeviceIdentifiersInternal deviceIdentifiersInternal = new DeviceIdentifiersInternal();
  28. internal bool ServiceEnabled { get; private set; } = true;
  29. internal AnalyticsServiceInstance()
  30. {
  31. // The docs say nothing about Application.cloudProjectId being guaranteed or not,
  32. // we add a check just to be sure.
  33. if (string.IsNullOrEmpty(Application.cloudProjectId))
  34. {
  35. Debug.LogError("No Cloud ProjectID Found for Analytics");
  36. return;
  37. }
  38. dataDispatcher = new Dispatcher(dataBuffer, new WebRequestHelper(), ConsentTracker);
  39. m_SessionID = Guid.NewGuid().ToString();
  40. m_CommonParams.ClientVersion = Application.version;
  41. m_CommonParams.ProjectID = Application.cloudProjectId;
  42. m_CommonParams.GameBundleID = Application.identifier;
  43. m_CommonParams.Platform = Runtime.Name();
  44. m_CommonParams.BuildGuuid = Application.buildGUID;
  45. m_CommonParams.Idfv = deviceIdentifiersInternal.Idfv;
  46. }
  47. public void Flush()
  48. {
  49. if (!ServiceEnabled)
  50. {
  51. return;
  52. }
  53. if (string.IsNullOrEmpty(Application.cloudProjectId))
  54. {
  55. return;
  56. }
  57. if (InstallId == null)
  58. {
  59. #if UNITY_ANALYTICS_DEVELOPMENT
  60. Debug.Log("The Core callback hasn't yet triggered.");
  61. #endif
  62. return;
  63. }
  64. if (ConsentTracker.IsGeoIpChecked() && ConsentTracker.IsConsentGiven())
  65. {
  66. dataBuffer.InstallID = InstallId.GetOrCreateIdentifier();
  67. dataBuffer.PlayerID = PlayerId?.PlayerId;
  68. dataBuffer.UserID = !string.IsNullOrEmpty(CustomAnalyticsId) ? CustomAnalyticsId : dataBuffer.InstallID;
  69. dataBuffer.SessionID = m_SessionID;
  70. dataDispatcher.CollectUrl = m_CollectURL;
  71. dataDispatcher.Flush();
  72. }
  73. if (ConsentTracker.IsOptingOutInProgress())
  74. {
  75. analyticsForgetter.AttemptToForget();
  76. }
  77. }
  78. public void RecordInternalEvent(Event eventToRecord)
  79. {
  80. if (!ServiceEnabled)
  81. {
  82. return;
  83. }
  84. dataBuffer.PushEvent(eventToRecord);
  85. }
  86. internal void SetDependencies(IInstallationId installId, IPlayerId playerId, string environment, string customAnalyticsId)
  87. {
  88. InstallId = installId;
  89. PlayerId = playerId;
  90. CustomAnalyticsId = customAnalyticsId;
  91. m_CollectURL = string.Format(k_CollectUrlPattern, Application.cloudProjectId, environment.ToLowerInvariant());
  92. }
  93. internal async Task Initialize(IInstallationId installId, IPlayerId playerId, string environment, string customAnalyticsId)
  94. {
  95. SetDependencies(installId, playerId, environment, customAnalyticsId);
  96. if (!ServiceEnabled)
  97. {
  98. return;
  99. }
  100. await InitializeUser();
  101. }
  102. async Task InitializeUser()
  103. {
  104. SetVariableCommonParams();
  105. #if UNITY_ANALYTICS_DEVELOPMENT
  106. Debug.LogFormat("UA2 Setup\nCollectURL:{0}\nSessionID:{1}", m_CollectURL, m_SessionID);
  107. #endif
  108. try
  109. {
  110. await ConsentTracker.CheckGeoIP();
  111. if (ConsentTracker.IsGeoIpChecked() && (ConsentTracker.IsConsentDenied() || ConsentTracker.IsOptingOutInProgress()))
  112. {
  113. OptOut();
  114. }
  115. }
  116. #if UNITY_ANALYTICS_EVENT_LOGS
  117. catch (ConsentCheckException e)
  118. {
  119. Debug.Log("Initial GeoIP lookup fail: " + e.Message);
  120. }
  121. #else
  122. catch (ConsentCheckException) {}
  123. #endif
  124. }
  125. /// <summary>
  126. /// Sets up the internals of the Analytics SDK, including the regular sending of events and assigning
  127. /// the userID to be used in further event recording.
  128. /// </summary>
  129. internal void Startup()
  130. {
  131. if (!ServiceEnabled)
  132. {
  133. return;
  134. }
  135. // Startup Events.
  136. dataGenerator.SdkStartup(ref dataBuffer, DateTime.Now, m_CommonParams, m_StartUpCallingId);
  137. dataGenerator.ClientDevice(ref dataBuffer, DateTime.Now, m_CommonParams, m_StartUpCallingId, SystemInfo.processorType, SystemInfo.graphicsDeviceName, SystemInfo.processorCount, SystemInfo.systemMemorySize, Screen.width, Screen.height, (int)Screen.dpi);
  138. #if UNITY_DOTSRUNTIME
  139. var isTiny = true;
  140. #else
  141. var isTiny = false;
  142. #endif
  143. dataGenerator.GameStarted(ref dataBuffer, DateTime.Now, m_CommonParams, m_StartUpCallingId, Application.buildGUID, SystemInfo.operatingSystem, isTiny, DebugDevice.IsDebugDevice(), Locale.AnalyticsRegionLanguageCode());
  144. }
  145. internal void NewPlayerEvent()
  146. {
  147. if (!ServiceEnabled)
  148. {
  149. return;
  150. }
  151. if (InstallId != null && new InternalNewPlayerHelper(InstallId).IsNewPlayer())
  152. {
  153. dataGenerator.NewPlayer(ref dataBuffer, DateTime.Now, m_CommonParams, m_StartUpCallingId, SystemInfo.deviceModel);
  154. }
  155. }
  156. /// <summary>
  157. /// Records the gameEnded event, and flushes the buffer to upload all events.
  158. /// </summary>
  159. internal void GameEnded()
  160. {
  161. if (!ServiceEnabled)
  162. {
  163. return;
  164. }
  165. dataGenerator.GameEnded(ref dataBuffer, DateTime.Now, m_CommonParams, "com.unity.services.analytics.Events.Shutdown", DataGenerator.SessionEndState.QUIT);
  166. if (ConsentTracker.IsGeoIpChecked())
  167. {
  168. Flush();
  169. }
  170. }
  171. // <summary>
  172. // Internal tick is called by the Heartbeat at set intervals.
  173. // </summary>
  174. internal void InternalTick()
  175. {
  176. if (!ServiceEnabled)
  177. {
  178. return;
  179. }
  180. SetVariableCommonParams();
  181. dataGenerator.GameRunning(ref dataBuffer, DateTime.Now, m_CommonParams, "com.unity.services.analytics.Events.InternalTick");
  182. if (ConsentTracker.IsGeoIpChecked())
  183. {
  184. Flush();
  185. }
  186. }
  187. void SetVariableCommonParams()
  188. {
  189. m_CommonParams.Idfv = deviceIdentifiersInternal.Idfv;
  190. m_CommonParams.DeviceVolume = DeviceVolumeProvider.GetDeviceVolume();
  191. m_CommonParams.BatteryLoad = SystemInfo.batteryLevel;
  192. m_CommonParams.UasUserID = PlayerId?.PlayerId;
  193. }
  194. void GameEnded(DataGenerator.SessionEndState quitState)
  195. {
  196. if (!ServiceEnabled)
  197. {
  198. return;
  199. }
  200. dataGenerator.GameEnded(ref dataBuffer, DateTime.Now, m_CommonParams, "com.unity.services.analytics.Events.GameEnded", quitState);
  201. }
  202. public async Task SetAnalyticsEnabled(bool enabled)
  203. {
  204. if (enabled && !ServiceEnabled)
  205. {
  206. dataBuffer = new Internal.Buffer();
  207. dataDispatcher = new Dispatcher(dataBuffer, new WebRequestHelper(), ConsentTracker);
  208. await InitializeUser();
  209. ServiceEnabled = true;
  210. }
  211. else if (!enabled && ServiceEnabled)
  212. {
  213. dataBuffer.ClearBuffer();
  214. dataBuffer.ClearDiskCache();
  215. dataBuffer = new BufferRevoked();
  216. ServiceEnabled = false;
  217. }
  218. }
  219. }
  220. }