com.amanotes.gdk 0.2.19 → 0.2.21
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 +95 -86
- package/Editor/UserProfile.PostBuild.cs.meta +1 -1
- package/Editor/UserProfileDependencies.xml.meta +1 -1
- package/Extra/AmaGDKInstaller.unitypackage +0 -0
- package/Extra/AmaGDKProject.unitypackage +0 -0
- package/Packages/AmaGDKConfig.unitypackage +0 -0
- package/Packages/AmaGDKExample.unitypackage +0 -0
- package/Packages/AmaGDKTest.unitypackage +0 -0
- 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/Packages/IronSourceAdapter_v7.2.6.unitypackage +0 -0
- package/Packages/RevenueCatAdapter_v6.0.0.unitypackage +0 -0
- package/Packages/{RevenueCatAdapter_v5.1.3.unitypackage.meta → RevenueCatAdapter_v6.0.0.unitypackage.meta} +1 -1
- package/README.md +51 -6
- package/Runtime/AmaGDK.Analytics.cs +34 -21
- package/Runtime/AmaGDK.Config.cs +10 -1
- package/Runtime/AmaGDK.IAP.cs +126 -30
- package/Runtime/AmaGDK.Internal.cs +9 -8
- package/Runtime/AmaGDK.UserProfile.cs +21 -12
- package/Runtime/AmaGDK.cs +4 -3
- package/Runtime/UserProfile/Plugins/Android/AdvertisingIdFetcher.java.meta +1 -1
- package/Runtime/UserProfile/Plugins/Android.meta +1 -1
- package/package.json +1 -1
- package/Packages/RevenueCatAdapter_v5.1.3.unitypackage +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,149 +1,158 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.21 - 2023-10-11]
|
|
4
|
+
- RevenueCat adapter v6.0.0
|
|
5
|
+
- Handle early Firebase call
|
|
6
|
+
- Fix null exception in non-subscription game
|
|
7
|
+
- Add log level
|
|
8
|
+
|
|
9
|
+
## [0.2.20 - 2023-10-05]
|
|
10
|
+
- Update RevenueCat 5.3.0
|
|
11
|
+
|
|
3
12
|
## [0.2.19 - 2023-09-12]
|
|
4
|
-
|
|
13
|
+
- Add `ama_device_id` to all events
|
|
5
14
|
|
|
6
15
|
## [0.2.18 - 2023-09-11]
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
16
|
+
- Add dev mode switch
|
|
17
|
+
- Auto get SDK version
|
|
18
|
+
- Add in-app purchase module, RevenueCat
|
|
19
|
+
- Support Unity 2019.4
|
|
20
|
+
- Remove AmaPassport
|
|
12
21
|
|
|
13
22
|
## [0.2.14 - 2023-08-08]
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
- Support multiple embed remote config and load config by id
|
|
24
|
+
- Clear cached remote config on new app update
|
|
25
|
+
- Override remote config value in editor mode
|
|
26
|
+
- New feature: Analytics Quality
|
|
18
27
|
|
|
19
28
|
## [0.2.13 - 2023-07-20]
|
|
20
|
-
|
|
29
|
+
- Fix error Remote Config JSON caused by special chars (", ', \)
|
|
21
30
|
|
|
22
31
|
## [0.2.12 - 2023-07-07]
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
32
|
+
- Restructure GDK - symlink GDK source to unity projects
|
|
33
|
+
- Unity 2019 compatible - no null coalescing
|
|
34
|
+
- Remove redundant AmaPassport config field
|
|
35
|
+
- Auto request AmaId
|
|
27
36
|
|
|
28
37
|
## [0.2.11 - 2023-06-29]
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
38
|
+
- SetLogCondition with EventParam
|
|
39
|
+
- Rename Migrated -> HasMigrated
|
|
40
|
+
- Fix StopShowAd
|
|
32
41
|
|
|
33
42
|
## [0.2.10 - 2023-06-23]
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
43
|
+
- Extra package: Project Panel
|
|
44
|
+
- Remote config: Allow user to enable / disable automatic default valuye updating (in play mode)
|
|
45
|
+
- Fix ad routine
|
|
46
|
+
- Expose analytics migration flag
|
|
38
47
|
|
|
39
48
|
## [0.2.9 - 2023-06-15]
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
- Show total init time
|
|
50
|
+
- Show adapter version + status at init time
|
|
51
|
+
- Remove AmaGDK version in debug log
|
|
52
|
+
- Remove "Params" in analytics debug log
|
|
53
|
+
- Check "event_name" early
|
|
54
|
+
- Fix null exception in AmaGDKInstaller
|
|
55
|
+
- Add csc.rsp to enable AMAGDK_DEV
|
|
56
|
+
- Update Ads module
|
|
48
57
|
|
|
49
58
|
## [0.2.8 - 2023-06-12]
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
59
|
+
- Mute Appsflyer's init log on Editor
|
|
60
|
+
- Clear analytics log in adapters
|
|
61
|
+
- Check null event params before calling AddParam()
|
|
62
|
+
- Export AmaPassport info
|
|
54
63
|
|
|
55
64
|
## [0.2.7 - 2023-06-09]
|
|
56
|
-
|
|
65
|
+
- Fix log single adapter
|
|
57
66
|
|
|
58
67
|
## [0.2.6 - 2023-06-08]
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
68
|
+
- Update AmaPassport
|
|
69
|
+
- Fix JSON parse in RemoteConfig
|
|
70
|
+
- Ads adds interstitial callbacks
|
|
71
|
+
- Clean & export AmaGDK Installer
|
|
63
72
|
|
|
64
73
|
## [0.2.5 - 2023-06-07]
|
|
65
|
-
|
|
74
|
+
- Remove ATT dependency package
|
|
66
75
|
|
|
67
76
|
## [0.2.4 - 2023-06-07]
|
|
68
|
-
|
|
69
|
-
|
|
77
|
+
- Hotfix Ads module
|
|
78
|
+
- Update Analytics unit tests
|
|
70
79
|
|
|
71
80
|
## [0.2.3 - 2023-06-06]
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
81
|
+
- Refactor Ads module, support ironSource
|
|
82
|
+
- Refactor AmaPassport
|
|
83
|
+
- Refactor AmaGDK structure
|
|
84
|
+
- Add callback when RemoteConfig module completes fetching
|
|
76
85
|
|
|
77
86
|
## [0.1.20 - 2023-04-20]
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
87
|
+
- Refactor Adapter architure to support reading adapter config from Core
|
|
88
|
+
- Add session stat for Analytics module
|
|
89
|
+
- Unit test for Json parser and Analytics module
|
|
81
90
|
|
|
82
91
|
## [0.1.19 - 2023-04-11]
|
|
83
|
-
|
|
92
|
+
- Move AmaGDKTest out of AmaGDKCore
|
|
84
93
|
|
|
85
94
|
## [0.1.18 - 2023-03-27]
|
|
86
|
-
|
|
95
|
+
- Fix AmaGDK's autoInit saving issue
|
|
87
96
|
|
|
88
97
|
## [0.1.17 - 2023-03-13]
|
|
89
|
-
|
|
90
|
-
|
|
98
|
+
- Release AmaGDK v0.1.17
|
|
99
|
+
- Rename Analytics APIs
|
|
91
100
|
|
|
92
101
|
## [0.1.16 - 2023-03-10]
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
102
|
+
- Release AmaGDK v0.1.16
|
|
103
|
+
- SemVer supports 4 parts
|
|
104
|
+
- Analytics supports EventConfig
|
|
96
105
|
|
|
97
106
|
## [0.1.15 - 2023-03-06]
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
107
|
+
- Release AmaGDK v0.1.15
|
|
108
|
+
- Fix null exception in VersionExtractor
|
|
109
|
+
- Warn unhandle platform in Appsflyer initialization
|
|
110
|
+
- Allow dev to SetPermittedEvents and SetForbiddenEvents to the adapter config
|
|
102
111
|
|
|
103
112
|
## [0.1.14 - 2023-03-02]
|
|
104
|
-
|
|
113
|
+
- Release AmaGDK v0.1.14
|
|
105
114
|
|
|
106
115
|
## [0.1.13 - 2023-03-01]
|
|
107
|
-
|
|
108
|
-
|
|
116
|
+
- Release AmaGDK v0.1.13
|
|
117
|
+
- Fix Semver parser
|
|
109
118
|
|
|
110
119
|
## [0.1.12 - 2023-03-01]
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
120
|
+
- Release AmaGDK v0.1.12
|
|
121
|
+
- Prioritize analytics instant config over the base config
|
|
122
|
+
- Public common config
|
|
114
123
|
|
|
115
124
|
## [0.1.11 - 2023-02-28]
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
125
|
+
- Release AmaGDK v0.1.11
|
|
126
|
+
- Auto start and log Appsflyer open session
|
|
127
|
+
- Add analytics adapter base config
|
|
128
|
+
- Analytics: count by session
|
|
129
|
+
- Export example scene
|
|
130
|
+
- Add AmaGDKManager
|
|
131
|
+
- Refactor Adapter to support for init order configuration
|
|
123
132
|
|
|
124
133
|
## [0.1.10 - 2023-02-17]
|
|
125
|
-
|
|
134
|
+
- Release AmaGDK v0.1.10
|
|
126
135
|
|
|
127
136
|
## [0.1.9 - 2023-02-15]
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
137
|
+
- Release AmaGDK v0.1.9
|
|
138
|
+
- Change Documentation URL
|
|
139
|
+
- Support API LogEvent(eventName, parameters)
|
|
131
140
|
|
|
132
141
|
## [0.1.8 - 2023-02-15]
|
|
133
|
-
|
|
134
|
-
|
|
142
|
+
- Release AmaGDK v0.1.8
|
|
143
|
+
- Add AdapterID
|
|
135
144
|
|
|
136
145
|
## [0.1.5 - 2023-02-13]
|
|
137
|
-
|
|
138
|
-
|
|
146
|
+
- Release AmaSDK v0.1.5
|
|
147
|
+
- Validate EventParams
|
|
139
148
|
|
|
140
149
|
## [0.1.4 - 2023-02-13]
|
|
141
|
-
|
|
150
|
+
- Release AmaSDK v0.1.4
|
|
142
151
|
|
|
143
152
|
## [0.1.3 - 2023-02-10]
|
|
144
|
-
|
|
153
|
+
- Release AmaSDK v0.1.3
|
|
145
154
|
|
|
146
155
|
## [0.1.2] - 2023-02-08
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
156
|
+
- Release AmaGDK 0.1.2
|
|
157
|
+
- FirebaseAnalytics adapter compatible with FirebaseAnalytics SDK v9
|
|
158
|
+
- AppsFlyer adapter compatible with AppsFlyer SDK v6
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/README.md
CHANGED
|
@@ -1,12 +1,57 @@
|
|
|
1
1
|
# Amanotes GDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## AmaGDK Dev Project Setup
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
### Clone Project From GitLab
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
1. Clone project from GitLab url: https://gitlab.amanotes.net/sdk/AmaSDK_v5
|
|
8
|
+
2. Open terminal windows and cd to your project
|
|
9
|
+
3. Run file create-links.sh (Link GDK folder children to GDKDev)
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
### How To Open Project
|
|
14
|
+
|
|
15
|
+
* Open project GDKDev
|
|
16
|
+
|
|
17
|
+

|
|
18
|
+
|
|
19
|
+
### Main folder
|
|
20
|
+
|
|
21
|
+
* AmaGDK: adapters logic, example, installer, configs
|
|
22
|
+
|
|
23
|
+
* AmaGDKCore: core logic, packages
|
|
24
|
+
|
|
25
|
+
* AmaGDKDev: tools for dev as build tool, release tool
|
|
26
|
+
|
|
27
|
+
* AmaGDKTest: scenes test, unit test
|
|
28
|
+
|
|
29
|
+

|
|
30
|
+
|
|
31
|
+
### Switch To Dev Mode
|
|
32
|
+
|
|
33
|
+
1. Add GDK_HOME variable to .zshrc file in Mac OS
|
|
34
|
+
|
|
35
|
+
* Step 1: Open terminal, input sudo nano `~/.zshrc`
|
|
36
|
+
|
|
37
|
+
* Step 2: Enter and input password, add new line export `GDK_HOME=/AmaGDKCoreFolderPath`
|
|
38
|
+
|
|
39
|
+
* Step 3: Press Ctr+X buttons -> Press Y button -> Press `Enter` button to save
|
|
40
|
+
|
|
41
|
+

|
|
42
|
+
|
|
43
|
+
2. Select AmaGDK prefab in scene → select `Change Dev Mode` in context menu
|
|
44
|
+
|
|
45
|
+

|
|
46
|
+
|
|
47
|
+
### Code Convention
|
|
48
|
+
[Convention](https://amanotesjsc.atlassian.net/wiki/spaces/AP/pages/3409413152)
|
|
49
|
+
|
|
50
|
+
### Links Reference
|
|
51
|
+
[Reference](https://amanotesjsc.atlassian.net/wiki/spaces/AP/pages/3334930473)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
## Getting started with AmaGDK
|
|
10
55
|
|
|
11
56
|
### Add AmaGDK prefab to your bootstrap scene (the first scene in your game build settings)
|
|
12
57
|
There are two ways to do:
|
|
@@ -35,10 +80,10 @@ public class YourGameSceneController
|
|
|
35
80
|
}
|
|
36
81
|
```
|
|
37
82
|
|
|
38
|
-
|
|
83
|
+
### Versioning
|
|
39
84
|
|
|
40
85
|
We use [SemVer](http://semver.org/) for versioning.
|
|
41
86
|
|
|
42
|
-
|
|
87
|
+
### License
|
|
43
88
|
|
|
44
89
|
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details
|
|
@@ -136,30 +136,12 @@ namespace Amanotes.Core
|
|
|
136
136
|
|
|
137
137
|
public static void SetUserId(string userId)
|
|
138
138
|
{
|
|
139
|
-
|
|
140
|
-
{
|
|
141
|
-
LogWarningOnce("ListAnalyticsAdapter is empty! Maybe you need to wait for Analytics to init");
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
foreach (AdapterContext s in listAdapters)
|
|
146
|
-
{
|
|
147
|
-
s.GetAdapterApi<IAnalyticAdapter>().SetUserId(userId);
|
|
148
|
-
}
|
|
139
|
+
actionQueue.Enqueue(() => InternalSetUserId(userId));
|
|
149
140
|
}
|
|
150
141
|
|
|
151
142
|
public static void SetUserProperty(string key, string value)
|
|
152
143
|
{
|
|
153
|
-
|
|
154
|
-
{
|
|
155
|
-
LogWarningOnce("ListAnalyticsAdapter is empty! Maybe you need to wait for Analytics to init");
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
foreach (AdapterContext s in listAdapters)
|
|
160
|
-
{
|
|
161
|
-
s.GetAdapterApi<IAnalyticAdapter>().SetUserProperty(key, value);
|
|
162
|
-
}
|
|
144
|
+
actionQueue.Enqueue(() => InternalSetUserProperty(key, value));
|
|
163
145
|
}
|
|
164
146
|
|
|
165
147
|
private static IntegrityFlag MergeData(List<string> funnelEvents, Dictionary<string, int> eventCountMap, bool sumEventCount)
|
|
@@ -285,6 +267,7 @@ namespace Amanotes.Core
|
|
|
285
267
|
internal static readonly Dictionary<string, EventConfig> sendAtCount = new Dictionary<string, EventConfig>();
|
|
286
268
|
internal static Predicate<EventParams> logEventHook = null;
|
|
287
269
|
internal static readonly Queue<EventParams> eventQueue = new Queue<EventParams>();
|
|
270
|
+
internal static readonly Queue<Action> actionQueue = new Queue<Action>();
|
|
288
271
|
internal static readonly List<AdapterContext> listAdapters = new List<AdapterContext>();
|
|
289
272
|
internal static readonly AnalyticsData localData = new AnalyticsData().LoadJsonFromFile();
|
|
290
273
|
internal static readonly SessionStat sessionStat = new SessionStat();
|
|
@@ -296,6 +279,9 @@ namespace Amanotes.Core
|
|
|
296
279
|
|
|
297
280
|
onFrameUpdate -= ProcessEventQueue;
|
|
298
281
|
onFrameUpdate += ProcessEventQueue;
|
|
282
|
+
|
|
283
|
+
onFrameUpdate -= ProcessActionQueue;
|
|
284
|
+
onFrameUpdate += ProcessActionQueue;
|
|
299
285
|
}
|
|
300
286
|
|
|
301
287
|
internal static void ProcessEventQueue()
|
|
@@ -389,7 +375,7 @@ namespace Amanotes.Core
|
|
|
389
375
|
sb.AppendLine($" - Malformed eventName (should not contains <space> or <dash>: <{eventName}>");
|
|
390
376
|
}
|
|
391
377
|
}
|
|
392
|
-
|
|
378
|
+
|
|
393
379
|
if (!char.IsLetter(eventName[0])) sb.AppendLine($" - EventName must start with a letter: <{eventName}> ");
|
|
394
380
|
if (eventName.Length > 40) sb.AppendLine($" - EventName is too long ({eventName.Length} > 40): <{eventName}> ");
|
|
395
381
|
if (sb.Length > 0 && dryRun) LogWarningOnce(sb.ToString(), $"NormalizeEventName<{eventName}>");
|
|
@@ -418,6 +404,33 @@ namespace Amanotes.Core
|
|
|
418
404
|
|
|
419
405
|
return true;
|
|
420
406
|
}
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
internal static void ProcessActionQueue()
|
|
410
|
+
{
|
|
411
|
+
if (actionQueue.Count <= 0) return;
|
|
412
|
+
while (actionQueue.Count > 0)
|
|
413
|
+
{
|
|
414
|
+
var action = actionQueue.Dequeue();
|
|
415
|
+
action.Invoke();
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
internal static void InternalSetUserId(string userId)
|
|
420
|
+
{
|
|
421
|
+
foreach (AdapterContext s in listAdapters)
|
|
422
|
+
{
|
|
423
|
+
s.GetAdapterApi<IAnalyticAdapter>().SetUserId(userId);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
internal static void InternalSetUserProperty(string key, string value)
|
|
428
|
+
{
|
|
429
|
+
foreach (AdapterContext s in listAdapters)
|
|
430
|
+
{
|
|
431
|
+
s.GetAdapterApi<IAnalyticAdapter>().SetUserProperty(key, value);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
421
434
|
}
|
|
422
435
|
|
|
423
436
|
//PERSISTENT DATA
|
package/Runtime/AmaGDK.Config.cs
CHANGED
|
@@ -83,10 +83,19 @@ namespace Amanotes.Core.Internal
|
|
|
83
83
|
#endif
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
[Flags]
|
|
87
|
+
public enum LogLevel
|
|
88
|
+
{
|
|
89
|
+
None = 0,
|
|
90
|
+
Error = 1,
|
|
91
|
+
Warning = 2,
|
|
92
|
+
Verbose = 4
|
|
93
|
+
}
|
|
94
|
+
|
|
86
95
|
[Serializable]
|
|
87
96
|
public partial class SDKConfig
|
|
88
97
|
{
|
|
89
|
-
public
|
|
98
|
+
public LogLevel logLevel = LogLevel.Warning | LogLevel.Error;
|
|
90
99
|
}
|
|
91
100
|
|
|
92
101
|
[Serializable]
|
package/Runtime/AmaGDK.IAP.cs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
using System;
|
|
2
2
|
using System.Collections;
|
|
3
3
|
using System.Collections.Generic;
|
|
4
|
+
using System.Globalization;
|
|
4
5
|
using UnityEngine;
|
|
5
6
|
using Amanotes.Core.Internal;
|
|
6
7
|
|
|
@@ -14,15 +15,21 @@ namespace Amanotes.Core
|
|
|
14
15
|
public partial class IAP //Public
|
|
15
16
|
{
|
|
16
17
|
public static bool IsVIP => !string.IsNullOrEmpty(localData.activeSubscriptionId);
|
|
17
|
-
|
|
18
18
|
public static string ActiveSubscriptionId => localData.activeSubscriptionId;
|
|
19
|
-
|
|
19
|
+
public static string SubscriptionPeriodType => localData.subscriptionPeriodType;
|
|
20
|
+
public static DateTime? SubscriptionLastPurchaseDate => localData.SubscriptionLastPurchaseDate;
|
|
21
|
+
public static DateTime? SubscriptionExpiredDate => localData.SubscriptionExpiredDate;
|
|
22
|
+
public static DateTime? UnsubscribedDate => localData.UnsubscribedDate;
|
|
20
23
|
public static Dictionary<string, ProductInfo> AllProducts => dicProducts;
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
private const string DATE_FORMAT = "yyyy/MM/yy HH:mm:ss";
|
|
25
|
+
|
|
26
|
+
public static ISetupBuilder GetProducts(bool appendExistingList = false)
|
|
23
27
|
{
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
if (!appendExistingList)
|
|
29
|
+
{
|
|
30
|
+
IAPExtension.isCleanUpConfig = false;
|
|
31
|
+
dicProducts.Clear();
|
|
32
|
+
}
|
|
26
33
|
var result = new SetupContext();
|
|
27
34
|
ExecuteInNextFrame(result.GetProducts);
|
|
28
35
|
return result;
|
|
@@ -31,7 +38,13 @@ namespace Amanotes.Core
|
|
|
31
38
|
public static IPurchaseBuilder Purchase(string productId)
|
|
32
39
|
{
|
|
33
40
|
var result = new PurchaseContext();
|
|
34
|
-
|
|
41
|
+
if (!dicProducts.ContainsKey(productId))
|
|
42
|
+
{
|
|
43
|
+
LogWarning($"[IAP] Product {productId} is not found");
|
|
44
|
+
result.onFail?.Invoke(new PurchaseError($"Product {productId} is not found"));
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
ExecuteInNextFrame(() => result.Purchase(dicProducts[productId]));
|
|
35
48
|
return result;
|
|
36
49
|
}
|
|
37
50
|
|
|
@@ -46,7 +59,7 @@ namespace Amanotes.Core
|
|
|
46
59
|
{
|
|
47
60
|
if (!dicProducts.ContainsKey(productId))
|
|
48
61
|
{
|
|
49
|
-
LogWarning($"[IAP] Not found product with id <{productId}>. Make sure you have called
|
|
62
|
+
LogWarning($"[IAP] Not found product with id <{productId}>. Make sure you have called GetProducts() first.");
|
|
50
63
|
return null;
|
|
51
64
|
}
|
|
52
65
|
|
|
@@ -73,6 +86,13 @@ namespace Amanotes.Core
|
|
|
73
86
|
{
|
|
74
87
|
return Adapter?.GetPurchaseHistory();
|
|
75
88
|
}
|
|
89
|
+
|
|
90
|
+
public static DateTime? GetLastPurchaseDate(string productId)
|
|
91
|
+
{
|
|
92
|
+
var product = GetProduct(productId);
|
|
93
|
+
if (product == null) return null;
|
|
94
|
+
return Adapter?.GetLastPurchaseDate(product.productAndPlanId);
|
|
95
|
+
}
|
|
76
96
|
}
|
|
77
97
|
|
|
78
98
|
public partial class IAP //Internal
|
|
@@ -134,12 +154,68 @@ namespace Amanotes.Core
|
|
|
134
154
|
internal class IAPData : IJsonFile
|
|
135
155
|
{
|
|
136
156
|
public string activeSubscriptionId;
|
|
157
|
+
public string subscriptionPeriodType;
|
|
158
|
+
public string subscriptionLastPurchaseDate;
|
|
159
|
+
public string subscriptionExpiredDate;
|
|
160
|
+
public string unsubscribedDate;
|
|
137
161
|
public List<string> purchasedProducts;
|
|
162
|
+
|
|
163
|
+
private DateTime? _subscriptionLastPurchaseDate;
|
|
164
|
+
public DateTime? SubscriptionLastPurchaseDate
|
|
165
|
+
{
|
|
166
|
+
get
|
|
167
|
+
{
|
|
168
|
+
if (_subscriptionLastPurchaseDate != null) return _subscriptionLastPurchaseDate;
|
|
169
|
+
if (DateTime.TryParseExact(subscriptionLastPurchaseDate, DATE_FORMAT,
|
|
170
|
+
CultureInfo.InvariantCulture, DateTimeStyles.None, out var pd))
|
|
171
|
+
{
|
|
172
|
+
_subscriptionLastPurchaseDate = pd;
|
|
173
|
+
}
|
|
174
|
+
return _subscriptionLastPurchaseDate;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private DateTime? _subscriptionExpiredDate;
|
|
179
|
+
public DateTime? SubscriptionExpiredDate
|
|
180
|
+
{
|
|
181
|
+
get
|
|
182
|
+
{
|
|
183
|
+
if (_subscriptionExpiredDate != null) return _subscriptionExpiredDate;
|
|
184
|
+
if (DateTime.TryParseExact(subscriptionExpiredDate, DATE_FORMAT,
|
|
185
|
+
CultureInfo.InvariantCulture, DateTimeStyles.None, out var pd))
|
|
186
|
+
{
|
|
187
|
+
_subscriptionExpiredDate = pd;
|
|
188
|
+
}
|
|
189
|
+
return _subscriptionExpiredDate;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private DateTime? _unsubscribedDate;
|
|
194
|
+
public DateTime? UnsubscribedDate
|
|
195
|
+
{
|
|
196
|
+
get
|
|
197
|
+
{
|
|
198
|
+
if (_unsubscribedDate != null) return _unsubscribedDate;
|
|
199
|
+
if (DateTime.TryParseExact(unsubscribedDate, DATE_FORMAT,
|
|
200
|
+
CultureInfo.InvariantCulture, DateTimeStyles.None, out var pd))
|
|
201
|
+
{
|
|
202
|
+
_unsubscribedDate = pd;
|
|
203
|
+
}
|
|
204
|
+
return _unsubscribedDate;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
138
207
|
|
|
139
208
|
public void Sync()
|
|
140
209
|
{
|
|
141
210
|
activeSubscriptionId = Adapter?.GetActiveSubscriptionId();
|
|
211
|
+
subscriptionPeriodType = Adapter?.GetSubscriptionPeriodType();
|
|
142
212
|
purchasedProducts = Adapter?.GetPurchasedProducts();
|
|
213
|
+
_subscriptionLastPurchaseDate = Adapter?.GetSubscriptionLastPurchaseDate();
|
|
214
|
+
subscriptionLastPurchaseDate = _subscriptionLastPurchaseDate?.ToString(DATE_FORMAT);
|
|
215
|
+
_subscriptionExpiredDate = Adapter?.GetSubscriptionExpiredDate();
|
|
216
|
+
subscriptionExpiredDate = _subscriptionExpiredDate?.ToString(DATE_FORMAT);
|
|
217
|
+
_unsubscribedDate = Adapter?.GetUnsubscribedDate();
|
|
218
|
+
unsubscribedDate = _unsubscribedDate?.ToString(DATE_FORMAT);
|
|
143
219
|
this.SaveJsonToFile();
|
|
144
220
|
}
|
|
145
221
|
}
|
|
@@ -158,6 +234,7 @@ namespace Amanotes.Core
|
|
|
158
234
|
{
|
|
159
235
|
public string id;
|
|
160
236
|
public ProductType type;
|
|
237
|
+
[HideInInspector] public string productAndPlanId;
|
|
161
238
|
[HideInInspector] public string title;
|
|
162
239
|
[HideInInspector] public string description;
|
|
163
240
|
[HideInInspector] public float price;
|
|
@@ -186,8 +263,9 @@ namespace Amanotes.Core
|
|
|
186
263
|
{
|
|
187
264
|
}
|
|
188
265
|
|
|
189
|
-
public PurchaseError(string errorMessage)
|
|
266
|
+
public PurchaseError(string errorMessage, string productId = null)
|
|
190
267
|
{
|
|
268
|
+
this.productId = productId;
|
|
191
269
|
error = errorMessage;
|
|
192
270
|
}
|
|
193
271
|
}
|
|
@@ -241,9 +319,11 @@ namespace Amanotes.Core
|
|
|
241
319
|
{
|
|
242
320
|
if (sc == null) return null;
|
|
243
321
|
ClearOldProductConfig();
|
|
322
|
+
var ls = AdapterConfig?.products;
|
|
323
|
+
if (ls == null) return null;
|
|
244
324
|
foreach (var pId in subs)
|
|
245
325
|
{
|
|
246
|
-
|
|
326
|
+
ls.Add(new ProductInfo { id = pId, type = ProductType.Subscription });
|
|
247
327
|
}
|
|
248
328
|
return sc;
|
|
249
329
|
}
|
|
@@ -252,9 +332,11 @@ namespace Amanotes.Core
|
|
|
252
332
|
{
|
|
253
333
|
if (sc == null) return null;
|
|
254
334
|
ClearOldProductConfig();
|
|
335
|
+
var ls = AdapterConfig?.products;
|
|
336
|
+
if (ls == null) return null;
|
|
255
337
|
foreach (var pId in cons)
|
|
256
338
|
{
|
|
257
|
-
|
|
339
|
+
ls.Add(new ProductInfo { id = pId, type = ProductType.Consumable });
|
|
258
340
|
}
|
|
259
341
|
return sc;
|
|
260
342
|
}
|
|
@@ -263,9 +345,11 @@ namespace Amanotes.Core
|
|
|
263
345
|
{
|
|
264
346
|
if (sc == null) return null;
|
|
265
347
|
ClearOldProductConfig();
|
|
348
|
+
var ls = AdapterConfig?.products;
|
|
349
|
+
if (ls == null) return null;
|
|
266
350
|
foreach (var pId in nons)
|
|
267
351
|
{
|
|
268
|
-
|
|
352
|
+
ls.Add(new ProductInfo { id = pId, type = ProductType.NonConsumable });
|
|
269
353
|
}
|
|
270
354
|
return sc;
|
|
271
355
|
}
|
|
@@ -339,18 +423,29 @@ namespace Amanotes.Core.Internal
|
|
|
339
423
|
|
|
340
424
|
public void GetProducts()
|
|
341
425
|
{
|
|
342
|
-
|
|
426
|
+
var ls = AdapterConfig?.products;
|
|
427
|
+
if (ls == null || ls.Count == 0)
|
|
343
428
|
{
|
|
344
429
|
LogWarning("There is no IAP product");
|
|
345
430
|
return;
|
|
346
|
-
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
#if UNITY_EDITOR
|
|
434
|
+
foreach (var p in ls)
|
|
435
|
+
{
|
|
436
|
+
if (dicProducts.ContainsKey(p.id)) dicProducts[p.id] = p;
|
|
437
|
+
else dicProducts.Add(p.id, p);
|
|
438
|
+
}
|
|
439
|
+
onSuccess?.Invoke(dicProducts);
|
|
440
|
+
return;
|
|
441
|
+
#else
|
|
347
442
|
|
|
348
443
|
getProdQueue.Clear();
|
|
349
444
|
var subs = new List<string>();
|
|
350
445
|
var cons = new List<string>();
|
|
351
446
|
var nons = new List<string>();
|
|
352
447
|
|
|
353
|
-
foreach (var p in
|
|
448
|
+
foreach (var p in ls)
|
|
354
449
|
{
|
|
355
450
|
switch (p.type)
|
|
356
451
|
{
|
|
@@ -373,6 +468,7 @@ namespace Amanotes.Core.Internal
|
|
|
373
468
|
getProdQueue.Enqueue((cons, ProductType.Consumable));
|
|
374
469
|
getProdQueue.Enqueue((nons, ProductType.NonConsumable));
|
|
375
470
|
GetNextProductsInQueue();
|
|
471
|
+
#endif
|
|
376
472
|
}
|
|
377
473
|
|
|
378
474
|
void GetNextProductsInQueue()
|
|
@@ -393,9 +489,10 @@ namespace Amanotes.Core.Internal
|
|
|
393
489
|
{
|
|
394
490
|
AmaGDK.IAP.Adapter?.GetProducts(lsProduct.ToArray(), type, (pList) =>
|
|
395
491
|
{
|
|
396
|
-
foreach (var
|
|
492
|
+
foreach (var p in pList)
|
|
397
493
|
{
|
|
398
|
-
dicProducts.
|
|
494
|
+
if (dicProducts.ContainsKey(p.id)) dicProducts[p.id] = p;
|
|
495
|
+
else dicProducts.Add(p.id, p);
|
|
399
496
|
}
|
|
400
497
|
ExecuteInNextFrame(GetNextProductsInQueue);
|
|
401
498
|
}, error => onFail?.Invoke(error));
|
|
@@ -416,20 +513,14 @@ namespace Amanotes.Core.Internal
|
|
|
416
513
|
public Action<PurchaseError> onFail;
|
|
417
514
|
public string discountId;
|
|
418
515
|
|
|
419
|
-
public void Purchase(
|
|
516
|
+
public void Purchase(ProductInfo productInfo)
|
|
420
517
|
{
|
|
421
|
-
if (!dicProducts.ContainsKey(productId))
|
|
422
|
-
{
|
|
423
|
-
LogWarning($"[IAP] Product {productId} is not found");
|
|
424
|
-
return;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
518
|
#if UNITY_EDITOR
|
|
428
519
|
if (AdapterConfig.allPurchaseSuccessInEditor)
|
|
429
520
|
{
|
|
430
521
|
DoOnSuccess(new PurchaseSuccess
|
|
431
522
|
{
|
|
432
|
-
productIds = new[] {
|
|
523
|
+
productIds = new[] { productInfo.id },
|
|
433
524
|
isSandbox = true
|
|
434
525
|
});
|
|
435
526
|
return;
|
|
@@ -438,11 +529,11 @@ namespace Amanotes.Core.Internal
|
|
|
438
529
|
|
|
439
530
|
if (!string.IsNullOrWhiteSpace(discountId))
|
|
440
531
|
{
|
|
441
|
-
AmaGDK.IAP.Adapter?.PurchaseDiscount(
|
|
532
|
+
AmaGDK.IAP.Adapter?.PurchaseDiscount(productInfo, discountId, DoOnSuccess, DoOnFail);
|
|
442
533
|
return;
|
|
443
534
|
}
|
|
444
535
|
|
|
445
|
-
AmaGDK.IAP.Adapter?.Purchase(
|
|
536
|
+
AmaGDK.IAP.Adapter?.Purchase(productInfo, DoOnSuccess, DoOnFail);
|
|
446
537
|
}
|
|
447
538
|
|
|
448
539
|
public void RestorePurchase()
|
|
@@ -465,12 +556,17 @@ namespace Amanotes.Core.Internal
|
|
|
465
556
|
public interface IIAPAdapter
|
|
466
557
|
{
|
|
467
558
|
void GetProducts(string[] productIds, ProductType productType, Action<ProductInfo[]> onSuccess = null, Action<string> onFail = null);
|
|
468
|
-
void Purchase(
|
|
469
|
-
void PurchaseDiscount(
|
|
559
|
+
void Purchase(ProductInfo productInfo, Action<PurchaseSuccess> onSuccess = null, Action<PurchaseError> onFail = null);
|
|
560
|
+
void PurchaseDiscount(ProductInfo productInfo, string discountId, Action<PurchaseSuccess> onSuccess = null, Action<PurchaseError> onFail = null);
|
|
470
561
|
void RestorePurchase(Action<PurchaseSuccess> onSuccess = null, Action<PurchaseError> onFail = null);
|
|
471
562
|
List<string> GetActiveSubscriptions();
|
|
472
563
|
List<string> GetPurchasedProducts();
|
|
473
564
|
string GetActiveSubscriptionId();
|
|
565
|
+
string GetSubscriptionPeriodType();
|
|
566
|
+
DateTime? GetSubscriptionLastPurchaseDate();
|
|
567
|
+
DateTime? GetSubscriptionExpiredDate();
|
|
568
|
+
DateTime? GetUnsubscribedDate();
|
|
474
569
|
HashSet<PurchaseRecord> GetPurchaseHistory();
|
|
570
|
+
DateTime? GetLastPurchaseDate(string productAndPlanId);
|
|
475
571
|
}
|
|
476
|
-
}
|
|
572
|
+
}
|
|
@@ -68,6 +68,7 @@ namespace Amanotes.Core.Internal
|
|
|
68
68
|
|
|
69
69
|
public static void LogWarningOnce(string message, string key = null)
|
|
70
70
|
{
|
|
71
|
+
if ((Config.common.logLevel & LogLevel.Warning) == 0) return;
|
|
71
72
|
if (string.IsNullOrEmpty(key)) key = message;
|
|
72
73
|
if (logWarningDict.Contains(key)) return;
|
|
73
74
|
logWarningDict.Add(key);
|
|
@@ -75,15 +76,15 @@ namespace Amanotes.Core.Internal
|
|
|
75
76
|
}
|
|
76
77
|
public static void LogWarning(string message)
|
|
77
78
|
{
|
|
78
|
-
Debug.LogWarning($"AmaGDK {message}");
|
|
79
|
+
if ((Config.common.logLevel & LogLevel.Warning) != 0) Debug.LogWarning($"AmaGDK {message}");
|
|
79
80
|
}
|
|
80
81
|
public static void LogError(string message)
|
|
81
82
|
{
|
|
82
|
-
Debug.LogError($"AmaGDK {message}");
|
|
83
|
+
if ((Config.common.logLevel & LogLevel.Error) != 0) Debug.LogError($"AmaGDK {message}");
|
|
83
84
|
}
|
|
84
85
|
public static void Log(string message)
|
|
85
86
|
{
|
|
86
|
-
if (
|
|
87
|
+
if ((Config.common.logLevel & LogLevel.Verbose) != 0) Debug.Log($"AmaGDK {message}");
|
|
87
88
|
}
|
|
88
89
|
}
|
|
89
90
|
|
|
@@ -91,10 +92,10 @@ namespace Amanotes.Core.Internal
|
|
|
91
92
|
{
|
|
92
93
|
public static void DestroyAndReset()
|
|
93
94
|
{
|
|
94
|
-
if (
|
|
95
|
+
if (_instance != null)
|
|
95
96
|
{
|
|
96
|
-
UnityObject.Destroy(
|
|
97
|
-
|
|
97
|
+
UnityObject.Destroy(_instance);
|
|
98
|
+
_instance = null;
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
AmaGDK[] result = Resources.FindObjectsOfTypeAll<AmaGDK>();
|
|
@@ -113,8 +114,8 @@ namespace Amanotes.Core.Internal
|
|
|
113
114
|
UnityObject.Destroy(result[i].gameObject);
|
|
114
115
|
}
|
|
115
116
|
|
|
116
|
-
|
|
117
|
-
|
|
117
|
+
_status = Status.None;
|
|
118
|
+
_allowInit = false;
|
|
118
119
|
|
|
119
120
|
// TODO: Destroy adapters? - Don't do this. An adapter registers just 1 time. Clear adapters cause Analytics test fail.
|
|
120
121
|
//Adapter.listAdapters.Clear();
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
using System;
|
|
2
|
+
using System.Collections;
|
|
2
3
|
using Amanotes.Core.Internal;
|
|
3
4
|
using UnityEngine;
|
|
4
5
|
namespace Amanotes.Core
|
|
5
6
|
{
|
|
6
7
|
public partial class AmaGDK //User profile
|
|
7
8
|
{
|
|
8
|
-
public static readonly UserProfile User = new UserProfile()
|
|
9
|
+
public static readonly UserProfile User = new UserProfile();
|
|
9
10
|
|
|
10
11
|
[Serializable]
|
|
11
12
|
public partial class UserProfile : IJsonFile
|
|
@@ -18,14 +19,6 @@ namespace Amanotes.Core
|
|
|
18
19
|
GDKFileUtils.Save(FILE_NAME, JsonUtility.ToJson(this));
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
internal UserProfile Load()
|
|
22
|
-
{
|
|
23
|
-
string json = GDKFileUtils.Load(FILE_NAME);
|
|
24
|
-
if (string.IsNullOrEmpty(json)) return this;
|
|
25
|
-
JsonUtility.FromJsonOverwrite(json, this);
|
|
26
|
-
return this;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
22
|
internal void SaveIfDirty()
|
|
30
23
|
{
|
|
31
24
|
if (!_dirty) return;
|
|
@@ -57,10 +50,26 @@ namespace Amanotes.Core
|
|
|
57
50
|
private string appsFlyerId;
|
|
58
51
|
|
|
59
52
|
private const string AMA_DEVICE_ID_KEY = "ama_device_id";
|
|
53
|
+
private const float TIME_OUT = 5f;
|
|
54
|
+
private const float WAIT_TIME = 0.5f;
|
|
55
|
+
private WaitForSeconds waitForDuration = new WaitForSeconds(WAIT_TIME);
|
|
60
56
|
|
|
61
|
-
internal
|
|
57
|
+
internal IEnumerator Init()
|
|
62
58
|
{
|
|
63
|
-
|
|
59
|
+
User.LoadJsonFromFile();
|
|
60
|
+
if (IsAmaDeviceIdExist()) yield break;
|
|
61
|
+
|
|
62
|
+
GetAdvertisingId();
|
|
63
|
+
|
|
64
|
+
float time = 0;
|
|
65
|
+
while (!User.IsAmaDeviceIdExist())
|
|
66
|
+
{
|
|
67
|
+
yield return waitForDuration;
|
|
68
|
+
time += WAIT_TIME;
|
|
69
|
+
if (time <= TIME_OUT) continue;
|
|
70
|
+
Logging.LogWarning($"User init time out: {TIME_OUT}");
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
64
73
|
}
|
|
65
74
|
|
|
66
75
|
private bool IsAmaDeviceIdExist()
|
|
@@ -118,7 +127,7 @@ namespace Amanotes.Core
|
|
|
118
127
|
break;
|
|
119
128
|
|
|
120
129
|
default:
|
|
121
|
-
|
|
130
|
+
amaDeviceId = SystemInfo.deviceUniqueIdentifier;
|
|
122
131
|
break;
|
|
123
132
|
}
|
|
124
133
|
Logging.Log($"Generate AmaDeviceId completed: {amaDeviceId}");
|
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.
|
|
17
|
+
public const string VERSION = "0.2.21";
|
|
18
18
|
|
|
19
19
|
internal static AmaGDK _instance;
|
|
20
20
|
internal static Status _status = Status.None;
|
|
@@ -61,8 +61,10 @@ namespace Amanotes.Core
|
|
|
61
61
|
throw new Exception("[AmaGDK] " + CONFIG_NOT_FOUND);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
yield return User.Init();
|
|
65
|
+
|
|
64
66
|
float time = 0;
|
|
65
|
-
float timeout =
|
|
67
|
+
float timeout = 10;
|
|
66
68
|
|
|
67
69
|
var counter = 0;
|
|
68
70
|
const int INIT_TOLERANCE = 10 * 60;
|
|
@@ -106,7 +108,6 @@ namespace Amanotes.Core
|
|
|
106
108
|
}
|
|
107
109
|
|
|
108
110
|
// Init modules (Adapter managers)
|
|
109
|
-
User.InitUserProfile();
|
|
110
111
|
Analytics.Init();
|
|
111
112
|
Ads.Init();
|
|
112
113
|
IAP.Init();
|
package/package.json
CHANGED
|
Binary file
|