com.amanotes.gdk 0.2.13 → 0.2.16

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.
Files changed (30) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/Editor/EmbedRemoteConfigAssetInspector.cs +191 -0
  3. package/Editor/EmbedRemoteConfigAssetInspector.cs.meta +11 -0
  4. package/Editor/MatchSDKVersion.cs +151 -0
  5. package/Editor/MatchSDKVersion.cs.meta +11 -0
  6. package/Editor/Utils/AmaGDKEditor.ExtractVersion.cs +1 -1
  7. package/Editor/Utils/AmaGDKEditor.Utils.cs +52 -0
  8. package/Extra/AmaGDKInstaller.unitypackage +0 -0
  9. package/Extra/AmaGDKProject.unitypackage +0 -0
  10. package/Packages/AdjustAdapter_v4.33.0.unitypackage +0 -0
  11. package/Packages/AmaGDKConfig.unitypackage +0 -0
  12. package/Packages/AmaGDKExample.unitypackage +0 -0
  13. package/Packages/AmaGDKTest.unitypackage +0 -0
  14. package/Packages/AmaPassport.ATTSupport.unitypackage +0 -0
  15. package/Packages/AmaPassportAdapter_v1.0.0.unitypackage +0 -0
  16. package/Packages/AppsFlyerAdapter_v6.5.4.unitypackage +0 -0
  17. package/Packages/FirebaseAnalyticsAdapter_v9.1.0.unitypackage +0 -0
  18. package/Packages/FirebaseRemoteConfigAdapter_v9.1.0.unitypackage +0 -0
  19. package/Packages/IronsourceAdapter_v7.2.6.unitypackage +0 -0
  20. package/Runtime/AmaGDK.AmaPassport.cs +1 -0
  21. package/Runtime/AmaGDK.Analytics.cs +22 -3
  22. package/Runtime/AmaGDK.IAP.cs +423 -0
  23. package/Runtime/AmaGDK.IAP.cs.meta +11 -0
  24. package/Runtime/AmaGDK.RemoteConfig.cs +73 -43
  25. package/Runtime/AmaGDK.cs +3 -2
  26. package/Runtime/AnalyticQualityAsset.cs +218 -0
  27. package/Runtime/AnalyticQualityAsset.cs.meta +11 -0
  28. package/Runtime/EmbedRemoteConfigAsset.cs +59 -0
  29. package/Runtime/EmbedRemoteConfigAsset.cs.meta +11 -0
  30. package/package.json +2 -2
@@ -0,0 +1,423 @@
1
+ using System;
2
+ using System.Collections;
3
+ using System.Collections.Generic;
4
+ using UnityEngine;
5
+ using Amanotes.Core.Internal;
6
+
7
+ using static Amanotes.Core.AmaGDK.IAP;
8
+ using static Amanotes.Core.Internal.Logging;
9
+
10
+ namespace Amanotes.Core
11
+ {
12
+ public partial class AmaGDK //In-app purchase
13
+ {
14
+ public partial class IAP //Public
15
+ {
16
+ public static bool IsVIP => !string.IsNullOrEmpty(localData.activeSubscriptionId);
17
+
18
+ public static string ActiveSubscriptionId => localData.activeSubscriptionId;
19
+
20
+ public static Dictionary<string, ProductInfo> AllProducts => dicProducts;
21
+
22
+ public static ISetupBuilder GetProducts()
23
+ {
24
+ var result = new SetupContext();
25
+ ExecuteInNextFrame(result.GetProducts);
26
+ return result;
27
+ }
28
+
29
+ public static IPurchaseBuilder Purchase(string productId)
30
+ {
31
+ var result = new PurchaseContext();
32
+ ExecuteInNextFrame(() => result.Purchase(productId));
33
+ return result;
34
+ }
35
+
36
+ public static IPurchaseBuilder RestorePurchase()
37
+ {
38
+ var result = new PurchaseContext();
39
+ ExecuteInNextFrame(result.RestorePurchase);
40
+ return result;
41
+ }
42
+
43
+ public static ProductInfo GetProduct(string productId)
44
+ {
45
+ if (!dicProducts.ContainsKey(productId))
46
+ {
47
+ LogWarning($"[IAP] Not found product with id <{productId}>. Make sure you have called Setup() first.");
48
+ return null;
49
+ }
50
+
51
+ return dicProducts[productId];
52
+ }
53
+
54
+ public static List<string> GetActiveSubscriptions()
55
+ {
56
+ return IAPAdapter?.GetActiveSubscriptions();
57
+ }
58
+
59
+ public static List<string> GetPurchasedProductIds()
60
+ {
61
+ return localData.purchasedProducts;
62
+ }
63
+
64
+ public static bool IsPurchased(string productId)
65
+ {
66
+ var purchasedProductIds = GetPurchasedProductIds();
67
+ return purchasedProductIds != null && purchasedProductIds.Contains(productId);
68
+ }
69
+ }
70
+
71
+ public partial class IAP //Internal
72
+ {
73
+ internal static IIAPAdapter adapter;
74
+ internal static readonly IAPData localData = new IAPData().LoadJsonFromFile();
75
+ internal static IIAPAdapter IAPAdapter
76
+ {
77
+ get
78
+ {
79
+ if (adapter != null) return adapter;
80
+ LogWarning("[IAP] Adapter is not available.");
81
+ return null;
82
+ }
83
+ }
84
+
85
+ private static IAPAdapterConfig _adapterConfig;
86
+ internal static IAPAdapterConfig AdapterConfig
87
+ {
88
+ get
89
+ {
90
+ if (_adapterConfig != null) return _adapterConfig;
91
+ LogWarning("[IAP] Adapter config is not available.");
92
+ return null;
93
+ }
94
+ }
95
+
96
+ internal static Dictionary<string, ProductInfo> dicProducts = new Dictionary<string, ProductInfo>();
97
+
98
+ internal static void Init()
99
+ {
100
+ adapter = Adapter.GetSingleAdapter<IIAPAdapter>();
101
+ var adapterContext = adapter as AdapterContext;
102
+
103
+ if (adapterContext == null) return;
104
+ _adapterConfig = adapterContext?.GetAdapterConfig<IAPAdapterConfig>();
105
+
106
+ if (!adapterContext.IsReady) return;
107
+ localData.Sync();
108
+ if (_adapterConfig.autoGetProducts)
109
+ GetProducts();
110
+ }
111
+
112
+ internal static void ExecuteInNextFrame(Action method)
113
+ {
114
+ _instance.StartCoroutine(ExecuteRoutine(method));
115
+ }
116
+
117
+ static IEnumerator ExecuteRoutine(Action method)
118
+ {
119
+ yield return null;
120
+ method?.Invoke();
121
+ }
122
+ }
123
+
124
+ public partial class IAP //Persistent
125
+ {
126
+ [Serializable]
127
+ internal class IAPData : IJsonFile
128
+ {
129
+ public string activeSubscriptionId;
130
+ public List<string> purchasedProducts;
131
+
132
+ public void Sync()
133
+ {
134
+ activeSubscriptionId = adapter.GetActiveSubscriptionId();
135
+ purchasedProducts = adapter.GetPurchasedProducts();
136
+ this.SaveJsonToFile();
137
+ }
138
+ }
139
+ }
140
+ }
141
+
142
+ public enum ProductType
143
+ {
144
+ Subscription,
145
+ Consumable,
146
+ NonConsumable
147
+ }
148
+
149
+ [Serializable]
150
+ public class ProductInfo
151
+ {
152
+ public string id;
153
+ public ProductType type;
154
+ [HideInInspector] public string title;
155
+ [HideInInspector] public string description;
156
+ [HideInInspector] public float price;
157
+ [HideInInspector] public string currencyCode;
158
+ [HideInInspector] public string[] discountIds;
159
+ }
160
+
161
+ public class PurchaseSuccess
162
+ {
163
+ public string productId;
164
+ public string transactionId;
165
+ public string receipt;
166
+ public string purchaseToken;
167
+ }
168
+
169
+ public class PurchaseError
170
+ {
171
+ public string productId;
172
+ public bool isCancelled;
173
+ public string error;
174
+
175
+ public PurchaseError()
176
+ {
177
+ }
178
+
179
+ public PurchaseError(string errorMessage)
180
+ {
181
+ error = errorMessage;
182
+ }
183
+ }
184
+
185
+ public static class IAPExtension
186
+ {
187
+ //GetProducts extensions
188
+ public static ISetupBuilder SetSubscriptions(this ISetupBuilder sc, params string[] subs)
189
+ {
190
+ if (sc == null) return null;
191
+
192
+ foreach (var pId in subs)
193
+ {
194
+ AdapterConfig?.products.Add(new ProductInfo() { id = pId, type = ProductType.Subscription });
195
+ }
196
+ return sc;
197
+ }
198
+
199
+ public static ISetupBuilder SetConsumables(this ISetupBuilder sc, params string[] cons)
200
+ {
201
+ if (sc == null) return null;
202
+
203
+ foreach (var pId in cons)
204
+ {
205
+ AdapterConfig?.products.Add(new ProductInfo() { id = pId, type = ProductType.Consumable });
206
+ }
207
+ return sc;
208
+ }
209
+
210
+ public static ISetupBuilder SetNonComsumables(this ISetupBuilder sc, params string[] nons)
211
+ {
212
+ if (sc == null) return null;
213
+
214
+ foreach (var pId in nons)
215
+ {
216
+ AdapterConfig?.products.Add(new ProductInfo() { id = pId, type = ProductType.NonConsumable });
217
+ }
218
+ return sc;
219
+ }
220
+
221
+ public static ISetupBuilder OnSuccess(this ISetupBuilder sc, Action<Dictionary<string, ProductInfo>> callback)
222
+ {
223
+ if (sc == null) return null;
224
+
225
+ var setupContext = sc as SetupContext;
226
+ setupContext.onSuccess = callback;
227
+ return sc;
228
+ }
229
+
230
+ public static ISetupBuilder OnFail(this ISetupBuilder sc, Action<string> callback)
231
+ {
232
+ if (sc == null) return null;
233
+
234
+ var setupContext = sc as SetupContext;
235
+ setupContext.onFail = callback;
236
+ return sc;
237
+ }
238
+
239
+ //Purchase extensions
240
+ public static IPurchaseBuilder OnSuccess(this IPurchaseBuilder pb, Action<PurchaseSuccess> callback)
241
+ {
242
+ if (pb == null) return null;
243
+
244
+ var purchaseContext = pb as PurchaseContext;
245
+ purchaseContext.onSuccess = callback;
246
+ return pb;
247
+ }
248
+
249
+ public static IPurchaseBuilder OnFail(this IPurchaseBuilder pb, Action<PurchaseError> callback)
250
+ {
251
+ if (pb == null) return null;
252
+
253
+ var purchaseContext = pb as PurchaseContext;
254
+ purchaseContext.onFail = callback;
255
+ return pb;
256
+ }
257
+
258
+ public static IPurchaseBuilder SetDiscount(this IPurchaseBuilder pb, string discountId)
259
+ {
260
+ if (pb == null) return null;
261
+
262
+ var purchaseContext = pb as PurchaseContext;
263
+ purchaseContext.discountId = discountId;
264
+ return pb;
265
+ }
266
+ }
267
+ }
268
+
269
+ namespace Amanotes.Core.Internal
270
+ {
271
+ [Serializable]
272
+ public class IAPAdapterConfig
273
+ {
274
+ [SerializeField] internal bool allPurchaseSuccessInEditor;
275
+ [SerializeField] internal List<ProductInfo> products;
276
+ [SerializeField] internal bool autoGetProducts;
277
+ }
278
+
279
+ public interface ISetupBuilder { }
280
+
281
+ public class SetupContext: ISetupBuilder
282
+ {
283
+ public Action<Dictionary<string, ProductInfo>> onSuccess;
284
+ public Action<string> onFail;
285
+
286
+ private readonly Queue<(List<string> pIds, ProductType pType)> getProdQueue = new Queue<(List<string> pIds, ProductType pType)>();
287
+
288
+ public void GetProducts()
289
+ {
290
+ if (AdapterConfig?.products.Count == 0)
291
+ {
292
+ LogWarning("There is no IAP product");
293
+ return;
294
+ }
295
+
296
+ getProdQueue.Clear();
297
+ var subs = new List<string>();
298
+ var cons = new List<string>();
299
+ var nons = new List<string>();
300
+
301
+ foreach (var p in AdapterConfig.products)
302
+ {
303
+ switch (p.type)
304
+ {
305
+ case ProductType.Subscription:
306
+ subs.Add(p.id);
307
+ break;
308
+ case ProductType.Consumable:
309
+ cons.Add(p.id);
310
+ break;
311
+ case ProductType.NonConsumable:
312
+ nons.Add(p.id);
313
+ break;
314
+ default:
315
+ LogWarning($"[IAP] Product <{p.id}> has not specified ProductType.");
316
+ break;
317
+ }
318
+ }
319
+
320
+ getProdQueue.Enqueue((subs, ProductType.Subscription));
321
+ getProdQueue.Enqueue((cons, ProductType.Consumable));
322
+ getProdQueue.Enqueue((nons, ProductType.NonConsumable));
323
+ GetNextProductsInQueue();
324
+ }
325
+
326
+ void GetNextProductsInQueue()
327
+ {
328
+ if (getProdQueue.Count <= 0)
329
+ {
330
+ onSuccess?.Invoke(dicProducts);
331
+ return;
332
+ }
333
+
334
+ var item = getProdQueue.Dequeue();
335
+ GetProductsByType(item.pIds, item.pType);
336
+ }
337
+
338
+ void GetProductsByType(List<string> lsProduct, ProductType type)
339
+ {
340
+ try
341
+ {
342
+ IAPAdapter?.GetProducts(lsProduct.ToArray(), type, (pList) =>
343
+ {
344
+ foreach (var pI in pList)
345
+ {
346
+ dicProducts.Add(pI.id, pI);
347
+ }
348
+ ExecuteInNextFrame(GetNextProductsInQueue);
349
+ });
350
+ }
351
+ catch (Exception e)
352
+ {
353
+ LogWarning($"[IAP] Error on getting products of type <{type}>. Error detail:\n{e.Message}");
354
+ onFail?.Invoke(e.Message);
355
+ throw;
356
+ }
357
+ }
358
+ }
359
+
360
+ public interface IPurchaseBuilder { }
361
+
362
+ public class PurchaseContext : IPurchaseBuilder
363
+ {
364
+ public Action<PurchaseSuccess> onSuccess;
365
+ public Action<PurchaseError> onFail;
366
+ public string discountId;
367
+
368
+ public void Purchase(string productId)
369
+ {
370
+ if (!dicProducts.ContainsKey(productId))
371
+ {
372
+ LogWarning($"[IAP] Product {productId} is not found");
373
+ return;
374
+ }
375
+
376
+ #if UNITY_EDITOR
377
+ if (AdapterConfig.allPurchaseSuccessInEditor)
378
+ {
379
+ DoOnSuccess(new PurchaseSuccess
380
+ {
381
+ productId = productId
382
+ });
383
+ return;
384
+ }
385
+ #endif
386
+
387
+ if (!string.IsNullOrWhiteSpace(discountId))
388
+ {
389
+ IAPAdapter?.PurchaseDiscount(productId, dicProducts[productId].type, discountId, DoOnSuccess, DoOnFail);
390
+ return;
391
+ }
392
+
393
+ IAPAdapter?.Purchase(productId, dicProducts[productId].type, DoOnSuccess, DoOnFail);
394
+ }
395
+
396
+ public void RestorePurchase()
397
+ {
398
+ IAPAdapter?.RestorePurchase(DoOnSuccess, DoOnFail);
399
+ }
400
+
401
+ void DoOnSuccess(PurchaseSuccess success)
402
+ {
403
+ localData.Sync();
404
+ onSuccess?.Invoke(success);
405
+ }
406
+
407
+ void DoOnFail(PurchaseError error)
408
+ {
409
+ onFail?.Invoke(error);
410
+ }
411
+ }
412
+
413
+ public interface IIAPAdapter
414
+ {
415
+ void GetProducts(string[] productIds, ProductType productType, Action<ProductInfo[]> onComplete);
416
+ void Purchase(string productId, ProductType productType, Action<PurchaseSuccess> onSuccess, Action<PurchaseError> onFail);
417
+ void PurchaseDiscount(string productId, ProductType productType, string discountId, Action<PurchaseSuccess> onSuccess, Action<PurchaseError> onFail);
418
+ void RestorePurchase(Action<PurchaseSuccess> onSuccess, Action<PurchaseError> onFail);
419
+ List<string> GetActiveSubscriptions();
420
+ List<string> GetPurchasedProducts();
421
+ string GetActiveSubscriptionId();
422
+ }
423
+ }
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: a49a40b8b04e3450b9dac915b22533de
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
@@ -16,8 +16,7 @@ namespace Amanotes.Core
16
16
  {
17
17
  public enum RemoteConfigSource
18
18
  {
19
- DefaultAsset,
20
- DefaultFile,
19
+ EmbedConfig,
21
20
  Cache,
22
21
  Internet
23
22
  }
@@ -26,7 +25,7 @@ namespace Amanotes.Core
26
25
  public partial class RemoteConfig //Public
27
26
  {
28
27
  public static Action<bool> onFetchCompleted;
29
- public static Dictionary<string, string> DictConfig { get { return dictConfig; } }
28
+ public static Dictionary<string, string> DictConfig => dictConfig;
30
29
  public static RemoteConfigSource Source { private set; get; }
31
30
  static bool? _cacheExisted = null;
32
31
  public static bool HasCache
@@ -64,6 +63,15 @@ namespace Amanotes.Core
64
63
 
65
64
  public static T Get<T>(string key, T defaultValue = default(T))
66
65
  {
66
+ #if UNITY_EDITOR
67
+ //Override value in editor environment
68
+ if (adapterConfig.embedRemoteConfig.overrideInEditor)
69
+ {
70
+ foreach (var c in adapterConfig.embedRemoteConfig.overrideConfig)
71
+ if (c.key == key)
72
+ return (T)Convert.ChangeType(c.value, typeof(T));
73
+ }
74
+ #endif
67
75
  if (dictConfig.ContainsKey(key))
68
76
  return (T)Convert.ChangeType(dictConfig[key], typeof(T));
69
77
  return defaultValue;
@@ -78,6 +86,13 @@ namespace Amanotes.Core
78
86
  {
79
87
  return JsonUtils.DictionaryToJson(dictConfig);
80
88
  }
89
+
90
+ public static void SetActiveEmbedConfig(string id)
91
+ {
92
+ if (adapterConfig == null || adapterConfig.embedRemoteConfig == null)
93
+ LogWarning("[RemoteConfig] No embed remote config available");
94
+ adapterConfig.embedRemoteConfig.SetActiveConfig(id);
95
+ }
81
96
  }
82
97
 
83
98
  public partial class RemoteConfig //Internal
@@ -91,7 +106,7 @@ namespace Amanotes.Core
91
106
  SaveCache,
92
107
 
93
108
  LoadCache,
94
- LoadDefaultAsset,
109
+ LoadEmbedConfig,
95
110
 
96
111
  Success,
97
112
  Fail
@@ -100,9 +115,15 @@ namespace Amanotes.Core
100
115
  static Dictionary<string, string> dictConfig = new Dictionary<string, string>();
101
116
  static string fileName = $"{nameof(RemoteConfig)}.kv";
102
117
  static string base64Prefix = "base64:";
118
+ const string VERSION_PREFIX = "version:";
119
+ static int EmbedVersion =>
120
+ adapterConfig != null && adapterConfig.embedRemoteConfig != null
121
+ ? adapterConfig.embedRemoteConfig.version
122
+ : 1;
103
123
 
104
124
  static FetchState _state = FetchState.None;
105
- internal static FetchState State { get { return _state; } }
125
+ internal static FetchState State => _state;
126
+
106
127
  static readonly Dictionary<FetchState, Action[]> fetchSM = new Dictionary<FetchState, Action[]>
107
128
  {
108
129
  { FetchState.None, new Action[]{ ResolveDependency }},
@@ -110,8 +131,8 @@ namespace Amanotes.Core
110
131
  { FetchState.CheckInternet, new Action[]{ LoadCache, Fetch}},
111
132
  { FetchState.Fetch, new Action[]{ LoadCache, SaveCache}},
112
133
  { FetchState.SaveCache, new Action[]{ SetDone }},
113
- { FetchState.LoadCache, new Action[]{ LoadDefaultAsset, SetDone}},
114
- { FetchState.LoadDefaultAsset, new Action[]{ SetFail, SetDone}}
134
+ { FetchState.LoadCache, new Action[]{ LoadEmbedConfig, SetDone}},
135
+ { FetchState.LoadEmbedConfig, new Action[]{ SetFail, SetDone}}
115
136
  };
116
137
 
117
138
  internal static IRemoteConfig adapter;
@@ -177,27 +198,14 @@ namespace Amanotes.Core
177
198
  {
178
199
  _state = FetchState.SaveCache;
179
200
  StringBuilder sb = new StringBuilder();
180
-
181
-
182
- bool needUpdateDefault = Application.isEditor && adapterConfig.autoUpdateDefaultValue;
183
- List<KeyValue> list = needUpdateDefault ? new List<KeyValue>() : null;
184
201
 
202
+ //Add embedded remote config version to force load from embedded config after app update
203
+ sb.AppendLine($"{VERSION_PREFIX}{EmbedVersion}");
204
+
185
205
  foreach (var c in dictConfig)
186
206
  {
187
207
  sb.AppendLine($"{c.Key}\t{Encode(c.Value)}");
188
- if (!needUpdateDefault) continue;
189
- list.Add(new KeyValue() { key = c.Key, value = c.Value });
190
- }
191
-
192
- #if UNITY_EDITOR
193
- if (needUpdateDefault)
194
- {
195
- list.Sort((item1, item2) => string.Compare(item1.key, item2.key, StringComparison.Ordinal));
196
- adapterConfig.defaultValue = list.ToArray();
197
- EditorUtility.SetDirty(_config);
198
- Log($"[RemoteConfig] Updated default remote config!");
199
208
  }
200
- #endif
201
209
 
202
210
  string filePath = GDKFileUtils.GetPath(fileName);
203
211
  GDKFileUtils.Save(filePath, sb.ToString());
@@ -220,15 +228,32 @@ namespace Amanotes.Core
220
228
  dictConfig.Clear();
221
229
  using (StreamReader sr = new StreamReader(GDKFileUtils.GetPath(fileName)))
222
230
  {
231
+ //Check new app update
232
+ string firstLine = sr.ReadLine();
233
+ if (firstLine == null)
234
+ {
235
+ NextState(false);
236
+ return;
237
+ }
238
+ if (ShouldClearCache(firstLine))
239
+ {
240
+ GDKFileUtils.Delete(fileName);
241
+ string oldVersion = firstLine.StartsWith(VERSION_PREFIX) ? firstLine : "<none>";
242
+ Log($"[RemoteConfig] Cached remote config cleared due to embed version changed:\n{oldVersion} -> {EmbedVersion}");
243
+ NextState(false);
244
+ return;
245
+ }
246
+
247
+ //Read key-value
223
248
  string line;
224
- int lineIdx = 0;
249
+ int lineNo = 1;
225
250
  while ((line = sr.ReadLine()) != null)
226
251
  {
227
- lineIdx++;
252
+ lineNo++;
228
253
  var idx = line.IndexOf('\t');
229
254
  if (idx == -1)
230
255
  {
231
- LogWarning($"[RemoteConfig] Cannot get (key, value) at line {lineIdx} of cache");
256
+ LogWarning($"[RemoteConfig] Cannot get (key, value) at line {lineNo} of cache. Content:\n<{line}>");
232
257
  continue;
233
258
  }
234
259
  string key = line.Substring(0, idx);
@@ -250,24 +275,30 @@ namespace Amanotes.Core
250
275
  NextState(true);
251
276
  }
252
277
 
253
- static void LoadDefaultAsset()
278
+ static void LoadEmbedConfig()
254
279
  {
255
- _state = FetchState.LoadDefaultAsset;
280
+ _state = FetchState.LoadEmbedConfig;
281
+
282
+ if (adapterConfig == null || adapterConfig.embedRemoteConfig == null)
283
+ {
284
+ NextState(false);
285
+ return;
286
+ }
256
287
 
257
- var defaultValue = ((AdapterContext)adapter).GetAdapterConfig<RemoteConfigConfig>().defaultValue;
288
+ var config = adapterConfig.embedRemoteConfig.ActiveConfig;
258
289
 
259
- if (defaultValue.Length == 0)
290
+ if (config == null || config.items.Length == 0)
260
291
  {
261
292
  NextState(false);
262
293
  return;
263
294
  }
264
295
 
265
- foreach (var item in defaultValue)
296
+ foreach (var item in config.items)
266
297
  {
267
298
  dictConfig.Add(item.key, item.value);
268
299
  }
269
- Source = RemoteConfigSource.DefaultAsset;
270
- Log("[RemoteConfig] Load from default asset");
300
+ Source = RemoteConfigSource.EmbedConfig;
301
+ Log("[RemoteConfig] Load from embed asset");
271
302
  NextState(true);
272
303
  }
273
304
 
@@ -301,6 +332,12 @@ namespace Amanotes.Core
301
332
  s = s.Remove(0, base64Prefix.Length);
302
333
  return Encoding.UTF8.GetString(Convert.FromBase64String(s));
303
334
  }
335
+
336
+ static bool ShouldClearCache(string cacheVersion)
337
+ {
338
+ if (!cacheVersion.StartsWith(VERSION_PREFIX)) return true;
339
+ return cacheVersion != VERSION_PREFIX + EmbedVersion;
340
+ }
304
341
  }
305
342
  }
306
343
 
@@ -324,19 +361,12 @@ namespace Amanotes.Core.Internal
324
361
  [Serializable]
325
362
  public class RemoteConfigConfig
326
363
  {
327
- public bool autoUpdateDefaultValue;
328
- public KeyValue[] defaultValue;
364
+ [SerializeField]
365
+ internal EmbedRemoteConfigAsset embedRemoteConfig;
329
366
  public float firstFetchTimeOutInSeconds = 10;
330
367
  public float defaultTimeOutInSeconds = 3;
331
368
  }
332
-
333
- [Serializable]
334
- public class KeyValue
335
- {
336
- public string key;
337
- public string value;
338
- }
339
-
369
+
340
370
  public interface IRemoteConfig
341
371
  {
342
372
  void ResolveDependencies(Action<bool> onComplete);
package/Runtime/AmaGDK.cs CHANGED
@@ -14,7 +14,7 @@ namespace Amanotes.Core
14
14
  {
15
15
  public partial class AmaGDK : MonoBehaviour
16
16
  {
17
- public const string VERSION = "0.2.13";
17
+ public const string VERSION = "0.2.14";
18
18
 
19
19
  internal static AmaGDK _instance;
20
20
  internal static Status _status = Status.None;
@@ -109,6 +109,7 @@ namespace Amanotes.Core
109
109
  AmaPassport.Init();
110
110
  Analytics.Init();
111
111
  Ads.Init();
112
+ IAP.Init();
112
113
 
113
114
  _status = Status.Ready;
114
115
  _onReadyCallback?.Invoke();
@@ -242,7 +243,7 @@ namespace Amanotes.Core
242
243
  public void ChangeDevMode()
243
244
  {
244
245
  string variableName = "GDK_HOME";
245
- string output = RunShellCommand($"source ~/.zshrc && echo ${variableName}");
246
+ string output = RunShellCommand($"source ~/.zshrc && echo file:${variableName}");
246
247
  output = output.Trim();
247
248
 
248
249
  if (string.IsNullOrEmpty(output))