Skip to content

Commit

Permalink
Customize player preferences (#128)
Browse files Browse the repository at this point in the history
* allowing the user to supply a custom preferences source, since PlayerPrefs require running in the main thread

* using C# random generator so it will be accessible to other threads
  • Loading branch information
eronnen authored Apr 21, 2022
1 parent 58ba136 commit 9b3e663
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 36 deletions.
7 changes: 4 additions & 3 deletions Mixpanel/Controller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -351,17 +351,18 @@ internal static class Metadata
{
private static Int32 _eventCounter = 0, _peopleCounter = 0, _sessionStartEpoch;
private static String _sessionID;
private static System.Random _random = new System.Random(Guid.NewGuid().GetHashCode());

internal static void InitSession() {
_eventCounter = 0;
_peopleCounter = 0;
_sessionID = Convert.ToString(UnityEngine.Random.Range(0, Int32.MaxValue), 16);
_sessionID = Convert.ToString(_random.Next(0, Int32.MaxValue), 16);
_sessionStartEpoch = (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
}
internal static Value GetEventMetadata() {
Value eventMetadata = new Value
{
{"$mp_event_id", Convert.ToString(UnityEngine.Random.Range(0, Int32.MaxValue), 16)},
{"$mp_event_id", Convert.ToString(_random.Next(0, Int32.MaxValue), 16)},
{"$mp_session_id", _sessionID},
{"$mp_session_seq_id", _eventCounter},
{"$mp_session_start_sec", _sessionStartEpoch}
Expand All @@ -373,7 +374,7 @@ internal static Value GetEventMetadata() {
internal static Value GetPeopleMetadata() {
Value peopleMetadata = new Value
{
{"$mp_event_id", Convert.ToString(UnityEngine.Random.Range(0, Int32.MaxValue), 16)},
{"$mp_event_id", Convert.ToString(_random.Next(0, Int32.MaxValue), 16)},
{"$mp_session_id", _sessionID},
{"$mp_session_seq_id", _peopleCounter},
{"$mp_session_start_sec", _sessionStartEpoch}
Expand Down
15 changes: 15 additions & 0 deletions Mixpanel/IPreferences.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

namespace mixpanel
{
public interface IPreferences
{
void DeleteKey(string key);
int GetInt(string key);
int GetInt(string key, int defaultValue);
string GetString(string key);
string GetString(string key, string defaultValue);
bool HasKey(string key);
void SetInt(string key, int value);
void SetString(string key, string value);
}
}
11 changes: 11 additions & 0 deletions Mixpanel/IPreferences.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

52 changes: 52 additions & 0 deletions Mixpanel/PlayerPreferences.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using UnityEngine;

namespace mixpanel
{
public class PlayerPreferences : IPreferences
{
public void DeleteKey(string key)
{
PlayerPrefs.DeleteKey(key);
}

public float GetFloat(string key)
{
return PlayerPrefs.GetFloat(key);
}

public int GetInt(string key)
{
return PlayerPrefs.GetInt(key);
}

public int GetInt(string key, int defaultValue)
{
return PlayerPrefs.GetInt(key, defaultValue);
}

public string GetString(string key)
{
return PlayerPrefs.GetString(key);
}

public string GetString(string key, string defaultValue)
{
return PlayerPrefs.GetString(key, defaultValue);
}

public bool HasKey(string key)
{
return PlayerPrefs.HasKey(key);
}

public void SetInt(string key, int value)
{
PlayerPrefs.SetInt(key, value);
}

public void SetString(string key, string value)
{
PlayerPrefs.SetString(key, value);
}
}
}
11 changes: 11 additions & 0 deletions Mixpanel/PlayerPreferences.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

76 changes: 43 additions & 33 deletions Mixpanel/Storage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,24 @@ namespace mixpanel
{
public static class MixpanelStorage
{
#region Preferences
private static IPreferences PreferencesSource = new PlayerPreferences();

public static void SetPreferencesSource(IPreferences preferences)
{
PreferencesSource = preferences;
}

#endregion

#region HasMigratedFrom1To2

private const string HasMigratedFrom1To2Name = "Mixpanel.HasMigratedFrom1To2";

internal static bool HasMigratedFrom1To2
{
get => Convert.ToBoolean(PlayerPrefs.GetInt(HasMigratedFrom1To2Name, 0));
set => PlayerPrefs.SetInt(HasMigratedFrom1To2Name, Convert.ToInt32(value));
get => Convert.ToBoolean(PreferencesSource.GetInt(HasMigratedFrom1To2Name, 0));
set => PreferencesSource.SetInt(HasMigratedFrom1To2Name, Convert.ToInt32(value));
}

#endregion
Expand All @@ -34,8 +44,8 @@ internal static bool HasMigratedFrom1To2

internal static bool HasIntegratedLibrary
{
get => Convert.ToBoolean(PlayerPrefs.GetInt(HasIntegratedLibraryName, 0));
set => PlayerPrefs.SetInt(HasIntegratedLibraryName, Convert.ToInt32(value));
get => Convert.ToBoolean(PreferencesSource.GetInt(HasIntegratedLibraryName, 0));
set => PreferencesSource.SetInt(HasIntegratedLibraryName, Convert.ToInt32(value));
}

#endregion
Expand All @@ -51,9 +61,9 @@ public static string DistinctId
get
{
if (!string.IsNullOrEmpty(_distinctId)) return _distinctId;
if (PlayerPrefs.HasKey(DistinctIdName))
if (PreferencesSource.HasKey(DistinctIdName))
{
_distinctId = PlayerPrefs.GetString(DistinctIdName);
_distinctId = PreferencesSource.GetString(DistinctIdName);
}
// Generate a Unique ID for this client if still null or empty
// https://devblogs.microsoft.com/oldnewthing/?p=21823
Expand All @@ -63,7 +73,7 @@ public static string DistinctId
set
{
_distinctId = value;
PlayerPrefs.SetString(DistinctIdName, _distinctId);
PreferencesSource.SetString(DistinctIdName, _distinctId);
}
}

Expand All @@ -84,26 +94,26 @@ internal static void EnqueueTrackingData(Value data, FlushType flushType)
int peopleId = PeopleAutoIncrementingID();
String trackingKey = (flushType == FlushType.EVENTS)? "Event" + eventId.ToString() : "People" + peopleId.ToString();
data["id"] = trackingKey;
PlayerPrefs.SetString(trackingKey, JsonUtility.ToJson(data));
PreferencesSource.SetString(trackingKey, JsonUtility.ToJson(data));
IncreaseTrackingDataID(flushType);
}

internal static int EventAutoIncrementingID()
{
return PlayerPrefs.HasKey("EventAutoIncrementingID") ? PlayerPrefs.GetInt("EventAutoIncrementingID") : 0;
return PreferencesSource.HasKey("EventAutoIncrementingID") ? PreferencesSource.GetInt("EventAutoIncrementingID") : 0;
}

internal static int PeopleAutoIncrementingID()
{
return PlayerPrefs.HasKey("PeopleAutoIncrementingID") ? PlayerPrefs.GetInt("PeopleAutoIncrementingID") : 0;
return PreferencesSource.HasKey("PeopleAutoIncrementingID") ? PreferencesSource.GetInt("PeopleAutoIncrementingID") : 0;
}

private static void IncreaseTrackingDataID(FlushType flushType)
{
int id = (flushType == FlushType.EVENTS)? EventAutoIncrementingID() : PeopleAutoIncrementingID();
id += 1;
String trackingIdKey = (flushType == FlushType.EVENTS)? "EventAutoIncrementingID" : "PeopleAutoIncrementingID";
PlayerPrefs.SetInt(trackingIdKey, id);
PreferencesSource.SetInt(trackingIdKey, id);
}

internal static Value DequeueBatchTrackingData(FlushType flushType, int batchSize)
Expand All @@ -113,13 +123,13 @@ internal static Value DequeueBatchTrackingData(FlushType flushType, int batchSiz
int maxIndex = (flushType == FlushType.EVENTS) ? EventAutoIncrementingID() - 1 : PeopleAutoIncrementingID() - 1;
while (batch.Count < batchSize && dataIndex <= maxIndex) {
String trackingKey = (flushType == FlushType.EVENTS) ? "Event" + dataIndex.ToString() : "People" + dataIndex.ToString();
if (PlayerPrefs.HasKey(trackingKey)) {
if (PreferencesSource.HasKey(trackingKey)) {
try {
batch.Add(JsonUtility.FromJson<Value>(PlayerPrefs.GetString(trackingKey)));
batch.Add(JsonUtility.FromJson<Value>(PreferencesSource.GetString(trackingKey)));
}
catch (Exception e) {
Mixpanel.LogError($"There was an error processing '{trackingKey}' from the internal object pool: " + e);
PlayerPrefs.DeleteKey(trackingKey);
PreferencesSource.DeleteKey(trackingKey);
}
}
dataIndex++;
Expand All @@ -135,8 +145,8 @@ internal static void DeleteBatchTrackingData(FlushType flushType, int batchSize)
int maxIndex = (flushType == FlushType.EVENTS) ? EventAutoIncrementingID() - 1 : PeopleAutoIncrementingID() - 1;
while (deletedCount < batchSize && dataIndex <= maxIndex) {
String trackingKey = (flushType == FlushType.EVENTS) ? "Event" + dataIndex.ToString() : "People" + dataIndex.ToString();
if (PlayerPrefs.HasKey(trackingKey)) {
PlayerPrefs.DeleteKey(trackingKey);
if (PreferencesSource.HasKey(trackingKey)) {
PreferencesSource.DeleteKey(trackingKey);
deletedCount++;
}
dataIndex++;
Expand All @@ -146,8 +156,8 @@ internal static void DeleteBatchTrackingData(FlushType flushType, int batchSize)
internal static void DeleteBatchTrackingData(Value batch) {
foreach(Value data in batch) {
String id = data["id"];
if (id != null && PlayerPrefs.HasKey(id)) {
PlayerPrefs.DeleteKey(id);
if (id != null && PreferencesSource.HasKey(id)) {
PreferencesSource.DeleteKey(id);
}
}
}
Expand All @@ -169,14 +179,14 @@ public static bool IsTracking
{
get
{
if (!PlayerPrefs.HasKey(IsTrackingName)) IsTracking = true;
else _isTracking = PlayerPrefs.GetInt(IsTrackingName) == 1;
if (!PreferencesSource.HasKey(IsTrackingName)) IsTracking = true;
else _isTracking = PreferencesSource.GetInt(IsTrackingName) == 1;
return _isTracking;
}
set
{
_isTracking = value;
PlayerPrefs.SetInt(IsTrackingName, _isTracking ? 1 : 0);
PreferencesSource.SetInt(IsTrackingName, _isTracking ? 1 : 0);
}
}

Expand All @@ -193,14 +203,14 @@ internal static string PushDeviceTokenString
get
{
if (!string.IsNullOrEmpty(_pushDeviceTokenString)) return _pushDeviceTokenString;
if (!PlayerPrefs.HasKey(PushDeviceTokenName)) PushDeviceTokenString = "";
else _pushDeviceTokenString = PlayerPrefs.GetString(PushDeviceTokenName);
if (!PreferencesSource.HasKey(PushDeviceTokenName)) PushDeviceTokenString = "";
else _pushDeviceTokenString = PreferencesSource.GetString(PushDeviceTokenName);
return _pushDeviceTokenString;
}
set
{
_pushDeviceTokenString = value;
PlayerPrefs.SetString(PushDeviceTokenName, _pushDeviceTokenString);
PreferencesSource.SetString(PushDeviceTokenName, _pushDeviceTokenString);
}
}

Expand All @@ -223,18 +233,18 @@ internal static Value OnceProperties
get
{
if (_onceProperties != null) return _onceProperties;
if (!PlayerPrefs.HasKey(OncePropertiesName)) OnceProperties = new Value();
if (!PreferencesSource.HasKey(OncePropertiesName)) OnceProperties = new Value();
else
{
_onceProperties = new Value();
JsonUtility.FromJsonOverwrite(PlayerPrefs.GetString(OncePropertiesName), _onceProperties);
JsonUtility.FromJsonOverwrite(PreferencesSource.GetString(OncePropertiesName), _onceProperties);
}
return _onceProperties;
}
set
{
_onceProperties = value;
PlayerPrefs.SetString(OncePropertiesName, JsonUtility.ToJson(_onceProperties));
PreferencesSource.SetString(OncePropertiesName, JsonUtility.ToJson(_onceProperties));
}
}

Expand All @@ -258,18 +268,18 @@ internal static Value SuperProperties
get
{
if (_superProperties != null) return _superProperties;
if (!PlayerPrefs.HasKey(SuperPropertiesName)) SuperProperties = new Value();
if (!PreferencesSource.HasKey(SuperPropertiesName)) SuperProperties = new Value();
else
{
_superProperties = new Value();
JsonUtility.FromJsonOverwrite(PlayerPrefs.GetString(SuperPropertiesName), _superProperties);
JsonUtility.FromJsonOverwrite(PreferencesSource.GetString(SuperPropertiesName), _superProperties);
}
return _superProperties;
}
set
{
_superProperties = value;
PlayerPrefs.SetString(SuperPropertiesName, JsonUtility.ToJson(_superProperties));
PreferencesSource.SetString(SuperPropertiesName, JsonUtility.ToJson(_superProperties));
}
}

Expand All @@ -293,18 +303,18 @@ internal static Value TimedEvents
get
{
if (_timedEvents != null) return _timedEvents;
if (!PlayerPrefs.HasKey(TimedEventsName)) TimedEvents = new Value();
if (!PreferencesSource.HasKey(TimedEventsName)) TimedEvents = new Value();
else
{
_timedEvents = new Value();
JsonUtility.FromJsonOverwrite(PlayerPrefs.GetString(TimedEventsName), _timedEvents);
JsonUtility.FromJsonOverwrite(PreferencesSource.GetString(TimedEventsName), _timedEvents);
}
return _timedEvents;
}
set
{
_timedEvents = value;
PlayerPrefs.SetString(TimedEventsName, JsonUtility.ToJson(_timedEvents));
PreferencesSource.SetString(TimedEventsName, JsonUtility.ToJson(_timedEvents));
}
}

Expand Down

0 comments on commit 9b3e663

Please sign in to comment.