Skip to content

Commit e7ccf3e

Browse files
committed
Merge branch 'release/2.0.0'
2 parents 8dae2ff + 8e17804 commit e7ccf3e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+2723
-642
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## 2.0.0
2+
* We have rethought our approach to working with subscriptions and prepared our largest update that includes [Product Center](https://documentation.qonversion.io/docs/product-center) – our major feature for working with any type in-app purchases.
3+
14
## 1.1.2
25
* Fix Android `manualTrackPurchase` args parsing
36
* Update Example app

README.md

+34-68
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,55 @@
11
<p align="center">
2-
<a href="https://qonversion.io" target="_blank"><img width="460" height="150" src="https://qonversion.io/img/q_brand.svg"></a>
2+
<a href="https://qonversion.io" target="_blank"><img width="360" height="150" src="https://qonversion.io/img/q_brand.svg"></a>
33
</p>
44

55
<p align="center">
6-
<a href="https://qonversion.io"><img width="660" src="https://qonversion.io/img/illustrations/charts.svg"></a></p>
7-
8-
Get access to the powerful yet simple subscription analytics:
9-
* Conversion from install to paying user, MRR, LTV, churn and other metrics.
10-
* Feed the advertising and analytics tools you are already using with the data on high-value users to improve your ads targeting and marketing ROAS.
11-
12-
[![Pub](https://img.shields.io/pub/v/qonversion_flutter.svg)](https://pub.dev/packages/qonversion_flutter)
13-
14-
## Installation
15-
To use Qonversion in your Flutter app, add `qonversion` as a [dependency in your pubspec.yaml file](https://flutter.io/platform-plugins/):
16-
17-
```
18-
dependencies:
19-
qonversion_flutter: ^1.1.2
20-
```
21-
22-
Run `flutter pub get` to install dependency.
23-
24-
## Usage
25-
26-
### Setup
27-
28-
You need to configure Qonversion once at a starting point of your app.
6+
<a href="https://qonversion.io"><img width="660" src="https://qonversion.io/img/images/product-center.svg">
7+
</a>
8+
</p>
299

30-
For example, launch Qonversion in `initState` of your top level widget:
3110

32-
```
33-
...
34-
import 'package:qonversion_flutter/qonversion.dart';
11+
<p>
12+
Qonversion provides full in-app purchases infrastructure, so you do not need to build your own server for receipt validation.
13+
</p>
3514

36-
...
3715

38-
String _qonversionUserId;
16+
<p>
17+
Implement in-app subscriptions, validate user receipts, check subscription status, and provide access to your app features and content using our StoreKit wrapper and Google Play Billing wrapper.
18+
</p>
3919

40-
@override
41-
void initState() {
42-
super.initState();
43-
44-
_launchQonversion();
45-
}
20+
Read more in [documentation](https://docs.qonversion.io).
4621

47-
Future<String> _launchQonversion() async {
48-
_qonversionUserId = await Qonversion.launch('YOUR_API_KEY');
49-
}
22+
[![Pub](https://img.shields.io/pub/v/qonversion_flutter.svg)](https://pub.dev/packages/qonversion_flutter)
23+
[![MIT License](http://img.shields.io/cocoapods/l/Qonversion.svg?style=flat)](http://qonversion.io)
5024

51-
...
52-
```
5325

54-
You can also specify your client side `userId` (instead of Qonversion user-id) that will be used for matching data in the third party data:
26+
## Product Center
5527

56-
```
57-
final userId = 'CLIENT_SIDE_USER_ID';
58-
Qonversion.launch(
59-
'YOUR_API_KEY',
60-
userId: userId,
61-
);
62-
```
28+
<p align="center">
29+
<a href="https://qonversion.io"><img width="400" src="https://qonversion.io/img/images/product-center-scheme.svg">
30+
</a>
31+
</p>
6332

64-
### Purchase tracking
33+
1. Application calls the purchase method to initialize Qonversion SDK.
34+
2. Qonversion SDK communicates with StoreKit or Google Billing Client to make a purchase.
35+
3. If a purchase is successful, the SDK sends a request to Qonversion API for server-to-server validation of purchase. Qonversion server unlocks permissions associated with the product.
36+
4. SDK returns control to the application with a processing state
6537

66-
#### Android
67-
On Android you must call `Qonversion.manualTrackPurchase(skuDetails, purchase)` method on each purchase success in order to track purchases.
68-
If you're not using official [in_app_purchase plugin](https://pub.dev/packages/in_app_purchase), you can use fallback method `trackPurchase` and pass it correct SkuDetails and ProductDetails Maps.
38+
## Analytics
6939

70-
#### iOS
71-
On iOS Qonversion will track purchases automatically.
40+
Monitor your in-app revenue metrics. Understand your customers and make better decisions with precise subscription revenue data.
7241

73-
### Attribution
74-
You need to have AppsFlyer SDK integrated in your app before starting with this integration. If you do not have Appsflyer integration yet, please use [this docs](https://pub.dev/packages/appsflyer_sdk#-readme-tab-).
42+
<p align="center">
43+
<a href="https://qonversion.io"><img width="90%" src="https://qonversion.io/img/screenshots/desktop/mobile_subscription_analytics.jpg">
44+
</a>
45+
</p>
7546

76-
On iOS you can also use Branch integration.
47+
## Integrations
7748

78-
Use `addAttributionData(data, provider, userId)` method to pass attribution data dictionary:
79-
```
80-
Qonversion.addAttributionData(
81-
data,
82-
QAttributionProvider.appsFlyer,
83-
'USER_ID',
84-
)
85-
```
49+
Share your iOS and Android in-app subscription data with your favorite platforms.
8650

87-
## License
8851

89-
Qonversion SDK is available under the MIT license.
52+
<p align="center">
53+
<a href="https://qonversion.io"><img width="500" src="https://qonversion.io/img/illustrations/pic-integration.svg">
54+
</a>
55+
</p>

android/build.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
group 'com.qonversion.flutter.sdk.qonversion_flutter_sdk'
2-
version '1.1.2'
2+
version '2.0.0'
33

44
buildscript {
55
ext.kotlin_version = '1.3.50'
@@ -41,5 +41,5 @@ android {
4141

4242
dependencies {
4343
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
44-
implementation "com.qonversion.android.sdk:sdk:1.0.4"
44+
implementation "com.qonversion.android.sdk:sdk:2.0.2"
4545
}

android/gradle.properties

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
org.gradle.jvmargs=-Xmx1536M
2-
android.enableR8=true
32
android.useAndroidX=true
43
android.enableJetifier=true

android/src/main/kotlin/com/qonversion/flutter/sdk/qonversion_flutter_sdk/FlutterResult+CustomErrors.kt

+29-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package com.qonversion.flutter.sdk.qonversion_flutter_sdk
22

33
import io.flutter.plugin.common.MethodChannel
44

5+
private const val passValidValue = "Please make sure you pass a valid value"
6+
57
fun MethodChannel.Result.noArgsError() {
68
return this.error("0", "Could not find call arguments", "Make sure you pass Map as call arguments")
79
}
@@ -19,13 +21,37 @@ fun MethodChannel.Result.noAutoTrackPurchasesError() {
1921
}
2022

2123
fun MethodChannel.Result.noDataError() {
22-
return this.error("4", "Could not find data", "Please make sure you pass a valid value")
24+
return this.error("4", "Could not find data", passValidValue)
2325
}
2426

2527
fun MethodChannel.Result.noProviderError() {
26-
return this.error("5", "Could not find provider", "Please make sure you pass a valid value")
28+
return this.error("5", "Could not find provider", passValidValue)
29+
}
30+
31+
fun MethodChannel.Result.noProductIdError() {
32+
return this.error("8", "Could not find productId value", "Please provide valid productId")
2733
}
2834

2935
fun MethodChannel.Result.qonversionError(message: String, cause: String) {
3036
return this.error("9", message, cause)
31-
}
37+
}
38+
39+
fun MethodChannel.Result.noNewProductIdError() {
40+
return this.error("10", "Could not find new product id", passValidValue)
41+
}
42+
43+
fun MethodChannel.Result.noOldProductIdError() {
44+
return this.error("11", "Could not find new product id", passValidValue)
45+
}
46+
47+
fun MethodChannel.Result.parsingError(message: String?) {
48+
return this.error("12", "Arguments Parsing Error", message)
49+
}
50+
51+
fun MethodChannel.Result.noProperty() {
52+
return this.error("13", "Could not find property", passValidValue)
53+
}
54+
55+
fun MethodChannel.Result.noPropertyValue() {
56+
return this.error("14", "Could not find property value", passValidValue)
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package com.qonversion.flutter.sdk.qonversion_flutter_sdk
2+
3+
import com.android.billingclient.api.SkuDetails
4+
import com.qonversion.android.sdk.QonversionError
5+
import com.qonversion.android.sdk.dto.QLaunchResult
6+
import com.qonversion.android.sdk.dto.QPermission
7+
import com.qonversion.android.sdk.dto.QProduct
8+
9+
data class PurchaseResult(val permissions: Map<String, QPermission>? = null, val error: QonversionError? = null) {
10+
fun toMap(): Map<String, Any?> {
11+
return mapOf(
12+
"permissions" to permissions?.mapValues { it.value.toMap() },
13+
"error" to (error?.description ?: error?.additionalMessage)
14+
)
15+
}
16+
}
17+
18+
fun QLaunchResult.toMap(): Map<String, Any> {
19+
return mapOf(
20+
"uid" to uid,
21+
"timestamp" to date.time.toDouble(),
22+
"products" to products.mapValues { it.value.toMap() },
23+
"permissions" to permissions.mapValues { it.value.toMap() },
24+
"user_products" to userProducts.mapValues { it.value.toMap() }
25+
)
26+
}
27+
28+
fun QProduct.toMap(): Map<String, Any?> {
29+
return mapOf(
30+
"id" to qonversionID,
31+
"store_id" to storeID,
32+
"type" to type.type,
33+
"duration" to duration?.type,
34+
"sku_details" to skuDetail?.toMap(),
35+
"pretty_price" to prettyPrice
36+
)
37+
}
38+
39+
fun QPermission.toMap(): Map<String, Any?> {
40+
return mapOf(
41+
"id" to permissionID,
42+
"associated_product" to productID,
43+
"renew_state" to renewState.type,
44+
"started_timestamp" to startedDate.time.toDouble(),
45+
"expiration_timestamp" to expirationDate?.time?.toDouble(),
46+
"active" to isActive()
47+
)
48+
}
49+
50+
fun SkuDetails.toMap(): Map<String, Any?> {
51+
return mapOf(
52+
"title" to title,
53+
"description" to description,
54+
"freeTrialPeriod" to freeTrialPeriod,
55+
"introductoryPrice" to introductoryPrice,
56+
"introductoryPriceAmountMicros" to introductoryPriceAmountMicros,
57+
"introductoryPriceCycles" to introductoryPriceCycles,
58+
"introductoryPricePeriod" to introductoryPricePeriod,
59+
"price" to price,
60+
"priceAmountMicros" to priceAmountMicros,
61+
"priceCurrencyCode" to priceCurrencyCode,
62+
"sku" to sku,
63+
"type" to type,
64+
"subscriptionPeriod" to subscriptionPeriod,
65+
"originalPrice" to originalPrice,
66+
"originalPriceAmountMicros" to originalPriceAmountMicros
67+
)
68+
}

0 commit comments

Comments
 (0)