public static void InternalInitialize() #endif { // Make sure database is ready if (!GAStore.IsTableReady) { return; } EnsurePersistedStates(); GAStore.SetState(DefaultUserIdKey, Instance.DefaultUserId); Initialized = true; #if WINDOWS_UWP || WINDOWS_WSA await StartNewSession(); #else StartNewSession(); #endif if (IsEnabled()) { GAEvents.EnsureEventQueueIsRunning(); } }
public static void AddSessionStartEvent() { string categorySessionStart = CategorySessionStart; // Event specific data JSONClass eventDict = new JSONClass(); eventDict["category"] = categorySessionStart; // Increment session number and persist GAState.IncrementSessionNum(); GAStore.SetState(GAState.SessionNumKey, GAState.SessionNum.ToString(CultureInfo.InvariantCulture)); // Add custom dimensions AddDimensionsToEvent(eventDict); // Add to store AddEventToStore(eventDict); // Log GALogger.I("Add SESSION START event"); // Send event right away ProcessEvents(categorySessionStart, false); }
private static void FixMissingSessionEndEvents() { if (!GAState.IsEventSubmissionEnabled) { return; } // Get all sessions that are not current Dictionary <string, object> parameters = new Dictionary <string, object>(); parameters.Add("$session_id", GAState.SessionId); string sql = "SELECT timestamp, event FROM ga_session WHERE session_id != $session_id;"; JSONArray sessions = GAStore.ExecuteQuerySync(sql, parameters); if (sessions == null || sessions.Count == 0) { return; } GALogger.I(sessions.Count + " session(s) located with missing session_end event."); // Add missing session_end events for (int i = 0; i < sessions.Count; ++i) { JSONNode session = sessions[i]; JSONNode sessionEndEvent = null; try { sessionEndEvent = JSONNode.LoadFromBinaryBase64(session["event"].Value); } catch (Exception) { //GALogger.E("FixMissingSessionEndEvents: Error decoding json, " + e); } if (sessionEndEvent != null) { long event_ts = sessionEndEvent["client_ts"].AsLong; long start_ts = session["timestamp"].AsLong; long length = event_ts - start_ts; length = Math.Max(0, length); GALogger.D("fixMissingSessionEndEvents length calculated: " + length); sessionEndEvent["category"] = CategorySessionEnd; sessionEndEvent.Add("length", new JSONNumber(length)); // Add to store AddEventToStore(sessionEndEvent.AsObject); } else { GALogger.I("Problem decoding session_end event. Skipping this session_end event."); } } }
public static void AddSessionStartEvent() { if (!GAState.IsEventSubmissionEnabled) { return; } string categorySessionStart = CategorySessionStart; // Event specific data JSONObject eventDict = new JSONObject(); eventDict["category"] = categorySessionStart; // Increment session number and persist GAState.IncrementSessionNum(); GAStore.SetState(GAState.SessionNumKey, GAState.SessionNum.ToString(CultureInfo.InvariantCulture)); // Add custom dimensions AddDimensionsToEvent(eventDict); IDictionary <string, object> fieldsToUse = GAState.CurrentGlobalCustomEventFields; // Add custom fields AddFieldsToEvent(eventDict, GAState.ValidateAndCleanCustomFields(fieldsToUse)); // Add to store AddEventToStore(eventDict); // Log GALogger.I("Add SESSION START event"); // Send event right away ProcessEvents(categorySessionStart, false); }
public static void Initialize(string gameKey, string gameSecret) { #if WINDOWS_UWP || WINDOWS_WSA || WINDOWS_PHONE CoreApplication.Suspending += OnSuspending; CoreApplication.Resuming += OnResuming; #endif GADevice.UpdateConnectionType(); GAThreading.PerformTaskOnGAThread("initialize", () => { if (IsSdkReady(true, false)) { GALogger.W("SDK already initialized. Can only be called once."); return; } if (!GAValidator.ValidateKeys(gameKey, gameSecret)) { GALogger.W("SDK failed initialize. Game key or secret key is invalid. Can only contain characters A-z 0-9, gameKey is 32 length, gameSecret is 40 length. Failed keys - gameKey: " + gameKey + ", secretKey: " + gameSecret); return; } GAState.SetKeys(gameKey, gameSecret); if (!GAStore.EnsureDatabase(false)) { GALogger.W("Could not ensure/validate local event database: " + GADevice.WritablePath); } GAState.InternalInitialize(); }); }
public static void SetBirthYear(int birthYear) { Instance.BirthYear = birthYear; if (GAStore.IsTableReady) { GAStore.SetState(BirthYearKey, birthYear.ToString()); } GALogger.I("Set birth year: " + birthYear); }
public static void SetGender(EGAGender gender) { Instance.Gender = gender.ToString().ToLowerInvariant(); if (GAStore.IsTableReady) { GAStore.SetState(GenderKey, Instance.Gender); } GALogger.I("Set gender: " + gender); }
public static void SetFacebookId(string facebookId) { Instance.FacebookId = facebookId; if (GAStore.IsTableReady) { GAStore.SetState(FacebookIdKey, facebookId); } GALogger.I("Set facebook id: " + facebookId); }
public static void SetCustomDimension03(string dimension) { CurrentCustomDimension03 = dimension; if (GAStore.IsTableReady) { GAStore.SetState(Dimension03Key, dimension); } GALogger.I("Set custom03 dimension value: " + dimension); }
public static void AddBusinessEvent( string currency, int amount, string itemType, string itemId, string cartType, IDictionary <string, object> fields ) { if (!GAState.IsEventSubmissionEnabled) { return; } // Validate event params if (!GAValidator.ValidateBusinessEvent(currency, amount, cartType, itemType, itemId)) { //GAHTTPApi.Instance.SendSdkErrorEvent(EGASdkErrorType.Rejected); return; } // Create empty eventData JSONObject eventDict = new JSONObject(); // Increment transaction number and persist GAState.IncrementTransactionNum(); GAStore.SetState(GAState.TransactionNumKey, GAState.TransactionNum.ToString(CultureInfo.InvariantCulture)); // Required eventDict["event_id"] = itemType + ":" + itemId; eventDict["category"] = CategoryBusiness; eventDict["currency"] = currency; eventDict.Add("amount", new JSONNumber(amount)); eventDict.Add(GAState.TransactionNumKey, new JSONNumber(GAState.TransactionNum)); // Optional if (!string.IsNullOrEmpty(cartType)) { eventDict.Add("cart_type", cartType); } // Add custom dimensions AddDimensionsToEvent(eventDict); // Add custom fields AddFieldsToEvent(eventDict, GAState.ValidateAndCleanCustomFields(fields)); // Log GALogger.I("Add BUSINESS event: {currency:" + currency + ", amount:" + amount + ", itemType:" + itemType + ", itemId:" + itemId + ", cartType:" + cartType + "}"); // Send to store AddEventToStore(eventDict); }
private static void UpdateSessionTime() { if (GAState.SessionIsStarted()) { JSONClass ev = GAState.GetEventAnnotations(); string jsonDefaults = ev.SaveToBase64(); string sql = "INSERT OR REPLACE INTO ga_session(session_id, timestamp, event) VALUES($session_id, $timestamp, $event);"; Dictionary <string, object> parameters = new Dictionary <string, object>(); parameters.Add("$session_id", ev["session_id"].Value); parameters.Add("$timestamp", GAState.SessionStart); parameters.Add("$event", jsonDefaults); GAStore.ExecuteQuerySync(sql, parameters); } }
public static void ProcessEvents(EGAHTTPApiResponse responseEnum, JSONNode dataDict, string putbackSql, string deleteSql, int eventCount) { if (responseEnum == EGAHTTPApiResponse.Ok) { // Delete events GAStore.ExecuteQuerySync(deleteSql); GALogger.I("Event queue: " + eventCount + " events sent."); } else { // Put events back (Only in case of no response) if (responseEnum == EGAHTTPApiResponse.NoResponse) { GALogger.W("Event queue: Failed to send events to collector - Retrying next time"); GAStore.ExecuteQuerySync(putbackSql); // Delete events (When getting some anwser back always assume events are processed) } else { if (dataDict != null) { JSONNode json = null; IEnumerator <JSONNode> enumerator = dataDict.Childs.GetEnumerator(); if (enumerator.MoveNext()) { json = enumerator.Current; } if (responseEnum == EGAHTTPApiResponse.BadRequest && json is JSONArray) { GALogger.W("Event queue: " + eventCount + " events sent. " + dataDict.Count + " events failed GA server validation."); } else { GALogger.W("Event queue: Failed to send events."); } } else { GALogger.W("Event queue: Failed to send events."); } GAStore.ExecuteQuerySync(deleteSql); } } UpdateSessionTime(); }
#pragma warning disable 0162 public static void IncrementProgressionTries(string progression) { int tries = GetProgressionTries(progression) + 1; Instance.progressionTries[progression] = tries; if (GAStore.InMemory) { GALogger.D("Trying to IncrementProgressionTries with InMemory=true - cannot. Skipping."); } else { // Persist Dictionary <string, object> parms = new Dictionary <string, object>(); parms.Add("$progression", progression); parms.Add("$tries", tries); GAStore.ExecuteQuerySync("INSERT OR REPLACE INTO ga_progression (progression, tries) VALUES($progression, $tries);", parms); } }
#pragma warning disable 0162 public static void ClearProgressionTries(string progression) { Dictionary <string, int> progressionTries = Instance.progressionTries; if (progressionTries.ContainsKey(progression)) { progressionTries.Remove(progression); } if (GAStore.InMemory) { GALogger.D("Trying to ClearProgressionTries with InMemory=true - cannot. Skipping."); } else { // Delete Dictionary <string, object> parms = new Dictionary <string, object>(); parms.Add("$progression", progression); GAStore.ExecuteQuerySync("DELETE FROM ga_progression WHERE progression = $progression;", parms); } }
private static void UpdateSessionTime() { if (GAState.SessionIsStarted()) { JSONObject ev = GAState.GetEventAnnotations(); // Add custom dimensions AddDimensionsToEvent(ev); IDictionary <string, object> fieldsToUse = GAState.CurrentGlobalCustomEventFields; // Add custom fields AddFieldsToEvent(ev, GAState.ValidateAndCleanCustomFields(fieldsToUse)); string jsonDefaults = ev.SaveToBinaryBase64(); string sql = "INSERT OR REPLACE INTO ga_session(session_id, timestamp, event) VALUES($session_id, $timestamp, $event);"; Dictionary <string, object> parameters = new Dictionary <string, object>(); parameters.Add("$session_id", ev["session_id"].Value); parameters.Add("$timestamp", GAState.SessionStart); parameters.Add("$event", jsonDefaults); GAStore.ExecuteQuerySync(sql, parameters); } }
private static void FixMissingSessionEndEvents() { // Get all sessions that are not current Dictionary <string, object> parameters = new Dictionary <string, object>(); parameters.Add("$session_id", GAState.SessionId); string sql = "SELECT timestamp, event FROM ga_session WHERE session_id != $session_id;"; JSONArray sessions = GAStore.ExecuteQuerySync(sql, parameters); if (sessions == null) { return; } GALogger.I(sessions.Count + " session(s) located with missing session_end event."); // Add missing session_end events for (int i = 0; i < sessions.Count; ++i) { JSONNode session = sessions[i]; JSONNode sessionEndEvent = JSONNode.LoadFromBase64(session["event"].AsString); long event_ts = sessionEndEvent["client_ts"].AsLong; long start_ts = session["timestamp"].AsLong; long length = event_ts - start_ts; length = Math.Max(0, length); GALogger.D("fixMissingSessionEndEvents length calculated: " + length); sessionEndEvent["category"] = CategorySessionEnd; sessionEndEvent.Add("length", new JSONData(length)); // Add to store AddEventToStore(sessionEndEvent.AsObject); } }
private static void AddEventToStore(JSONClass eventData) #endif { // Check if datastore is available if (!GAStore.IsTableReady) { GALogger.W("Could not add event: SDK datastore error"); return; } // Check if we are initialized if (!GAState.Initialized) { GALogger.W("Could not add event: SDK is not initialized"); return; } try { // Check db size limits (10mb) // If database is too large block all except user, session and business if (GAStore.IsDbTooLargeForEvents && !GAUtilities.StringMatch(eventData["category"].AsString, "^(user|session_end|business)$")) { GALogger.W("Database too large. Event has been blocked."); return; } // Get default annotations JSONClass ev = GAState.GetEventAnnotations(); // Create json with only default annotations string jsonDefaults = ev.SaveToBase64(); // Merge with eventData foreach (KeyValuePair <string, JSONNode> pair in eventData) { ev.Add(pair.Key, pair.Value); } // Create json string representation string json = ev.ToString(); // output if VERBOSE LOG enabled GALogger.II("Event added to queue: " + json); // Add to store Dictionary <string, object> parameters = new Dictionary <string, object>(); parameters.Add("$status", "new"); parameters.Add("$category", ev["category"].Value); parameters.Add("$session_id", ev["session_id"].Value); parameters.Add("$client_ts", ev["client_ts"].Value); parameters.Add("$event", ev.SaveToBase64()); string sql = "INSERT INTO ga_events (status, category, session_id, client_ts, event) VALUES($status, $category, $session_id, $client_ts, $event);"; GAStore.ExecuteQuerySync(sql, parameters); // Add to session store if not last if (eventData["category"].AsString.Equals(CategorySessionEnd)) { parameters.Clear(); parameters.Add("$session_id", ev["session_id"].Value); sql = "DELETE FROM ga_session WHERE session_id = $session_id;"; GAStore.ExecuteQuerySync(sql, parameters); } else { sql = "INSERT OR REPLACE INTO ga_session(session_id, timestamp, event) VALUES($session_id, $timestamp, $event);"; parameters.Clear(); parameters.Add("$session_id", ev["session_id"].Value); parameters.Add("$timestamp", GAState.SessionStart); parameters.Add("$event", jsonDefaults); GAStore.ExecuteQuerySync(sql, parameters); } } catch (Exception e) { GALogger.E("addEventToStoreWithEventData: error using json"); GALogger.E(e.ToString()); } }
private static void CleanupEvents() { GAStore.ExecuteQuerySync("UPDATE ga_events SET status = 'new';"); }
private static void ProcessEvents(string category, bool performCleanUp) #endif { try { string requestIdentifier = Guid.NewGuid().ToString(); string selectSql; string updateSql; string deleteSql = "DELETE FROM ga_events WHERE status = '" + requestIdentifier + "'"; string putbackSql = "UPDATE ga_events SET status = 'new' WHERE status = '" + requestIdentifier + "';"; // Cleanup if (performCleanUp) { CleanupEvents(); FixMissingSessionEndEvents(); } // Prepare SQL string andCategory = ""; if (!string.IsNullOrEmpty(category)) { andCategory = " AND category='" + category + "' "; } selectSql = "SELECT event FROM ga_events WHERE status = 'new' " + andCategory + ";"; updateSql = "UPDATE ga_events SET status = '" + requestIdentifier + "' WHERE status = 'new' " + andCategory + ";"; // Get events to process JSONArray events = GAStore.ExecuteQuerySync(selectSql); // Check for errors or empty if (events == null) { GALogger.I("Event queue: No events to send"); return; } // Check number of events and take some action if there are too many? if (events.Count > MaxEventCount) { // Make a limit request selectSql = "SELECT client_ts FROM ga_events WHERE status = 'new' " + andCategory + " ORDER BY client_ts ASC LIMIT 0," + MaxEventCount + ";"; events = GAStore.ExecuteQuerySync(selectSql); if (events == null) { return; } // Get last timestamp JSONNode lastItem = events[events.Count - 1]; string lastTimestamp = lastItem["client_ts"].AsString; // Select again selectSql = "SELECT event FROM ga_events WHERE status = 'new' " + andCategory + " AND client_ts<='" + lastTimestamp + "';"; events = GAStore.ExecuteQuerySync(selectSql); if (events == null) { return; } // Update sql updateSql = "UPDATE ga_events SET status='" + requestIdentifier + "' WHERE status='new' " + andCategory + " AND client_ts<='" + lastTimestamp + "';"; } // Log GALogger.I("Event queue: Sending " + events.Count + " events."); // Set status of events to 'sending' (also check for error) if (GAStore.ExecuteQuerySync(updateSql) == null) { return; } // Create payload data from events List <JSONNode> payloadArray = new List <JSONNode>(); for (int i = 0; i < events.Count; ++i) { JSONNode ev = events[i]; JSONNode eventDict = JSONNode.LoadFromBase64(ev["event"].AsString); if (eventDict.Count != 0) { payloadArray.Add(eventDict); } } // send events #if WINDOWS_UWP || WINDOWS_WSA KeyValuePair <EGAHTTPApiResponse, JSONNode> result = await GAHTTPApi.Instance.SendEventsInArray(payloadArray); #else KeyValuePair <EGAHTTPApiResponse, JSONNode> result = GAHTTPApi.Instance.SendEventsInArray(payloadArray); #endif ProcessEvents(result.Key, result.Value, putbackSql, deleteSql, payloadArray.Count); } catch (Exception e) { GALogger.E("Error during ProcessEvents(): " + e); } }
#pragma warning disable 0162 private static void EnsurePersistedStates() { if (GAStore.InMemory) { #if UNITY GALogger.D("retrieving persisted states from local PlayerPrefs"); GAState instance = GAState.Instance; instance.DefaultUserId = UnityEngine.PlayerPrefs.GetString(InMemoryPrefix + SessionNumKey, Guid.NewGuid().ToString()); { int tmp; int.TryParse(UnityEngine.PlayerPrefs.GetString(InMemoryPrefix + SessionNumKey, "0"), out tmp); SessionNum = tmp; } { int tmp; int.TryParse(UnityEngine.PlayerPrefs.GetString(InMemoryPrefix + TransactionNumKey, "0"), out tmp); TransactionNum = tmp; } if (!string.IsNullOrEmpty(instance.FacebookId)) { UnityEngine.PlayerPrefs.SetString(InMemoryPrefix + FacebookIdKey, instance.FacebookId); } else { instance.FacebookId = UnityEngine.PlayerPrefs.GetString(InMemoryPrefix + FacebookIdKey, ""); } if (!string.IsNullOrEmpty(instance.Gender)) { UnityEngine.PlayerPrefs.SetString(InMemoryPrefix + GenderKey, instance.Gender); } else { instance.Gender = UnityEngine.PlayerPrefs.GetString(InMemoryPrefix + GenderKey, ""); } if (instance.BirthYear != 0) { UnityEngine.PlayerPrefs.SetString(InMemoryPrefix + BirthYearKey, instance.BirthYear.ToString()); } else { int tmp; int.TryParse(UnityEngine.PlayerPrefs.GetString(InMemoryPrefix + BirthYearKey, "0"), out tmp); instance.BirthYear = tmp; } if (!string.IsNullOrEmpty(CurrentCustomDimension01)) { UnityEngine.PlayerPrefs.SetString(InMemoryPrefix + Dimension01Key, CurrentCustomDimension01); } else { CurrentCustomDimension01 = UnityEngine.PlayerPrefs.GetString(InMemoryPrefix + Dimension01Key, ""); } if (!string.IsNullOrEmpty(CurrentCustomDimension02)) { UnityEngine.PlayerPrefs.SetString(InMemoryPrefix + Dimension02Key, CurrentCustomDimension02); } else { CurrentCustomDimension02 = UnityEngine.PlayerPrefs.GetString(InMemoryPrefix + Dimension02Key, ""); } if (!string.IsNullOrEmpty(CurrentCustomDimension03)) { UnityEngine.PlayerPrefs.SetString(InMemoryPrefix + Dimension03Key, CurrentCustomDimension03); } else { CurrentCustomDimension03 = UnityEngine.PlayerPrefs.GetString(InMemoryPrefix + Dimension03Key, ""); } string sdkConfigCachedString = UnityEngine.PlayerPrefs.GetString(InMemoryPrefix + SdkConfigCachedKey, ""); if (!string.IsNullOrEmpty(sdkConfigCachedString)) { // decode JSON JSONNode sdkConfigCached = null; try { sdkConfigCached = JSONNode.LoadFromBinaryBase64(sdkConfigCachedString); } catch (Exception) { //GALogger.E("EnsurePersistedStates: Error decoding json, " + e); } if (sdkConfigCached != null && sdkConfigCached.Count != 0) { instance.SdkConfigCached = sdkConfigCached; } } #else GALogger.W("EnsurePersistedStates: No implementation yet for InMemory=true"); #endif } else { // get and extract stored states JSONObject state_dict = new JSONObject(); JSONArray results_ga_state = GAStore.ExecuteQuerySync("SELECT * FROM ga_state;"); if (results_ga_state != null && results_ga_state.Count != 0) { for (int i = 0; i < results_ga_state.Count; ++i) { JSONNode result = results_ga_state[i]; state_dict.Add(result["key"], result["value"]); } } // insert into GAState instance GAState instance = GAState.Instance; instance.DefaultUserId = state_dict[DefaultUserIdKey] != null ? state_dict[DefaultUserIdKey].Value : Guid.NewGuid().ToString(); SessionNum = state_dict[SessionNumKey] != null ? state_dict[SessionNumKey].AsInt : 0; TransactionNum = state_dict[TransactionNumKey] != null ? state_dict[TransactionNumKey].AsInt : 0; // restore cross session user values if (!string.IsNullOrEmpty(instance.FacebookId)) { GAStore.SetState(FacebookIdKey, instance.FacebookId); } else { instance.FacebookId = state_dict[FacebookIdKey] != null ? state_dict[FacebookIdKey].Value : ""; if (!string.IsNullOrEmpty(instance.FacebookId)) { GALogger.D("facebookid found in DB: " + instance.FacebookId); } } if (!string.IsNullOrEmpty(instance.Gender)) { GAStore.SetState(GenderKey, instance.Gender); } else { instance.Gender = state_dict[GenderKey] != null ? state_dict[GenderKey].Value : ""; if (!string.IsNullOrEmpty(instance.Gender)) { GALogger.D("gender found in DB: " + instance.Gender); } } if (instance.BirthYear != 0) { GAStore.SetState(BirthYearKey, instance.BirthYear.ToString()); } else { instance.BirthYear = state_dict[BirthYearKey] != null ? state_dict[BirthYearKey].AsInt : 0; if (instance.BirthYear != 0) { GALogger.D("birthYear found in DB: " + instance.BirthYear); } } // restore dimension settings if (!string.IsNullOrEmpty(CurrentCustomDimension01)) { GAStore.SetState(Dimension01Key, CurrentCustomDimension01); } else { CurrentCustomDimension01 = state_dict[Dimension01Key] != null ? state_dict[Dimension01Key].Value : ""; if (!string.IsNullOrEmpty(CurrentCustomDimension01)) { GALogger.D("Dimension01 found in cache: " + CurrentCustomDimension01); } } if (!string.IsNullOrEmpty(CurrentCustomDimension02)) { GAStore.SetState(Dimension02Key, CurrentCustomDimension02); } else { CurrentCustomDimension02 = state_dict[Dimension02Key] != null ? state_dict[Dimension02Key].Value : ""; if (!string.IsNullOrEmpty(CurrentCustomDimension02)) { GALogger.D("Dimension02 found in cache: " + CurrentCustomDimension02); } } if (!string.IsNullOrEmpty(CurrentCustomDimension03)) { GAStore.SetState(Dimension03Key, CurrentCustomDimension03); } else { CurrentCustomDimension03 = state_dict[Dimension03Key] != null ? state_dict[Dimension03Key].Value : ""; if (!string.IsNullOrEmpty(CurrentCustomDimension03)) { GALogger.D("Dimension03 found in cache: " + CurrentCustomDimension03); } } // get cached init call values string sdkConfigCachedString = state_dict[SdkConfigCachedKey] != null ? state_dict[SdkConfigCachedKey].Value : ""; if (!string.IsNullOrEmpty(sdkConfigCachedString)) { // decode JSON JSONNode sdkConfigCached = null; try { sdkConfigCached = JSONNode.LoadFromBinaryBase64(sdkConfigCachedString); } catch (Exception) { //GALogger.E("EnsurePersistedStates: Error decoding json, " + e); } if (sdkConfigCached != null && sdkConfigCached.Count != 0) { instance.SdkConfigCached = sdkConfigCached; } } JSONArray results_ga_progression = GAStore.ExecuteQuerySync("SELECT * FROM ga_progression;"); if (results_ga_progression != null && results_ga_progression.Count != 0) { for (int i = 0; i < results_ga_progression.Count; ++i) { JSONNode result = results_ga_progression[i]; if (result != null && result.Count != 0) { instance.progressionTries[result["progression"].Value] = result["tries"].AsInt; } } } } }
public static void StartNewSession(EGAHTTPApiResponse initResponse, JSONObject initResponseDict) { // init is ok if (initResponse == EGAHTTPApiResponse.Ok && initResponseDict != null) { // set the time offset - how many seconds the local time is different from servertime long timeOffsetSeconds = 0; if (initResponseDict["server_ts"] != null) { long serverTs = initResponseDict["server_ts"].AsLong; timeOffsetSeconds = CalculateServerTimeOffset(serverTs); } initResponseDict.Add("time_offset", new JSONNumber(timeOffsetSeconds)); // insert new config in sql lite cross session storage GAStore.SetState(SdkConfigCachedKey, initResponseDict.SaveToBinaryBase64()); // set new config and cache in memory Instance.sdkConfigCached = initResponseDict; Instance.sdkConfig = initResponseDict; Instance.InitAuthorized = true; } else if (initResponse == EGAHTTPApiResponse.Unauthorized) { GALogger.W("Initialize SDK failed - Unauthorized"); Instance.InitAuthorized = false; } else { // log the status if no connection if (initResponse == EGAHTTPApiResponse.NoResponse || initResponse == EGAHTTPApiResponse.RequestTimeout) { GALogger.I("Init call (session start) failed - no response. Could be offline or timeout."); } else if (initResponse == EGAHTTPApiResponse.BadResponse || initResponse == EGAHTTPApiResponse.JsonEncodeFailed || initResponse == EGAHTTPApiResponse.JsonDecodeFailed) { GALogger.I("Init call (session start) failed - bad response. Could be bad response from proxy or GA servers."); } else if (initResponse == EGAHTTPApiResponse.BadRequest || initResponse == EGAHTTPApiResponse.UnknownResponseCode) { GALogger.I("Init call (session start) failed - bad request or unknown response."); } // init call failed (perhaps offline) if (Instance.sdkConfig == null) { if (Instance.sdkConfigCached != null) { GALogger.I("Init call (session start) failed - using cached init values."); // set last cross session stored config init values Instance.sdkConfig = Instance.sdkConfigCached; } else { GALogger.I("Init call (session start) failed - using default init values."); // set default init values Instance.sdkConfig = Instance.sdkConfigDefault; } } else { GALogger.I("Init call (session start) failed - using cached init values."); } Instance.InitAuthorized = true; } { JSONNode currentSdkConfig = SdkConfig; if (currentSdkConfig["enabled"].IsBoolean && !currentSdkConfig["enabled"].AsBool) { Instance.Enabled = false; } else if (!Instance.InitAuthorized) { Instance.Enabled = false; } else { Instance.Enabled = true; } } // set offset in state (memory) from current config (config could be from cache etc.) Instance.ClientServerTimeOffset = SdkConfig["time_offset"] != null ? SdkConfig["time_offset"].AsLong : 0; // populate configurations PopulateConfigurations(SdkConfig); // if SDK is disabled in config if (!IsEnabled()) { GALogger.W("Could not start session: SDK is disabled."); // stop event queue // + make sure it's able to restart if another session detects it's enabled again GAEvents.StopEventQueue(); return; } else { GAEvents.EnsureEventQueueIsRunning(); } // generate the new session string newSessionId = Guid.NewGuid().ToString(); string newSessionIdLowercase = newSessionId.ToLowerInvariant(); // Set session id SessionId = newSessionIdLowercase; // Set session start SessionStart = GetClientTsAdjusted(); // Add session start event GAEvents.AddSessionStartEvent(); }