@@ -6,42 +6,65 @@ import androidx.annotation.NonNull
66import androidx.preference.PreferenceManager
77import com.google.gson.Gson
88import com.qonversion.android.sdk.*
9- import io.flutter.plugin.common.MethodCall
10- import io.flutter.plugin.common.MethodChannel
11- import io.flutter.plugin.common.MethodChannel.MethodCallHandler
12- import io.flutter.plugin.common.MethodChannel.Result
13- import io.flutter.plugin.common.PluginRegistry.Registrar
14-
159import com.qonversion.android.sdk.dto.QLaunchResult
1610import com.qonversion.android.sdk.dto.QPermission
1711import com.qonversion.android.sdk.dto.eligibility.QEligibility
1812import com.qonversion.android.sdk.dto.offerings.QOfferings
1913import com.qonversion.android.sdk.dto.products.QProduct
14+ import io.flutter.embedding.engine.plugins.FlutterPlugin
15+ import io.flutter.embedding.engine.plugins.activity.ActivityAware
16+ import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
17+ import io.flutter.plugin.common.BinaryMessenger
18+ import io.flutter.plugin.common.MethodCall
19+ import io.flutter.plugin.common.MethodChannel
20+ import io.flutter.plugin.common.MethodChannel.MethodCallHandler
21+ import io.flutter.plugin.common.MethodChannel.Result
22+ import io.flutter.plugin.common.PluginRegistry.Registrar
2023
2124/* * QonversionFlutterSdkPlugin */
22- class QonversionFlutterSdkPlugin internal constructor(registrar : Registrar ): MethodCallHandler {
23- private val activity: Activity = registrar.activity()
24- private val application: Application = activity.application
25+ class QonversionFlutterSdkPlugin : MethodCallHandler , FlutterPlugin , ActivityAware {
26+ private var activity: Activity ? = null
27+ private var application: Application ? = null
28+ private var channel: MethodChannel ? = null
2529 private var deferredPurchasesStreamHandler: BaseEventStreamHandler ? = null
2630
2731 companion object {
32+ const val METHOD_CHANNEL = " qonversion_flutter_sdk"
33+ const val EVENT_CHANNEL_PROMO_PURCHASES = " promo_purchases"
34+ const val EVENT_CHANNEL_DEFERRED_PURCHASES = " updated_purchases"
35+
2836 @JvmStatic
2937 fun registerWith (registrar : Registrar ) {
30- val channel = MethodChannel (registrar.messenger(), " qonversion_flutter_sdk" )
31- val instance = QonversionFlutterSdkPlugin (registrar)
32- channel.setMethodCallHandler(instance)
33-
34- // Register deferred purchases events
35- val purchasesListener = BaseListenerWrapper (registrar.messenger(), " updated_purchases" )
36- purchasesListener.register()
37- instance.deferredPurchasesStreamHandler = purchasesListener.eventStreamHandler
38-
39- // Register promo purchases events. Android SDK does not generate any promo purchases yet
40- val promoPurchasesListener = BaseListenerWrapper (registrar.messenger(), " promo_purchases" )
41- promoPurchasesListener.register()
38+ val instance = QonversionFlutterSdkPlugin ()
39+ instance.setup(registrar.messenger(), registrar.activity().application)
40+ instance.activity = registrar.activity()
4241 }
4342 }
4443
44+ override fun onAttachedToEngine (binding : FlutterPlugin .FlutterPluginBinding ) {
45+ setup(binding.binaryMessenger, binding.applicationContext as Application )
46+ }
47+
48+ override fun onAttachedToActivity (binding : ActivityPluginBinding ) {
49+ activity = binding.activity
50+ }
51+
52+ override fun onDetachedFromActivityForConfigChanges () {
53+ onDetachedFromActivity()
54+ }
55+
56+ override fun onReattachedToActivityForConfigChanges (binding : ActivityPluginBinding ) {
57+ onAttachedToActivity(binding)
58+ }
59+
60+ override fun onDetachedFromActivity () {
61+ activity = null
62+ }
63+
64+ override fun onDetachedFromEngine (binding : FlutterPlugin .FlutterPluginBinding ) {
65+ tearDown()
66+ }
67+
4568 override fun onMethodCall (@NonNull call : MethodCall , @NonNull result : Result ) {
4669
4770 // Methods without args
@@ -96,25 +119,25 @@ class QonversionFlutterSdkPlugin internal constructor(registrar: Registrar): Met
96119 }
97120
98121 private fun launch (args : Map <String , Any >, result : Result ) {
99- val apiKey = args[" key" ] as ? String ? : return result.noApiKeyError()
100- val isObserveMode = args[" isObserveMode" ] as ? Boolean ? : return result.noArgsError()
101-
102- Qonversion .launch(
103- application,
104- apiKey,
105- isObserveMode,
106- callback = object : QonversionLaunchCallback {
107- override fun onSuccess (launchResult : QLaunchResult ) {
108- result.success(launchResult.toMap())
109- }
110-
111- override fun onError (error : QonversionError ) {
112- result.qonversionError(error.description, error.additionalMessage)
122+ application?.let { application ->
123+ val apiKey = args[" key" ] as ? String ? : return result.noApiKeyError()
124+ val isObserveMode = args[" isObserveMode" ] as ? Boolean ? : return result.noArgsError()
125+ Qonversion .launch(
126+ application,
127+ apiKey,
128+ isObserveMode,
129+ callback = object : QonversionLaunchCallback {
130+ override fun onSuccess (launchResult : QLaunchResult ) {
131+ result.success(launchResult.toMap())
132+ }
133+
134+ override fun onError (error : QonversionError ) {
135+ result.qonversionError(error.description, error.additionalMessage)
136+ }
113137 }
114- }
115- )
116-
117- startListeningPendingPurchasesEvents()
138+ )
139+ startListeningPendingPurchasesEvents()
140+ } ? : result.error(QonversionErrorCode .UnknownError .name, " Couldn't launch Qonversion. There is no Application context" , null )
118141 }
119142
120143 private fun identify (userId : String? , result : Result ) {
@@ -143,31 +166,35 @@ class QonversionFlutterSdkPlugin internal constructor(registrar: Registrar): Met
143166 return
144167 }
145168
146- Qonversion .purchase(activity, productId, callback = object : QonversionPermissionsCallback {
147- override fun onSuccess (permissions : Map <String , QPermission >) {
148- result.success(PurchaseResult (permissions).toMap())
149- }
169+ activity?.let { activity ->
170+ Qonversion .purchase(activity, productId, callback = object : QonversionPermissionsCallback {
171+ override fun onSuccess (permissions : Map <String , QPermission >) {
172+ result.success(PurchaseResult (permissions).toMap())
173+ }
150174
151- override fun onError (error : QonversionError ) {
152- result.success(PurchaseResult (error = error).toMap())
153- }
154- })
175+ override fun onError (error : QonversionError ) {
176+ result.success(PurchaseResult (error = error).toMap())
177+ }
178+ })
179+ } ? : result.error(QonversionErrorCode .PurchaseInvalid .name, " Couldn't make purchase. There is no Activity context" , null )
155180 }
156181
157182 private fun updatePurchase (args : Map <String , Any >, result : Result ) {
158183 val newProductId = args[" newProductId" ] as ? String ? : return result.noNewProductIdError()
159184 val oldProductId = args[" oldProductId" ] as ? String ? : return result.noOldProductIdError()
160185 val prorationMode = args[" proration_mode" ] as ? Int
161186
162- Qonversion .updatePurchase(activity, newProductId, oldProductId, prorationMode, callback = object : QonversionPermissionsCallback {
163- override fun onSuccess (permissions : Map <String , QPermission >) {
164- result.success(permissions.mapValues { it.value.toMap() })
165- }
187+ activity?.let { activity ->
188+ Qonversion .updatePurchase(activity, newProductId, oldProductId, prorationMode, callback = object : QonversionPermissionsCallback {
189+ override fun onSuccess (permissions : Map <String , QPermission >) {
190+ result.success(permissions.mapValues { it.value.toMap() })
191+ }
166192
167- override fun onError (error : QonversionError ) {
168- result.qonversionError(error.description, error.additionalMessage)
169- }
170- })
193+ override fun onError (error : QonversionError ) {
194+ result.qonversionError(error.description, error.additionalMessage)
195+ }
196+ })
197+ } ? : result.error(QonversionErrorCode .PurchaseInvalid .name, " Couldn't update purchase. There is no Activity context" , null )
171198 }
172199
173200 private fun checkPermissions (result : Result ) {
@@ -304,4 +331,26 @@ class QonversionFlutterSdkPlugin internal constructor(registrar: Registrar): Met
304331
305332 result.success(null )
306333 }
334+
335+ private fun setup (messenger : BinaryMessenger , application : Application ) {
336+ this .application = application
337+ channel = MethodChannel (messenger, METHOD_CHANNEL )
338+ channel?.setMethodCallHandler(this )
339+
340+ // Register deferred purchases events
341+ val purchasesListener = BaseListenerWrapper (messenger, EVENT_CHANNEL_DEFERRED_PURCHASES )
342+ purchasesListener.register()
343+ this .deferredPurchasesStreamHandler = purchasesListener.eventStreamHandler
344+
345+ // Register promo purchases events. Android SDK does not generate any promo purchases yet
346+ val promoPurchasesListener = BaseListenerWrapper (messenger, EVENT_CHANNEL_PROMO_PURCHASES )
347+ promoPurchasesListener.register()
348+ }
349+
350+ private fun tearDown () {
351+ channel?.setMethodCallHandler(null )
352+ channel = null
353+ this .deferredPurchasesStreamHandler = null
354+ this .application = null
355+ }
307356}
0 commit comments