public static void Run() { GALogger.D("Starting GA thread"); try { while (shouldThreadrun) { TimedBlock timedBlock; while ((timedBlock = GetNextBlock()) != null) { if (!timedBlock.ignore) { timedBlock.block(); } } #if WINDOWS_WSA || WINDOWS_UWP || WINDOWS_PHONE Task.Delay(1000).Wait(); #else Thread.Sleep(ThreadWaitTimeInMs); #endif } } catch (Exception e) { GALogger.E("Error on GA thread"); GALogger.E(e.ToString()); } GALogger.D("Ending GA thread"); }
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]; try { JSONNode sessionEndEvent = JSONNode.LoadFromBase64(session["event"].Value); 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); } catch (Exception e) { GALogger.E("FixMissingSessionEndEvents: Error decoding json, " + e); } } }
public KeyValuePair <EGAHTTPApiResponse, JSONNode> SendEventsInArray(List <JSONNode> eventArray) #endif { JSONNode json; if (eventArray.Count == 0) { GALogger.D("sendEventsInArray called with missing eventArray"); } EGAHTTPApiResponse result = EGAHTTPApiResponse.NoResponse; string gameKey = GAState.GameKey; // Generate URL string url = baseUrl + "/" + gameKey + "/" + eventsUrlPath; GALogger.D("Sending 'events' URL: " + url); // make JSON string from data string JSONstring = GAUtilities.ArrayOfObjectsToJsonString(eventArray); if (JSONstring.Length == 0) { GALogger.D("sendEventsInArray JSON encoding failed of eventArray"); json = null; result = EGAHTTPApiResponse.JsonEncodeFailed; return(new KeyValuePair <EGAHTTPApiResponse, JSONNode>(result, json)); } string body = ""; HttpStatusCode responseCode = (HttpStatusCode)0; string responseDescription = ""; string authorization = ""; try { byte[] payloadData = CreatePayloadData(JSONstring, useGzip); HttpWebRequest request = CreateRequest(url, payloadData, useGzip); authorization = request.Headers[HttpRequestHeader.Authorization]; #if WINDOWS_UWP || WINDOWS_WSA using (Stream dataStream = await request.GetRequestStreamAsync()) #else using (Stream dataStream = request.GetRequestStream()) #endif { dataStream.Write(payloadData, 0, payloadData.Length); } #if WINDOWS_UWP || WINDOWS_WSA using (HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse) #else using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) #endif { using (Stream dataStream = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(dataStream)) { string responseString = reader.ReadToEnd(); responseCode = response.StatusCode; responseDescription = response.StatusDescription; // print result body = responseString; } } } } catch (WebException e) { if (e.Response != null) { using (HttpWebResponse response = (HttpWebResponse)e.Response) { using (Stream streamResponse = response.GetResponseStream()) { using (StreamReader streamRead = new StreamReader(streamResponse)) { string responseString = streamRead.ReadToEnd(); responseCode = response.StatusCode; responseDescription = response.StatusDescription; body = responseString; } } } } } catch (Exception e) { GALogger.E(e.ToString()); } GALogger.D("events request content: " + body); EGAHTTPApiResponse requestResponseEnum = ProcessRequestResponse(responseCode, responseDescription, body, "Events"); // if not 200 result if (requestResponseEnum != EGAHTTPApiResponse.Ok && requestResponseEnum != EGAHTTPApiResponse.BadRequest) { GALogger.D("Failed events Call. URL: " + url + ", Authorization: " + authorization + ", JSONString: " + JSONstring); json = null; result = requestResponseEnum; return(new KeyValuePair <EGAHTTPApiResponse, JSONNode>(result, json)); } // decode JSON JSONNode requestJsonDict = JSON.Parse(body); if (requestJsonDict == null) { json = null; result = EGAHTTPApiResponse.JsonDecodeFailed; return(new KeyValuePair <EGAHTTPApiResponse, JSONNode>(result, json)); } // print reason if bad request if (requestResponseEnum == EGAHTTPApiResponse.BadRequest) { GALogger.D("Failed Events Call. Bad request. Response: " + requestJsonDict.ToString()); } // return response json = requestJsonDict; result = requestResponseEnum; return(new KeyValuePair <EGAHTTPApiResponse, JSONNode>(result, json)); }
public KeyValuePair <EGAHTTPApiResponse, JSONClass> RequestInitReturningDict() #endif { JSONClass json; EGAHTTPApiResponse result = EGAHTTPApiResponse.NoResponse; string gameKey = GAState.GameKey; // Generate URL string url = baseUrl + "/" + gameKey + "/" + initializeUrlPath; GALogger.D("Sending 'init' URL: " + url); JSONClass initAnnotations = GAState.GetInitAnnotations(); // make JSON string from data string JSONstring = initAnnotations.ToString(); if (string.IsNullOrEmpty(JSONstring)) { result = EGAHTTPApiResponse.JsonEncodeFailed; json = null; return(new KeyValuePair <EGAHTTPApiResponse, JSONClass>(result, json)); } string body = ""; HttpStatusCode responseCode = (HttpStatusCode)0; string responseDescription = ""; string authorization = ""; try { byte[] payloadData = CreatePayloadData(JSONstring, useGzip); HttpWebRequest request = CreateRequest(url, payloadData, useGzip); authorization = request.Headers[HttpRequestHeader.Authorization]; #if WINDOWS_UWP || WINDOWS_WSA using (Stream dataStream = await request.GetRequestStreamAsync()) #else using (Stream dataStream = request.GetRequestStream()) #endif { dataStream.Write(payloadData, 0, payloadData.Length); } #if WINDOWS_UWP || WINDOWS_WSA using (HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse) #else using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) #endif { using (Stream dataStream = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(dataStream)) { string responseString = reader.ReadToEnd(); responseCode = response.StatusCode; responseDescription = response.StatusDescription; // print result body = responseString; } } } } catch (WebException e) { if (e.Response != null) { using (HttpWebResponse response = (HttpWebResponse)e.Response) { using (Stream streamResponse = response.GetResponseStream()) { using (StreamReader streamRead = new StreamReader(streamResponse)) { string responseString = streamRead.ReadToEnd(); responseCode = response.StatusCode; responseDescription = response.StatusDescription; body = responseString; } } } } } catch (Exception e) { GALogger.E(e.ToString()); } // process the response GALogger.D("init request content : " + body); JSONNode requestJsonDict = JSON.Parse(body); EGAHTTPApiResponse requestResponseEnum = ProcessRequestResponse(responseCode, responseDescription, body, "Init"); // if not 200 result if (requestResponseEnum != EGAHTTPApiResponse.Ok && requestResponseEnum != EGAHTTPApiResponse.BadRequest) { GALogger.D("Failed Init Call. URL: " + url + ", Authorization: " + authorization + ", JSONString: " + JSONstring); result = requestResponseEnum; json = null; return(new KeyValuePair <EGAHTTPApiResponse, JSONClass>(result, json)); } if (requestJsonDict == null) { GALogger.D("Failed Init Call. Json decoding failed"); result = EGAHTTPApiResponse.JsonDecodeFailed; json = null; return(new KeyValuePair <EGAHTTPApiResponse, JSONClass>(result, json)); } // print reason if bad request if (requestResponseEnum == EGAHTTPApiResponse.BadRequest) { GALogger.D("Failed Init Call. Bad request. Response: " + requestJsonDict.AsObject.ToString()); // return bad request result result = requestResponseEnum; json = null; return(new KeyValuePair <EGAHTTPApiResponse, JSONClass>(result, json)); } // validate Init call values JSONClass validatedInitValues = GAValidator.ValidateAndCleanInitRequestResponse(requestJsonDict); if (validatedInitValues == null) { result = EGAHTTPApiResponse.BadResponse; json = null; return(new KeyValuePair <EGAHTTPApiResponse, JSONClass>(result, json)); } // all ok result = EGAHTTPApiResponse.Ok; json = validatedInitValues; return(new KeyValuePair <EGAHTTPApiResponse, JSONClass>(result, json)); }
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 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); } }
public static JSONArray ExecuteQuerySync(string sql, Dictionary <string, object> parameters, bool useTransaction) { // Force transaction if it is an update, insert or delete. if (GAUtilities.StringMatch(sql.ToUpperInvariant(), "^(UPDATE|INSERT|DELETE)")) { useTransaction = true; } // Get database connection from singelton sharedInstance SqliteConnection sqlDatabasePtr = Instance.SqlDatabase; // Create mutable array for results JSONArray results = new JSONArray(); SqliteTransaction transaction = null; SqliteCommand command = null; try { if (useTransaction) { transaction = sqlDatabasePtr.BeginTransaction(); } command = sqlDatabasePtr.CreateCommand(); if (useTransaction) { command.Transaction = transaction; } command.CommandText = sql; command.Prepare(); // Bind parameters if (parameters.Count != 0) { foreach (KeyValuePair <string, object> pair in parameters) { command.Parameters.AddWithValue(pair.Key, pair.Value); } } using (SqliteDataReader reader = command.ExecuteReader()) { // Loop through results while (reader.Read()) { // get columns count int columnCount = reader.FieldCount; JSONObject row = new JSONObject(); for (int i = 0; i < columnCount; i++) { string column = reader.GetName(i); if (string.IsNullOrEmpty(column)) { continue; } row[column] = reader.GetValue(i).ToString(); } results.Add(row); } } if (useTransaction) { transaction.Commit(); } } catch (SqliteException e) { // TODO(nikolaj): Should we do a db validation to see if the db is corrupt here? GALogger.E("SQLITE3 ERROR: " + e); results = null; if (useTransaction) { if (transaction != null) { try { transaction.Rollback(); } catch (SqliteException ex) { GALogger.E("SQLITE3 ROLLBACK ERROR: " + ex); } finally { transaction.Dispose(); } } } } finally { if (command != null) { command.Dispose(); } if (transaction != null) { transaction.Dispose(); } } // Return results return(results); }
protected void DoInBackground(string url) #endif { if (!countMap.ContainsKey(this.type)) { countMap.Add(this.type, 0); } if (countMap[this.type] >= MaxCount) { return; } HttpStatusCode responseCode = (HttpStatusCode)0; string responseDescription = ""; try { HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest; request.Method = "POST"; #if WINDOWS_UWP || WINDOWS_WSA || WINDOWS_PHONE request.Headers[HttpRequestHeader.ContentLength] = this.payloadData.Length.ToString(); #else request.ContentLength = payloadData.Length; #endif request.Headers[HttpRequestHeader.Authorization] = this.hashHmac; request.ContentType = "application/json"; #if WINDOWS_UWP || WINDOWS_WSA using (Stream dataStream = await request.GetRequestStreamAsync()) #elif WINDOWS_PHONE using (Stream dataStream = await Task.Factory.FromAsync <Stream>(request.BeginGetRequestStream, request.EndGetRequestStream, null)) #else using (Stream dataStream = request.GetRequestStream()) #endif { dataStream.Write(this.payloadData, 0, payloadData.Length); } #if WINDOWS_UWP || WINDOWS_WSA using (HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse) #elif WINDOWS_PHONE using (WebResponse response = await Task.Factory.FromAsync <WebResponse>(request.BeginGetResponse, request.EndGetResponse, null)) #else using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) #endif { using (Stream dataStream = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(dataStream)) { string responseString = reader.ReadToEnd(); body = responseString; } } } } catch (WebException e) { if (e.Response != null) { using (HttpWebResponse response = (HttpWebResponse)e.Response) { using (Stream streamResponse = response.GetResponseStream()) { using (StreamReader streamRead = new StreamReader(streamResponse)) { string responseString = streamRead.ReadToEnd(); responseCode = response.StatusCode; responseDescription = response.StatusDescription; body = responseString; } } } } } catch (Exception e) { GALogger.E(e.ToString()); } // process the response GALogger.D("sdk error request content : " + body); OnPostExecute(responseCode, responseDescription); }
public static JSONArray ExecuteQuerySync(string sql, Dictionary <string, object> parameters, bool useTransaction) { #if !UNITY_EDITOR // Force transaction if it is an update, insert or delete. if (GAUtilities.StringMatch(sql.ToUpperInvariant(), "^(UPDATE|INSERT|DELETE)")) { useTransaction = true; } // Get database connection from singelton sharedInstance SqliteConnection sqlDatabasePtr = Instance.SqlDatabase; // Create mutable array for results JSONArray results = new JSONArray(); SqliteCommand command = null; try { if (useTransaction) { sqlDatabasePtr.BeginTransaction(); } command = sqlDatabasePtr.CreateCommand(); command.CommandText = sql; // Bind parameters if (parameters.Count != 0) { foreach (KeyValuePair <string, object> pair in parameters) { command.Bind(pair.Key, pair.Value); } } // Loop through results foreach (List <Tuple <string, string> > reader in command.ExecuteQueryMY()) { // get columns count int columnCount = reader.Count; JSONClass row = new JSONClass(); for (int i = 0; i < columnCount; i++) { string column = reader[i].Item1; if (string.IsNullOrEmpty(column)) { continue; } row[column] = reader[i].Item2.ToString(); } results.Add(row); } if (useTransaction) { //transaction.Commit(); sqlDatabasePtr.Commit(); } } catch (SqliteException e) { // TODO(nikolaj): Should we do a db validation to see if the db is corrupt here? GALogger.E("SQLITE3 ERROR: " + e); results = null; } finally { } // Return results return(results); #else return(null); #endif }
#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.LoadFromBase64(sdkConfigCachedString); } catch (Exception e) { 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 try { JSONNode sdkConfigCached = JSONNode.LoadFromBase64(sdkConfigCachedString); if (sdkConfigCached != null && sdkConfigCached.Count != 0) { instance.SdkConfigCached = sdkConfigCached; } } catch (Exception e) { GALogger.E("EnsurePersistedStates: Error decoding json, " + e); } } 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; } } } } }