Skip to content

Commit dd5e52b

Browse files
committed
Added fallbacks logic
1 parent 12a4236 commit dd5e52b

File tree

13 files changed

+281
-6
lines changed

13 files changed

+281
-6
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## 9.0.0
2+
New major release of Qonversion Flutter SDK with the new Google Play Billing Library 7 support!
3+
* installment plans supported for subscriptions
4+
* fallback files support added for improved reliability
5+
* several error code values updated
6+
7+
For the migration steps and the complete list of changes, see the following [guide](https://documentation.qonversion.io/docs/android-8-migration-guide).
8+
19
## 8.5.0
210
* Internal logic update
311

android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,6 @@ android {
5151

5252
dependencies {
5353
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
54-
implementation "io.qonversion.sandwich:sandwich:4.5.0"
54+
implementation "io.qonversion.sandwich:sandwich:5.0.2"
5555
implementation 'com.google.code.gson:gson:2.9.0'
5656
}
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
{
2+
"products": [
3+
{
4+
"id": "android_installment",
5+
"duration": 1,
6+
"store_id": "gb7_test_subscription",
7+
"type": 1,
8+
"base_plan_id": "monthly-installment"
9+
},
10+
{
11+
"id": "android_prepaid_2",
12+
"duration": null,
13+
"store_id": "daniel_prepaid",
14+
"type": 1,
15+
"base_plan_id": "monthly"
16+
},
17+
{
18+
"id": "dan_test",
19+
"duration": null,
20+
"store_id": "dan_test_annual",
21+
"type": null
22+
},
23+
{
24+
"id": "gb6_annual",
25+
"duration": 4,
26+
"store_id": "gb6_test",
27+
"type": 0,
28+
"base_plan_id": "annual"
29+
},
30+
{
31+
"id": "gb6_monthly",
32+
"duration": 1,
33+
"store_id": "gb6_test",
34+
"type": 0,
35+
"base_plan_id": "monthly"
36+
},
37+
{
38+
"id": "gb6_weekly",
39+
"duration": 0,
40+
"store_id": "gb6_test",
41+
"type": 1,
42+
"base_plan_id": "weekly"
43+
},
44+
{
45+
"id": "android_prepaid",
46+
"duration": 2,
47+
"store_id": "gp5_test_subscription_4",
48+
"type": 1,
49+
"base_plan_id": "prepaid-3m"
50+
},
51+
{
52+
"id": "weekly",
53+
"duration": 0,
54+
"store_id": "gp5_test_subscription_4",
55+
"type": 1,
56+
"base_plan_id": "monthly-2"
57+
},
58+
{
59+
"id": "consumable",
60+
"duration": null,
61+
"store_id": "qonversion_inapp_sample",
62+
"type": 2
63+
},
64+
{
65+
"id": "subs_plus_trial",
66+
"duration": 1,
67+
"store_id": "gp5_test_subscription_4",
68+
"type": 0
69+
},
70+
{
71+
"id": "annual",
72+
"duration": 4,
73+
"store_id": "article_test_trial",
74+
"type": 0
75+
},
76+
{
77+
"id": "in_app",
78+
"duration": null,
79+
"store_id": "qonversion_sample_purchase",
80+
"type": 2
81+
}
82+
],
83+
"offerings": [
84+
{
85+
"id": "main",
86+
"tag": 1,
87+
"products": [
88+
{
89+
"id": "weekly",
90+
"duration": 0,
91+
"store_id": "gp5_test_subscription_4",
92+
"type": 1,
93+
"base_plan_id": "monthly-2"
94+
},
95+
{
96+
"id": "annual",
97+
"duration": 4,
98+
"store_id": "article_test_trial",
99+
"type": 0
100+
},
101+
{
102+
"id": "consumable",
103+
"duration": null,
104+
"store_id": "qonversion_inapp_sample",
105+
"type": 2
106+
}
107+
]
108+
},
109+
{
110+
"id": "discounted_offer",
111+
"tag": 0,
112+
"products": []
113+
}
114+
],
115+
"products_permissions": {
116+
"android_installment": [
117+
"standart"
118+
],
119+
"android_prepaid_2": [
120+
"premium"
121+
],
122+
"dan_test": [
123+
"test_permission"
124+
],
125+
"gb6_annual": [
126+
"premium"
127+
],
128+
"gb6_monthly": [
129+
"plus"
130+
],
131+
"gb6_weekly": [
132+
"standart"
133+
],
134+
"android_prepaid": [
135+
"premium"
136+
],
137+
"weekly": [
138+
"plus"
139+
],
140+
"consumable": [],
141+
"subs_plus_trial": [
142+
"standart"
143+
],
144+
"annual": [
145+
"standart",
146+
"sample"
147+
],
148+
"in_app": [
149+
"Premium Movies"
150+
]
151+
},
152+
"remote_config_list": [
153+
{
154+
"experiment": null,
155+
"payload": {
156+
"CTA": "Start Trial",
157+
"CTA_color": "#307BF6",
158+
"main_image": "[IMAGE_URL]",
159+
"product_id": "prod_7d_trial_5.99",
160+
"show_close_button": true
161+
},
162+
"source": {
163+
"assignment_type": "auto",
164+
"context_key": "main_paywall",
165+
"name": "default paywall",
166+
"type": "remote_configuration",
167+
"uid": "0dcb1bd9-9bc3-4668-84aa-4540d1042c5d"
168+
}
169+
},
170+
{
171+
"experiment": null,
172+
"payload": {
173+
"CTA": "Start you trial",
174+
"CTA_color": "red",
175+
"main_image": "111",
176+
"product_id": "123123123123123",
177+
"show_close_button": true
178+
},
179+
"source": {
180+
"assignment_type": "auto",
181+
"context_key": "",
182+
"name": "Default settings",
183+
"type": "remote_configuration",
184+
"uid": "12feb1dd-8096-47bc-a5a1-443fd2828ecc"
185+
}
186+
},
187+
{
188+
"experiment": null,
189+
"payload": {
190+
"test_key": "test_value"
191+
},
192+
"source": {
193+
"assignment_type": "auto",
194+
"context_key": "test_context_key",
195+
"name": "Test with context key1",
196+
"type": "remote_configuration",
197+
"uid": "c5077ec4-acf4-41ea-8b43-05114be5d7ce"
198+
}
199+
},
200+
{
201+
"experiment": null,
202+
"payload": {
203+
"test_key_2": "test_value_2"
204+
},
205+
"source": {
206+
"assignment_type": "auto",
207+
"context_key": "test_context_key_2",
208+
"name": "Test with context key2 - copy",
209+
"type": "remote_configuration",
210+
"uid": "1c000f2a-2f4b-4736-b5dd-75b13bf73deb"
211+
}
212+
},
213+
{
214+
"experiment": null,
215+
"payload": {
216+
"bool": true,
217+
"json": {
218+
"key": "value"
219+
}
220+
},
221+
"source": {
222+
"assignment_type": "auto",
223+
"context_key": "swift_key ",
224+
"name": "Swift",
225+
"type": "remote_configuration",
226+
"uid": "9f85d738-56d8-4f6c-b54a-c08658be2cb4"
227+
}
228+
}
229+
]
230+
}

example/ios/Runner.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,15 +324,15 @@
324324
};
325325
9740EEB61CF901F6004384FC /* Run Script */ = {
326326
isa = PBXShellScriptBuildPhase;
327-
buildActionMask = 12;
327+
buildActionMask = 8;
328328
files = (
329329
);
330330
inputPaths = (
331331
);
332332
name = "Run Script";
333333
outputPaths = (
334334
);
335-
runOnlyForDeploymentPostprocessing = 0;
335+
runOnlyForDeploymentPostprocessing = 1;
336336
shellPath = /bin/sh;
337337
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
338338
};

ios/Classes/SwiftQonversionPlugin.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ public class SwiftQonversionPlugin: NSObject, FlutterPlugin {
8383

8484
case "collectAppleSearchAdsAttribution":
8585
return collectAppleSearchAdsAttribution(result)
86+
87+
case "isFallbackFileAccessible":
88+
return isFallbackFileAccessible(result)
8689

8790
case "automationsSubscribe":
8891
automationsPlugin?.subscribe()
@@ -356,6 +359,10 @@ public class SwiftQonversionPlugin: NSObject, FlutterPlugin {
356359
qonversionSandwich?.collectAppleSearchAdsAttribution()
357360
result(nil)
358361
}
362+
363+
private func isFallbackFileAccessible(_ result: @escaping FlutterResult) {
364+
qonversionSandwich?.isFallbackFileAccessible(completion: getJsonCompletion(result))
365+
}
359366

360367
private func presentCodeRedemptionSheet(_ result: @escaping FlutterResult) {
361368
if #available(iOS 14.0, *) {

ios/qonversion_flutter.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Pod::Spec.new do |s|
1616
s.source_files = 'Classes/**/*'
1717
s.dependency 'Flutter'
1818
s.platform = :ios, '9.0'
19-
s.dependency "QonversionSandwich", "4.5.0"
19+
s.dependency "QonversionSandwich", "5.0.2"
2020

2121
# Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported.
2222
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }

lib/src/internal/constants.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class Constants {
5252
static const mAddAttributionData = 'addAttributionData';
5353
static const mSetDebugMode = 'setDebugMode';
5454
static const mCollectAdvertisingId = 'collectAdvertisingId';
55+
static const mIsFallbackFileAccessible = 'isFallbackFileAccessible';
5556
static const mOfferings = 'offerings';
5657
static const mCheckTrialIntroEligibility = 'checkTrialIntroEligibility';
5758
static const mStoreSdkInfo = 'storeSdkInfo';

lib/src/internal/mapper.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,14 @@ class QMapper {
124124
return QUserPropertyKey.custom;
125125
}
126126

127+
static bool? mapIsFallbackFileAccessible(String? jsonString) {
128+
if (jsonString == null) return null;
129+
130+
final result = Map<String, dynamic>.from(jsonDecode(jsonString));
131+
132+
return result["success"];
133+
}
134+
127135
static QUserProperties? userPropertiesFromJson(String? jsonString) {
128136
if (jsonString == null) return null;
129137

lib/src/internal/qonversion_internal.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,16 @@ class QonversionInternal implements Qonversion {
255255
return;
256256
}
257257

258+
Future<bool> isFallbackFileAccessible() async {
259+
final rawResult = await _channel.invokeMethod(Constants.mIsFallbackFileAccessible);
260+
final result = QMapper.mapIsFallbackFileAccessible(rawResult);
261+
if (result == null) {
262+
return false;
263+
}
264+
265+
return result;
266+
}
267+
258268
@override
259269
Future<void> attribution(Map<dynamic, dynamic> data, QAttributionProvider provider) {
260270
final args = {

lib/src/qonversion.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,10 @@ abstract class Qonversion {
196196
/// Use this function to detach the user from the remote configuration.
197197
Future<void> detachUserFromRemoteConfiguration(String remoteConfigurationId);
198198

199+
/// Call this function to check if the fallback file is accessible.
200+
/// Returns flag that indicates whether Qonversion was able to read data from the fallback file or not.
201+
Future<bool> isFallbackFileAccessible();
202+
199203
/// iOS only. Returns `null` if called on Android.
200204
///
201205
/// Starts a promo purchase process with App Store [productId].

0 commit comments

Comments
 (0)