FlurryAnalyticsIOS.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. ///----------------------------------------------
  2. /// Flurry Analytics Plugin
  3. /// Copyright © 2016 Aleksei Kuzin
  4. ///----------------------------------------------
  5. using UnityEngine;
  6. using System.Collections.Generic;
  7. using System.Text;
  8. #if UNITY_IOS
  9. using System.Runtime.InteropServices;
  10. #endif
  11. namespace KHD {
  12. public static class FlurryAnalyticsIOS {
  13. #if UNITY_IOS
  14. [DllImport("__Internal")]
  15. private static extern void FlurryAnalyticsStartSession(string apiKey, bool sendCrashReports);
  16. [DllImport("__Internal")]
  17. private static extern void FlurryAnalyticsSetDebugLogEnabled(bool enabled);
  18. [DllImport("__Internal")]
  19. private static extern void FlurryAnalyticsSetAppVersion(string version);
  20. [DllImport("__Internal")]
  21. private static extern void FlurryAnalyticsSetSessionContinueSeconds(int seconds);
  22. [DllImport("__Internal")]
  23. private static extern void FlurryAnalyticsSetUserId(string userId);
  24. [DllImport("__Internal")]
  25. private static extern void FlurryAnalyticsSetAge(int age);
  26. [DllImport("__Internal")]
  27. private static extern void FlurryAnalyticsSetGender(int genderType);
  28. [DllImport("__Internal")]
  29. private static extern void FlurryAnalyticsLogEvent(string eventName, bool isTimed);
  30. [DllImport("__Internal")]
  31. private static extern void FlurryAnalyticsLogEventWithParameters(string eventName,
  32. string parameters,
  33. bool isTimed);
  34. [DllImport("__Internal")]
  35. private static extern void FlurryAnalyticsEndTimedEvent(string eventName,
  36. string parameters);
  37. [DllImport("__Internal")]
  38. private static extern void FlurryAnalyticsSetSessionReportsOnCloseEnabled(bool enabled);
  39. [DllImport("__Internal")]
  40. private static extern void FlurryAnalyticsSetSessionReportsOnPauseEnabled(bool enabled);
  41. [DllImport("__Internal")]
  42. private static extern void FlurryAnalyticsSetPulseEnabled(bool enabled);
  43. [DllImport("__Internal")]
  44. private static extern void FlurryAnalyticsSetLatitude(float latitude, float longitude,
  45. float horizontalAccuracy,
  46. float verticalAccuracy);
  47. [DllImport("__Internal")]
  48. private static extern void FlurryAnalyticsSetIAPReportingEnabled(bool enabled);
  49. #endif
  50. #if UNITY_EDITOR
  51. /// <summary>
  52. /// Generates debug logs to Editor console.
  53. /// </summary>
  54. private static bool _editorDebugLogEnabled = false;
  55. #endif
  56. /// <summary>
  57. /// Start Flurry session.
  58. /// </summary>
  59. /// <param name="apiKey">API key.</param>
  60. /// <param name="sendCrashReports">If set to <c>true</c> send crash reports.</param>
  61. public static void StartSession(string apiKey, bool sendCrashReports) {
  62. #if UNITY_IOS
  63. DebugLog("Session started with apiKey: " + apiKey + " send crash reports: " + sendCrashReports);
  64. if (!IsIPhonePlayer()) {
  65. return;
  66. }
  67. if (apiKey != null) {
  68. apiKey = apiKey.ToUpper();
  69. }
  70. if (string.IsNullOrEmpty(apiKey)) {
  71. DebugLogError("iOS API key is null or empty, please provide valid API key");
  72. }
  73. FlurryAnalyticsStartSession(apiKey, sendCrashReports);
  74. #endif
  75. }
  76. /// <summary>
  77. /// Enable/Disable Flurry SDK debug logs.
  78. ///
  79. /// By default logs are disabled.
  80. /// </summary>
  81. public static void SetDebugLogEnabled(bool enabled) {
  82. #if UNITY_EDITOR
  83. _editorDebugLogEnabled = enabled;
  84. #endif
  85. #if UNITY_IOS
  86. if (!IsIPhonePlayer()) {
  87. return;
  88. }
  89. FlurryAnalyticsSetDebugLogEnabled(enabled);
  90. #endif
  91. }
  92. /// <summary>
  93. /// Set app version. By default Flurry SDK use CFBundleVersion.
  94. /// Should be called before StartSession.
  95. /// </summary>
  96. /// <param name="appVersion">App version.</param>
  97. public static void SetAppVersion(string appVersion) {
  98. #if UNITY_IOS
  99. DebugLog("Application version changed to: " + appVersion);
  100. if (!IsIPhonePlayer()) {
  101. return;
  102. }
  103. FlurryAnalyticsSetAppVersion(appVersion);
  104. #endif
  105. }
  106. /// <summary>
  107. /// Sets the time the app may be in the background before starting a new session upon resume.
  108. /// Default value 10 seconds.
  109. ///
  110. /// Should be called before StartSession.
  111. /// </summary>
  112. public static void SetSessionContinueSeconds(int seconds) {
  113. #if UNITY_IOS
  114. DebugLog("Set continue session seconds to: " + seconds);
  115. if (!IsIPhonePlayer()) {
  116. return;
  117. }
  118. FlurryAnalyticsSetSessionContinueSeconds(seconds);
  119. #endif
  120. }
  121. /// <summary>
  122. /// Enables Flurry Pulse.
  123. /// Please see https://developer.yahoo.com/flurry-pulse/ for more details.
  124. ///
  125. /// Should be called before StartSession.
  126. /// </summary>
  127. public static void SetPulseEnabled(bool enabled) {
  128. #if UNITY_IOS
  129. DebugLog("Set Pulse enabled: " + enabled);
  130. if (!IsIPhonePlayer()) {
  131. return;
  132. }
  133. FlurryAnalyticsSetPulseEnabled(enabled);
  134. #endif
  135. }
  136. /// <summary>
  137. /// Enables implicit recording of Apple Store transactions.
  138. /// true to enable transaction logging, false to stop transaction logging.
  139. ///
  140. /// This method should be called after StartSession.
  141. /// </summary>
  142. public static void SetIAPReportingEnabled(bool enabled) {
  143. #if UNITY_IOS
  144. DebugLog("Set IAP reporting enabled: " + enabled);
  145. if (!IsIPhonePlayer()) {
  146. return;
  147. }
  148. FlurryAnalyticsSetIAPReportingEnabled(enabled);
  149. #endif
  150. }
  151. /// <summary>
  152. /// Assign a unique id for a user in your app.
  153. /// </summary>
  154. public static void SetUserId(string userId) {
  155. #if UNITY_IOS
  156. DebugLog("Set unique user id: " + userId);
  157. if (!IsIPhonePlayer()) {
  158. return;
  159. }
  160. FlurryAnalyticsSetUserId(userId);
  161. #endif
  162. }
  163. /// <summary>
  164. /// Use this method to capture the age of your user.
  165. /// </summary>
  166. public static void SetAge(int age) {
  167. #if UNITY_IOS
  168. DebugLog("Set user age: " + age);
  169. if (!IsIPhonePlayer()) {
  170. return;
  171. }
  172. FlurryAnalyticsSetAge(age);
  173. #endif
  174. }
  175. /// <summary>
  176. /// Set user's gender.
  177. /// </summary>
  178. public static void SetGender(FlurryAnalytics.Gender gender) {
  179. #if UNITY_IOS
  180. DebugLog("Set user gender: " + gender);
  181. if (!IsIPhonePlayer()) {
  182. return;
  183. }
  184. FlurryAnalyticsSetGender((int)gender);
  185. #endif
  186. }
  187. /// <summary>
  188. /// Set the location of the session.
  189. /// Only the last location entered is captured per session.
  190. /// Regardless of accuracy specified, the Flurry SDK will only report location at city level or higher.
  191. /// Location is aggregated across all users of your app and not available on a per user basis.
  192. /// This information should only be captured if it is germaine to the use of your app.
  193. /// </summary>
  194. public static void SetLocation(float latitude, float longitude,
  195. float horizontalAccuracy, float verticalAccuracy) {
  196. #if UNITY_IOS
  197. DebugLog("Set location: " + latitude + ", " + longitude);
  198. if (!IsIPhonePlayer()) {
  199. return;
  200. }
  201. FlurryAnalyticsSetLatitude(
  202. latitude, longitude, horizontalAccuracy, verticalAccuracy);
  203. #endif
  204. }
  205. /// <summary>
  206. /// Records a custom event specified by eventName.
  207. /// </summary>
  208. /// <param name="eventName">
  209. /// Name of the event. For maximum effectiveness, we recommend using a naming scheme
  210. /// that can be easily understood by non-technical people in your business domain.
  211. /// </param>
  212. /// <param name="isTimed">If set to <c>true</c> this will be a timed event.
  213. /// Call EndTimedEvent to stop timed event.</param>
  214. public static void LogEvent(string eventName, bool isTimed = false) {
  215. #if UNITY_IOS
  216. DebugLog("Log event: " + eventName + " isTimed: " + isTimed);
  217. if (!IsIPhonePlayer()) {
  218. return;
  219. }
  220. FlurryAnalyticsLogEvent(eventName, isTimed);
  221. #endif
  222. }
  223. /// <summary>
  224. /// Log custom event with parameters.
  225. /// A maximum of 10 parameter names may be associated with any event.
  226. /// </summary>
  227. /// <param name="eventName">
  228. /// Name of the event. For maximum effectiveness, we recommend using a naming scheme
  229. /// that can be easily understood by non-technical people in your business domain.
  230. /// </param>
  231. /// <param name="parameters">Parameters.</param>
  232. /// <param name="isTimed">If set to <c>true</c> this will be a timed event.
  233. /// Call EndTimedEvent to stop timed event.</param>
  234. public static void LogEventWithParameters(string eventName, Dictionary<string, string> parameters,
  235. bool isTimed = false) {
  236. #if UNITY_IOS
  237. DebugLog("Log event: " + eventName + " isTimed: " + isTimed + " with parameters");
  238. if (!IsIPhonePlayer()) {
  239. return;
  240. }
  241. FlurryAnalyticsLogEventWithParameters(eventName, ConvertParameters(parameters), isTimed);
  242. #endif
  243. }
  244. /// <summary>
  245. /// Ends the timed event.
  246. /// </summary>
  247. /// <param name="eventName">
  248. /// Name of the event. For maximum effectiveness, we recommend using a naming scheme
  249. /// that can be easily understood by non-technical people in your business domain.
  250. /// </param>
  251. /// <param name="parameters">Parameters.</param>
  252. public static void EndTimedEvent(string eventName, Dictionary<string, string> parameters = null) {
  253. #if UNITY_IOS
  254. DebugLog("End timed event: " + eventName);
  255. if (!IsIPhonePlayer()) {
  256. return;
  257. }
  258. FlurryAnalyticsEndTimedEvent(eventName, ConvertParameters(parameters));
  259. #endif
  260. }
  261. /// <summary>
  262. /// Sets the session reports on close enabled.
  263. /// Enabled by default.
  264. /// </summary>
  265. public static void SetSessionReportsOnCloseEnabled(bool enabled) {
  266. #if UNITY_IOS
  267. DebugLog("Set session reports on close: " + enabled);
  268. if (!IsIPhonePlayer()) {
  269. return;
  270. }
  271. FlurryAnalyticsSetSessionReportsOnCloseEnabled(enabled);
  272. #endif
  273. }
  274. /// <summary>
  275. /// Sets the session reports on pause enabled.
  276. /// Enabled by default.
  277. /// </summary>
  278. public static void SetSessionReportsOnPauseEnabled(bool enabled) {
  279. #if UNITY_IOS
  280. DebugLog("Set session reports on pause: " + enabled);
  281. if (!IsIPhonePlayer()) {
  282. return;
  283. }
  284. FlurryAnalyticsSetSessionReportsOnPauseEnabled(enabled);
  285. #endif
  286. }
  287. /// <summary>
  288. /// Converts the parameters to json.
  289. /// </summary>
  290. private static string ConvertParameters(Dictionary<string, string> parameters) {
  291. if (parameters == null) {
  292. return null;
  293. }
  294. StringBuilder builder = new StringBuilder();
  295. builder.Append("{\n");
  296. var first = true;
  297. foreach (var pair in parameters) {
  298. if (!first) {
  299. builder.Append(',');
  300. }
  301. SerializeString(builder, pair.Key);
  302. builder.Append(":");
  303. SerializeString(builder, pair.Value);
  304. first = false;
  305. }
  306. builder.Append("}\n");
  307. return builder.ToString();
  308. }
  309. /// <summary>
  310. /// Serialize string to json string.
  311. /// </summary>
  312. private static void SerializeString(StringBuilder builder, string str) {
  313. builder.Append('\"');
  314. var charArray = str.ToCharArray();
  315. foreach (var c in charArray) {
  316. switch (c) {
  317. case '"':
  318. builder.Append("\\\"");
  319. break;
  320. case '\\':
  321. builder.Append("\\\\");
  322. break;
  323. case '\b':
  324. builder.Append("\\b");
  325. break;
  326. case '\f':
  327. builder.Append("\\f");
  328. break;
  329. case '\n':
  330. builder.Append("\\n");
  331. break;
  332. case '\r':
  333. builder.Append("\\r");
  334. break;
  335. case '\t':
  336. builder.Append("\\t");
  337. break;
  338. default:
  339. var codepoint = System.Convert.ToInt32(c);
  340. if ((codepoint >= 32) && (codepoint <= 126)) {
  341. builder.Append(c);
  342. } else {
  343. builder.Append("\\u" + System.Convert.ToString(codepoint, 16).PadLeft(4, '0'));
  344. }
  345. break;
  346. }
  347. }
  348. builder.Append('\"');
  349. }
  350. /// <returns><c>true</c> if is iPhone player.</returns>
  351. private static bool IsIPhonePlayer() {
  352. return Application.platform == RuntimePlatform.IPhonePlayer;
  353. }
  354. private static bool EditorDebugLogEnabled() {
  355. #if UNITY_EDITOR
  356. return _editorDebugLogEnabled;
  357. #else
  358. return false;
  359. #endif
  360. }
  361. private static void DebugLog(string log) {
  362. if (!EditorDebugLogEnabled()) {
  363. return;
  364. }
  365. Debug.Log("[FlurryAnalyticsPlugin]: " + log);
  366. }
  367. private static void DebugLogError(string error) {
  368. Debug.Log("[FlurryAnalyticsPlugin]: " + error);
  369. }
  370. }
  371. }