com.amanotes.gdk 0.1.20 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/Editor/AmaGDKEditor.cs +91 -46
- package/Editor/AmaGDKManager.cs +26 -27
- package/Editor/Utils/AmaGDKEditor.ExtractVersion.cs +133 -103
- package/Editor/Utils/AmaGDKEditor.GUI.cs +54 -51
- package/Editor/Utils/AmaGDKEditor.Utils.cs +2 -3
- package/Packages/AmaGDKConfig.unitypackage +0 -0
- package/Packages/AmaGDKExample.unitypackage +0 -0
- package/Packages/AmaGDKTest.unitypackage +0 -0
- package/Packages/AmaPassport.ATTSupport.unitypackage +0 -0
- package/{Samples~/Example/AmaGDKExample.unity.meta → Packages/AmaPassport.ATTSupport.unitypackage.meta} +1 -1
- package/Packages/AmaPassport.AdvertisingID.unitypackage +0 -0
- package/{Sample~/Example/AmaGDKExample.unity.meta → Packages/AmaPassport.AdvertisingID.unitypackage.meta} +1 -1
- package/Packages/AppsFlyerAdapter_v6.5.4.unitypackage +0 -0
- package/Packages/FirebaseAnalyticsAdapter_v9.1.0.unitypackage +0 -0
- package/Packages/FirebaseRemoteConfigAdapter_v9.1.0.unitypackage +0 -0
- package/{Runtime/AmaPassport/Plugins.meta → Packages/FirebaseRemoteConfigAdapter_v9.1.0.unitypackage.meta} +1 -2
- package/Packages/IronsourceAdapter_v7.2.6.unitypackage +0 -0
- package/Runtime/AmaGDK.Adapters.cs +30 -12
- package/Runtime/AmaGDK.Ads.cs +520 -162
- package/Runtime/{AmaPassport/AmaGDK.AmaPassport.cs → AmaGDK.AmaPassport.cs} +36 -47
- package/Runtime/{AmaPassport/AmaGDK.AmaPassport.cs.meta → AmaGDK.AmaPassport.cs.meta} +1 -1
- package/Runtime/AmaGDK.Analytics.cs +78 -89
- package/Runtime/AmaGDK.Config.cs +23 -19
- package/Runtime/AmaGDK.Internal.SemVer.cs +11 -29
- package/Runtime/AmaGDK.Internal.cs +17 -11
- package/Runtime/AmaGDK.RemoteConfig.cs +352 -0
- package/Runtime/{AmaPassport/Plugins/Android/AdvertisingIdFetcher.cs.meta → AmaGDK.RemoteConfig.cs.meta} +1 -1
- package/Runtime/AmaGDK.UserProfile.cs +5 -8
- package/Runtime/AmaGDK.Utils.cs +79 -60
- package/Runtime/AmaGDK.WebUtils.cs +45 -48
- package/Runtime/AmaGDK.cs +74 -22
- package/Runtime/AssemblyInfo.cs +0 -1
- package/package.json +1 -1
- package/Packages/AppsflyerAdapter_v6.5.4.unitypackage +0 -0
- package/Runtime/AmaPassport/Plugins/Android/AdvertisingIdCallback.java +0 -7
- package/Runtime/AmaPassport/Plugins/Android/AdvertisingIdCallback.java.meta +0 -32
- package/Runtime/AmaPassport/Plugins/Android/AdvertisingIdFetcher.cs +0 -96
- package/Runtime/AmaPassport/Plugins/Android/AdvertisingIdFetcher.java +0 -79
- package/Runtime/AmaPassport/Plugins/Android/AdvertisingIdFetcher.java.meta +0 -32
- package/Runtime/AmaPassport/Plugins/Android.meta +0 -8
- package/Runtime/AmaPassport/Plugins/iOS/KeyChain.cs +0 -59
- package/Runtime/AmaPassport/Plugins/iOS/KeyChain.cs.meta +0 -11
- package/Runtime/AmaPassport/Plugins/iOS/KeyChainPlugin.mm +0 -52
- package/Runtime/AmaPassport/Plugins/iOS/KeyChainPlugin.mm.meta +0 -33
- package/Runtime/AmaPassport/Plugins/iOS/UICKeyChainStore.h +0 -281
- package/Runtime/AmaPassport/Plugins/iOS/UICKeyChainStore.h.meta +0 -33
- package/Runtime/AmaPassport/Plugins/iOS/UICKeyChainStore.m +0 -1393
- package/Runtime/AmaPassport/Plugins/iOS/UICKeyChainStore.m.meta +0 -33
- package/Runtime/AmaPassport/Plugins/iOS.meta +0 -8
- package/Runtime/AmaPassport.meta +0 -8
- package/Samples~/Example/AmaGDKExample.cs +0 -87
- package/Samples~/Example/AmaGDKExample.cs.meta +0 -11
- package/Samples~/Example/AmaGDKExample.unity +0 -3114
- package/Sample~/Example/AmaGDKExample.cs +0 -87
- package/Sample~/Example/AmaGDKExample.cs.meta +0 -11
- package/Sample~/Example/AmaGDKExample.unity +0 -3114
- /package/Packages/{AppsflyerAdapter_v6.5.4.unitypackage.meta → AppsFlyerAdapter_v6.5.4.unitypackage.meta} +0 -0
package/Runtime/AmaGDK.Config.cs
CHANGED
|
@@ -2,12 +2,12 @@ using System;
|
|
|
2
2
|
using System.Collections.Generic;
|
|
3
3
|
using System.Reflection;
|
|
4
4
|
using UnityEngine;
|
|
5
|
-
|
|
6
5
|
#if UNITY_EDITOR
|
|
7
6
|
using UnityEditor;
|
|
8
7
|
#endif
|
|
9
8
|
|
|
10
|
-
namespace Amanotes.Core.Internal
|
|
9
|
+
namespace Amanotes.Core.Internal
|
|
10
|
+
{
|
|
11
11
|
public partial class ConfigAsset : ScriptableObject
|
|
12
12
|
{
|
|
13
13
|
[SerializeField] internal bool simpleOrder = true;
|
|
@@ -15,63 +15,67 @@ namespace Amanotes.Core.Internal {
|
|
|
15
15
|
[SerializeField] public SDKConfig common;
|
|
16
16
|
|
|
17
17
|
#if UNITY_EDITOR
|
|
18
|
-
void OnValidate()
|
|
18
|
+
private void OnValidate()
|
|
19
19
|
{
|
|
20
20
|
if (Application.isPlaying) return;
|
|
21
|
-
if (simpleOrder)
|
|
21
|
+
if (simpleOrder)
|
|
22
|
+
{
|
|
22
23
|
EditorApplication.update -= DelayCheckOrder;
|
|
23
24
|
EditorApplication.update += DelayCheckOrder;
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
void DelayCheckOrder()
|
|
28
|
+
private void DelayCheckOrder()
|
|
28
29
|
{
|
|
29
30
|
EditorApplication.update -= DelayCheckOrder;
|
|
30
31
|
var dirty = false;
|
|
31
|
-
for (var i =0
|
|
32
|
+
for (var i = 0; i < initOrder.Count; i++)
|
|
33
|
+
{
|
|
32
34
|
if (initOrder[i].order == i) continue;
|
|
33
35
|
dirty = true;
|
|
34
36
|
break;
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
if (!dirty) return;
|
|
38
|
-
initOrder.Sort((a1, a2)=> a1.order.CompareTo(a2.order));
|
|
39
|
-
for (var i =0
|
|
40
|
+
initOrder.Sort((a1, a2) => a1.order.CompareTo(a2.order));
|
|
41
|
+
for (var i = 0; i < initOrder.Count; i++)
|
|
42
|
+
{
|
|
40
43
|
initOrder[i].order = i;
|
|
41
44
|
}
|
|
42
45
|
EditorUtility.SetDirty(this);
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
[ContextMenu("Scan Adapters")]
|
|
46
|
-
void ScanAdapters()
|
|
49
|
+
private void ScanAdapters()
|
|
47
50
|
{
|
|
48
51
|
initOrder.Clear();
|
|
49
52
|
|
|
50
53
|
var counter = 0;
|
|
51
|
-
foreach (
|
|
54
|
+
foreach (Type adapter in GetAllAdapters<AdapterContext>())
|
|
52
55
|
{
|
|
53
|
-
|
|
56
|
+
string id = adapter.Name.Replace("Adapter", string.Empty);
|
|
54
57
|
initOrder.Add(new InitOrder(){ id = id, order = counter++ });
|
|
55
58
|
}
|
|
56
59
|
}
|
|
57
60
|
|
|
58
61
|
[ContextMenu("Refresh Order")]
|
|
59
|
-
void UpdateOrderToPosition()
|
|
62
|
+
private void UpdateOrderToPosition()
|
|
60
63
|
{
|
|
61
|
-
for (var i =0
|
|
64
|
+
for (var i = 0; i < initOrder.Count; i++)
|
|
62
65
|
{
|
|
63
66
|
initOrder[i].order = i;
|
|
64
67
|
}
|
|
65
68
|
}
|
|
66
|
-
|
|
69
|
+
|
|
67
70
|
public static IEnumerable<Type> GetAllAdapters<T>()
|
|
68
71
|
{
|
|
69
|
-
|
|
72
|
+
Type typeT = typeof(T);
|
|
70
73
|
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
|
|
71
74
|
{
|
|
72
75
|
if (!a.FullName.Contains("Assembly-CSharp")) continue;
|
|
73
|
-
|
|
74
|
-
foreach (
|
|
76
|
+
|
|
77
|
+
foreach (Type type in a.GetTypes())
|
|
78
|
+
{
|
|
75
79
|
if (typeT.IsAssignableFrom(type)) yield return type;
|
|
76
80
|
}
|
|
77
81
|
}
|
|
@@ -82,7 +86,7 @@ namespace Amanotes.Core.Internal {
|
|
|
82
86
|
[Serializable]
|
|
83
87
|
public partial class SDKConfig
|
|
84
88
|
{
|
|
85
|
-
public bool verboseLog
|
|
89
|
+
public bool verboseLog;
|
|
86
90
|
}
|
|
87
91
|
|
|
88
92
|
[Serializable]
|
|
@@ -91,4 +95,4 @@ namespace Amanotes.Core.Internal {
|
|
|
91
95
|
public string id;
|
|
92
96
|
public int order;
|
|
93
97
|
}
|
|
94
|
-
}
|
|
98
|
+
}
|
|
@@ -29,14 +29,11 @@ namespace Amanotes.Core.Internal
|
|
|
29
29
|
patch = 0;
|
|
30
30
|
extra = -1;
|
|
31
31
|
|
|
32
|
-
if (string.IsNullOrEmpty(version))
|
|
33
|
-
{
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
32
|
+
if (string.IsNullOrEmpty(version)) return;
|
|
36
33
|
|
|
37
34
|
version = version.Trim();
|
|
38
35
|
|
|
39
|
-
|
|
36
|
+
var regex = new Regex(@"^(\d+)\.(\d+)\.(\d+)(?:\.(\d+))?$");
|
|
40
37
|
Match match = regex.Match(version);
|
|
41
38
|
if (!match.Success)
|
|
42
39
|
{
|
|
@@ -51,10 +48,10 @@ namespace Amanotes.Core.Internal
|
|
|
51
48
|
if (!int.TryParse(match.Groups[4].Value, out extra))
|
|
52
49
|
extra = -1;
|
|
53
50
|
}
|
|
54
|
-
|
|
51
|
+
|
|
55
52
|
}
|
|
56
53
|
|
|
57
|
-
public bool isValid
|
|
54
|
+
public bool isValid => this != ZERO;
|
|
58
55
|
|
|
59
56
|
public override string ToString()
|
|
60
57
|
{
|
|
@@ -65,22 +62,10 @@ namespace Amanotes.Core.Internal
|
|
|
65
62
|
|
|
66
63
|
public int CompareTo(SemVer other)
|
|
67
64
|
{
|
|
68
|
-
if (major != other.major)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (minor != other.minor)
|
|
73
|
-
{
|
|
74
|
-
return minor.CompareTo(other.minor);
|
|
75
|
-
}
|
|
76
|
-
if (patch != other.patch)
|
|
77
|
-
{
|
|
78
|
-
return patch.CompareTo(other.patch);
|
|
79
|
-
}
|
|
80
|
-
if (extra != other.extra)
|
|
81
|
-
{
|
|
82
|
-
return extra.CompareTo(other.extra);
|
|
83
|
-
}
|
|
65
|
+
if (major != other.major) return major.CompareTo(other.major);
|
|
66
|
+
if (minor != other.minor) return minor.CompareTo(other.minor);
|
|
67
|
+
if (patch != other.patch) return patch.CompareTo(other.patch);
|
|
68
|
+
if (extra != other.extra) return extra.CompareTo(other.extra);
|
|
84
69
|
return 0;
|
|
85
70
|
}
|
|
86
71
|
|
|
@@ -91,11 +76,8 @@ namespace Amanotes.Core.Internal
|
|
|
91
76
|
|
|
92
77
|
public override bool Equals(object obj)
|
|
93
78
|
{
|
|
94
|
-
if (!(obj is SemVer))
|
|
95
|
-
|
|
96
|
-
return false;
|
|
97
|
-
}
|
|
98
|
-
SemVer other = (SemVer)obj;
|
|
79
|
+
if (!(obj is SemVer)) return false;
|
|
80
|
+
var other = (SemVer)obj;
|
|
99
81
|
return major == other.major && minor == other.minor && patch == other.patch && extra == other.extra;
|
|
100
82
|
}
|
|
101
83
|
|
|
@@ -134,4 +116,4 @@ namespace Amanotes.Core.Internal
|
|
|
134
116
|
return (major << 24) | (minor << 16) | (patch << 8) | extra;
|
|
135
117
|
}
|
|
136
118
|
}
|
|
137
|
-
}
|
|
119
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
using System
|
|
1
|
+
using System;
|
|
2
2
|
using System.Collections.Generic;
|
|
3
|
-
|
|
3
|
+
using System.Text;
|
|
4
4
|
using UnityEngine;
|
|
5
5
|
using UnityObject = UnityEngine.Object;
|
|
6
6
|
using static Amanotes.Core.AmaGDK.Analytics;
|
|
@@ -39,11 +39,13 @@ namespace Amanotes.Core.Internal
|
|
|
39
39
|
public const string AMAGDK_PREFAB = BASE_PATH + "Runtime/AmaGDK.prefab";
|
|
40
40
|
public const string AMAGDK_CONFIG_PACKAGE = PACKAGE_PATH + "AmaGDKConfig.unitypackage";
|
|
41
41
|
|
|
42
|
-
public static readonly string[] AMAGDK_ADAPTERS =
|
|
42
|
+
public static readonly string[] AMAGDK_ADAPTERS =
|
|
43
43
|
{
|
|
44
44
|
"FirebaseAnalyticsAdapter_v9.1.0",
|
|
45
45
|
"AppsFlyerAdapter_v6.5.4",
|
|
46
|
+
|
|
46
47
|
// "IronsourceAdapter_v7.2.6",
|
|
48
|
+
"FirebaseRemoteConfigAdapter_v9.1.0"
|
|
47
49
|
};
|
|
48
50
|
|
|
49
51
|
#if UNITY_EDITOR
|
|
@@ -51,14 +53,14 @@ namespace Amanotes.Core.Internal
|
|
|
51
53
|
[MenuItem("GameObject/AmaGDK/Add AmaGDK Prefab", false, 10)]
|
|
52
54
|
private static void AddAmaGDKPrefab()
|
|
53
55
|
{
|
|
54
|
-
|
|
56
|
+
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(AMAGDK_PREFAB);
|
|
55
57
|
if (prefab == null)
|
|
56
58
|
{
|
|
57
59
|
Debug.LogWarning($"Prefab [AmaGDK] not found at: {AMAGDK_PREFAB}");
|
|
58
60
|
return;
|
|
59
61
|
}
|
|
60
62
|
|
|
61
|
-
|
|
63
|
+
var newPrefab = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
|
|
62
64
|
newPrefab.name = "AmaGDK";
|
|
63
65
|
newPrefab.transform.SetAsLastSibling();
|
|
64
66
|
Selection.activeObject = null;
|
|
@@ -67,7 +69,6 @@ namespace Amanotes.Core.Internal
|
|
|
67
69
|
#endif
|
|
68
70
|
}
|
|
69
71
|
|
|
70
|
-
|
|
71
72
|
public static class Logging
|
|
72
73
|
{
|
|
73
74
|
public static readonly StringBuilder tmpWarningSB = new StringBuilder();
|
|
@@ -104,14 +105,14 @@ namespace Amanotes.Core.Internal
|
|
|
104
105
|
AmaGDK._instance = null;
|
|
105
106
|
}
|
|
106
107
|
|
|
107
|
-
|
|
108
|
+
AmaGDK[] result = Resources.FindObjectsOfTypeAll<AmaGDK>();
|
|
108
109
|
for (var i = 0; i < result.Length; i++)
|
|
109
110
|
{
|
|
110
111
|
if (result[i] == null) continue;
|
|
111
112
|
|
|
112
113
|
#if UNITY_EDITOR // Ignore loaded prefabs assets
|
|
113
114
|
{
|
|
114
|
-
|
|
115
|
+
string path = AssetDatabase.GetAssetPath(result[i]);
|
|
115
116
|
if (!string.IsNullOrEmpty(path)) continue;
|
|
116
117
|
}
|
|
117
118
|
#endif
|
|
@@ -129,10 +130,15 @@ namespace Amanotes.Core.Internal
|
|
|
129
130
|
|
|
130
131
|
public static void ClearAnalyticsData()
|
|
131
132
|
{
|
|
132
|
-
AnalyticsData analyticsData =
|
|
133
|
+
AnalyticsData analyticsData = localData;
|
|
133
134
|
analyticsData.funnelSignatures.Clear();
|
|
134
135
|
analyticsData.eventDetails.Clear();
|
|
135
|
-
analyticsData.migrationLog = new
|
|
136
|
+
analyticsData.migrationLog = new MigrationLog();
|
|
136
137
|
}
|
|
137
138
|
}
|
|
138
|
-
|
|
139
|
+
|
|
140
|
+
public interface IOnApplicationPause { void OnApplicationPause(bool pauseStatus); }
|
|
141
|
+
public interface IOnApplicationQuit { void OnApplicationQuit(); }
|
|
142
|
+
public interface IOnApplicationFocus { void OnApplicationFocus(bool hasFocus); }
|
|
143
|
+
public interface IOnFrameUpdate { void OnFrameUpdate(); }
|
|
144
|
+
}
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.IO;
|
|
4
|
+
using System.Text;
|
|
5
|
+
using UnityEngine;
|
|
6
|
+
|
|
7
|
+
using Amanotes.Core.Internal;
|
|
8
|
+
using static Amanotes.Core.Internal.Logging;
|
|
9
|
+
|
|
10
|
+
namespace Amanotes.Core
|
|
11
|
+
{
|
|
12
|
+
public partial class AmaGDK //Remote Config
|
|
13
|
+
{
|
|
14
|
+
public enum RemoteConfigSource
|
|
15
|
+
{
|
|
16
|
+
DefaultAsset,
|
|
17
|
+
DefaultFile,
|
|
18
|
+
Cache,
|
|
19
|
+
Internet
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
[Serializable]
|
|
23
|
+
public partial class RemoteConfig //Public
|
|
24
|
+
{
|
|
25
|
+
public static Action<bool> onFetchCompleted;
|
|
26
|
+
public static Dictionary<string, string> DictConfig { get { return dictConfig; } }
|
|
27
|
+
public static RemoteConfigSource Source { private set; get; }
|
|
28
|
+
static bool? _cacheExisted = null;
|
|
29
|
+
public static bool HasCache
|
|
30
|
+
{
|
|
31
|
+
get
|
|
32
|
+
{
|
|
33
|
+
if (_cacheExisted == null)
|
|
34
|
+
_cacheExisted = FileUtils.Exist(fileName);
|
|
35
|
+
return _cacheExisted.GetValueOrDefault();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
internal static T ParseConfig<T>(T config = null) where T : class, new()
|
|
40
|
+
{
|
|
41
|
+
if (config == null)
|
|
42
|
+
config = new T();
|
|
43
|
+
|
|
44
|
+
var configInJson = GetConfigAsJsonString();
|
|
45
|
+
if (string.IsNullOrEmpty(configInJson))
|
|
46
|
+
{
|
|
47
|
+
LogWarning("[RemoteConfig] The config is empty");
|
|
48
|
+
return config;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try
|
|
52
|
+
{
|
|
53
|
+
return config = JsonUtility.FromJson<T>(configInJson);
|
|
54
|
+
}
|
|
55
|
+
catch (Exception e)
|
|
56
|
+
{
|
|
57
|
+
LogError("[RemoteConfig] Cannot parse remote config file. Error: " + e.Message);
|
|
58
|
+
return config;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public static T Get<T>(string key, T defaultValue = default(T))
|
|
63
|
+
{
|
|
64
|
+
if (dictConfig.ContainsKey(key))
|
|
65
|
+
return (T)Convert.ChangeType(dictConfig[key], typeof(T));
|
|
66
|
+
return defaultValue;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public static T WriteConfigTo<T>(T config = null) where T : class, new ()
|
|
70
|
+
{
|
|
71
|
+
return ParseConfig<T>(config);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public static string GetConfigAsJsonString()
|
|
75
|
+
{
|
|
76
|
+
return JsonUtils.DictionaryToJson(dictConfig);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public partial class RemoteConfig //Internal
|
|
81
|
+
{
|
|
82
|
+
internal enum FetchState
|
|
83
|
+
{
|
|
84
|
+
None,
|
|
85
|
+
ResolveDependencies,
|
|
86
|
+
CheckInternet,
|
|
87
|
+
Fetch,
|
|
88
|
+
SaveCache,
|
|
89
|
+
|
|
90
|
+
LoadCache,
|
|
91
|
+
LoadDefaultFile,
|
|
92
|
+
LoadDefaultAsset,
|
|
93
|
+
|
|
94
|
+
Success,
|
|
95
|
+
Fail
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
static Dictionary<string, string> dictConfig = new Dictionary<string, string>();
|
|
99
|
+
static string fileName = $"{nameof(RemoteConfig)}.kv";
|
|
100
|
+
static string defaultConfigFileName = "remote_config_defaults";
|
|
101
|
+
|
|
102
|
+
static FetchState _state = FetchState.None;
|
|
103
|
+
internal static FetchState State { get { return _state; } }
|
|
104
|
+
static readonly Dictionary<FetchState, Action[]> fetchSM = new Dictionary<FetchState, Action[]>
|
|
105
|
+
{
|
|
106
|
+
{ FetchState.None, new Action[]{ ResolveDependency }},
|
|
107
|
+
{ FetchState.ResolveDependencies, new Action[]{ LoadCache, CheckInternet}},
|
|
108
|
+
{ FetchState.CheckInternet, new Action[]{ LoadCache, Fetch}},
|
|
109
|
+
{ FetchState.Fetch, new Action[]{ LoadCache, SaveCache}},
|
|
110
|
+
{ FetchState.SaveCache, new Action[]{ SetDone }},
|
|
111
|
+
{ FetchState.LoadCache, new Action[]{ LoadDefaultFile, SetDone}},
|
|
112
|
+
{ FetchState.LoadDefaultFile, new Action[]{ LoadDefaultAsset, SetDone}},
|
|
113
|
+
{ FetchState.LoadDefaultAsset, new Action[]{ SetFail, SetDone}}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
internal static IRemoteConfig adapter;
|
|
117
|
+
internal static Action<bool> onAdapterInitCompleteCallback;
|
|
118
|
+
|
|
119
|
+
internal static void NextState(bool result = true)
|
|
120
|
+
{
|
|
121
|
+
if (!fetchSM.TryGetValue(_state, out var actions))
|
|
122
|
+
{
|
|
123
|
+
LogWarning("[RemoteConfig] Invalid / Unsupported state: " + _state);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (actions.Length == 1)
|
|
128
|
+
{
|
|
129
|
+
actions[0]();
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
actions[result ? 1 : 0]();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
static void ResolveDependency()
|
|
137
|
+
{
|
|
138
|
+
_state = FetchState.ResolveDependencies;
|
|
139
|
+
adapter = Adapter.GetSingleAdapter<IRemoteConfig>();
|
|
140
|
+
if (adapter == null)
|
|
141
|
+
{
|
|
142
|
+
NextState(false);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
adapter.ResolveDependencies(NextState);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
static void CheckInternet()
|
|
149
|
+
{
|
|
150
|
+
_state = FetchState.CheckInternet;
|
|
151
|
+
NextState(Application.internetReachability != NetworkReachability.NotReachable);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
static void Fetch()
|
|
155
|
+
{
|
|
156
|
+
_state = FetchState.Fetch;
|
|
157
|
+
adapter.FetchConfig(HasCache, (isSuccess, result) =>
|
|
158
|
+
{
|
|
159
|
+
if (!isSuccess)
|
|
160
|
+
{
|
|
161
|
+
NextState(false);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
dictConfig = result;
|
|
166
|
+
Source = RemoteConfigSource.Internet;
|
|
167
|
+
Log("[RemoteConfig] Load from the internet");
|
|
168
|
+
NextState(true);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
static void SaveCache()
|
|
173
|
+
{
|
|
174
|
+
_state = FetchState.SaveCache;
|
|
175
|
+
StringBuilder sb = new StringBuilder();
|
|
176
|
+
foreach (var c in dictConfig)
|
|
177
|
+
{
|
|
178
|
+
sb.AppendLine($"{c.Key}\t{c.Value}");
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
var filePath = FileUtils.GetPath(fileName);
|
|
182
|
+
FileUtils.Save(filePath, sb.ToString());
|
|
183
|
+
Log($"[RemoteConfig] Saved remote config to {filePath}");
|
|
184
|
+
NextState();
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
static void LoadCache()
|
|
188
|
+
{
|
|
189
|
+
_state = FetchState.LoadCache;
|
|
190
|
+
|
|
191
|
+
if (!HasCache)
|
|
192
|
+
{
|
|
193
|
+
NextState(false);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
try
|
|
198
|
+
{
|
|
199
|
+
dictConfig.Clear();
|
|
200
|
+
using (StreamReader sr = new StreamReader(FileUtils.GetPath(fileName)))
|
|
201
|
+
{
|
|
202
|
+
string line;
|
|
203
|
+
int lineIdx = 0;
|
|
204
|
+
while ((line = sr.ReadLine()) != null)
|
|
205
|
+
{
|
|
206
|
+
lineIdx++;
|
|
207
|
+
var idx = line.IndexOf('\t');
|
|
208
|
+
if (idx == -1)
|
|
209
|
+
{
|
|
210
|
+
LogWarning($"[RemoteConfig] Cannot get (key, value) at line {lineIdx} of cache");
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
string key = line.Substring(0, idx);
|
|
214
|
+
string value = line.Substring(idx + 1);
|
|
215
|
+
dictConfig.Add(key, value);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
Source = RemoteConfigSource.Cache;
|
|
219
|
+
Log("[RemoteConfig] Load from cache");
|
|
220
|
+
}
|
|
221
|
+
catch (Exception ex)
|
|
222
|
+
{
|
|
223
|
+
LogWarning($"[RemoteConfig] Error on LoadCache: {ex.Message}");
|
|
224
|
+
_cacheExisted = false;
|
|
225
|
+
NextState(false);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
NextState(true);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
static void LoadDefaultFile()
|
|
233
|
+
{
|
|
234
|
+
_state = FetchState.LoadDefaultFile;
|
|
235
|
+
|
|
236
|
+
var defaultConfigFile = Resources.Load<TextAsset>(defaultConfigFileName);
|
|
237
|
+
if (defaultConfigFile == null)
|
|
238
|
+
{
|
|
239
|
+
NextState(false);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
dictConfig = JsonToDictionary(defaultConfigFile.text);
|
|
244
|
+
|
|
245
|
+
Source = RemoteConfigSource.DefaultFile;
|
|
246
|
+
Log("[RemoteConfig] Load from default file");
|
|
247
|
+
NextState(true);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
static void LoadDefaultAsset()
|
|
251
|
+
{
|
|
252
|
+
_state = FetchState.LoadDefaultAsset;
|
|
253
|
+
|
|
254
|
+
var defaultValue = ((AdapterContext)adapter).GetAdapterConfig<RemoteConfigConfig>().defaultValue;
|
|
255
|
+
|
|
256
|
+
if (defaultValue.Length == 0)
|
|
257
|
+
{
|
|
258
|
+
NextState(false);
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
foreach (var item in defaultValue)
|
|
263
|
+
{
|
|
264
|
+
dictConfig.Add(item.key, item.value);
|
|
265
|
+
}
|
|
266
|
+
Source = RemoteConfigSource.DefaultAsset;
|
|
267
|
+
Log("[RemoteConfig] Load from default asset");
|
|
268
|
+
NextState(true);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
static void SetDone()
|
|
272
|
+
{
|
|
273
|
+
_state = FetchState.Success;
|
|
274
|
+
onAdapterInitCompleteCallback(true);
|
|
275
|
+
onFetchCompleted?.Invoke(true);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
static void SetFail()
|
|
279
|
+
{
|
|
280
|
+
_state = FetchState.Fail;
|
|
281
|
+
onAdapterInitCompleteCallback(false);
|
|
282
|
+
onFetchCompleted?.Invoke(false);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
static Dictionary<string, string> JsonToDictionary(string json)
|
|
286
|
+
{
|
|
287
|
+
var dictResult = new Dictionary<string, string>();
|
|
288
|
+
string[] lines = json.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
|
289
|
+
for (int i = 0; i < lines.Length; i++)
|
|
290
|
+
{
|
|
291
|
+
int idx = lines[i].IndexOf(':');
|
|
292
|
+
if (idx < 0)
|
|
293
|
+
{
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
string key = lines[i].Substring(0, idx - 1).Trim().Trim('"');
|
|
297
|
+
string value = "";
|
|
298
|
+
if (idx == lines.Length - 1)
|
|
299
|
+
{
|
|
300
|
+
value = lines[i].Substring(idx + 1).Trim().Trim('"');
|
|
301
|
+
}
|
|
302
|
+
else
|
|
303
|
+
{
|
|
304
|
+
value = lines[i].Substring(idx + 1).Trim();
|
|
305
|
+
value = value.Substring(1, value.Length - 3);
|
|
306
|
+
}
|
|
307
|
+
dictResult[key] = value;
|
|
308
|
+
}
|
|
309
|
+
return dictResult;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
public static class RemoteConfigExtension
|
|
315
|
+
{
|
|
316
|
+
public static void InitRemoteConfigModule(this IRemoteConfig ap, Action<bool> onCompleteCallback)
|
|
317
|
+
{
|
|
318
|
+
if (AmaGDK.RemoteConfig.State != AmaGDK.RemoteConfig.FetchState.None)
|
|
319
|
+
{
|
|
320
|
+
LogWarning($"[RemoteConfig] Current state {AmaGDK.RemoteConfig.State.ToString()}\n" +
|
|
321
|
+
$"Cannot start to initialize");
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
AmaGDK.RemoteConfig.onAdapterInitCompleteCallback = onCompleteCallback;
|
|
325
|
+
AmaGDK.RemoteConfig.NextState();
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
namespace Amanotes.Core.Internal
|
|
331
|
+
{
|
|
332
|
+
[Serializable]
|
|
333
|
+
public class RemoteConfigConfig
|
|
334
|
+
{
|
|
335
|
+
public KeyValue[] defaultValue;
|
|
336
|
+
public float firstFetchTimeOutInSeconds = 10;
|
|
337
|
+
public float defaultTimeOutInSeconds = 3;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
[Serializable]
|
|
341
|
+
public class KeyValue
|
|
342
|
+
{
|
|
343
|
+
public string key;
|
|
344
|
+
public string value;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
public interface IRemoteConfig
|
|
348
|
+
{
|
|
349
|
+
void ResolveDependencies(Action<bool> onComplete);
|
|
350
|
+
void FetchConfig(bool isFirstTime, Action<bool, Dictionary<string, string>> onComplete);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
using System;
|
|
2
2
|
using Amanotes.Core.Internal;
|
|
3
3
|
using UnityEngine;
|
|
4
|
-
using FileUtils = Amanotes.Core.Internal.FileUtils;
|
|
5
|
-
|
|
6
4
|
namespace Amanotes.Core
|
|
7
5
|
{
|
|
8
6
|
public partial class AmaGDK //User profile
|
|
@@ -10,10 +8,10 @@ namespace Amanotes.Core
|
|
|
10
8
|
public static readonly UserProfile User = new UserProfile().Load();
|
|
11
9
|
|
|
12
10
|
[Serializable]
|
|
13
|
-
public partial class UserProfile: IJsonFile
|
|
11
|
+
public partial class UserProfile : IJsonFile
|
|
14
12
|
{
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
private const string FILE_NAME = nameof(UserProfile);
|
|
14
|
+
[NonSerialized] internal bool _dirty;
|
|
17
15
|
|
|
18
16
|
public void Save()
|
|
19
17
|
{
|
|
@@ -22,9 +20,8 @@ namespace Amanotes.Core
|
|
|
22
20
|
|
|
23
21
|
public UserProfile Load()
|
|
24
22
|
{
|
|
25
|
-
|
|
26
|
-
if (string.IsNullOrEmpty(json))
|
|
27
|
-
return this;
|
|
23
|
+
string json = FileUtils.Load(FILE_NAME);
|
|
24
|
+
if (string.IsNullOrEmpty(json)) return this;
|
|
28
25
|
JsonUtility.FromJsonOverwrite(json, this);
|
|
29
26
|
return this;
|
|
30
27
|
}
|