@@ -2,8 +2,9 @@ package com.iproov.sdk
22
33import android.content.Context
44import android.graphics.Bitmap
5- import com.iproov.sdk.bridge.OptionsBridge
6- import com.iproov.sdk.core.exception.*
5+ import com.iproov.sdk.api.OptionsBridge
6+ import com.iproov.sdk.api.IProov
7+ import com.iproov.sdk.api.exception.*
78import io.flutter.FlutterInjector
89import io.flutter.embedding.engine.plugins.FlutterPlugin
910import io.flutter.plugin.common.EventChannel
@@ -15,6 +16,8 @@ import kotlinx.coroutines.CoroutineScope
1516import kotlinx.coroutines.Dispatchers
1617import kotlinx.coroutines.SupervisorJob
1718import kotlinx.coroutines.flow.collect
19+ import kotlinx.coroutines.flow.onSubscription
20+ import kotlinx.coroutines.Job
1821import kotlinx.coroutines.launch
1922import kotlinx.coroutines.cancel
2023import kotlinx.coroutines.withContext
@@ -35,30 +38,29 @@ class IProovSDKPlugin : FlutterPlugin {
3538 private var eventSink: EventChannel .EventSink ? = null
3639 private var uiEventSink: EventChannel .EventSink ? = null
3740 private var flutterPluginBinding: FlutterPlugin .FlutterPluginBinding ? = null
38- private val launcher = IProovFlowLauncher ()
39- private var pendingException: IProovException ? = null
4041
41- init {
42- sessionStateListener()
43- sessionUIStateListener()
44- }
42+ private var sessionStateJob: Job ? = null
43+ private var sessionUIStateJob: Job ? = null
44+ private var pendingException: IProovException ? = null
4545
46- private fun sessionStateListener () {
47- coroutineScope.launch {
48- launcher.sessionsStates.collect { sessionState ->
49- sessionState?.let {
50- sessionState.state.let { state ->
46+ private fun observeSessionState (session : IProov .Session , whenReady : (() -> Unit )? = null) {
47+ sessionStateJob?.cancel()
48+ sessionStateJob = coroutineScope.launch(Dispatchers .IO ) {
49+ kotlin.runCatching {
50+ session.state
51+ .onSubscription { whenReady?.invoke() }
52+ .collect { state ->
5153 withContext(Dispatchers .Main ) {
5254 when (state) {
53- is IProov .IProovState .Connecting -> {
55+ is IProov .State .Connecting -> {
5456 eventSink?.success(hashMapOf(" event" to " connecting" ))
5557 }
5658
57- is IProov .IProovState .Connected -> {
59+ is IProov .State .Connected -> {
5860 eventSink?.success(hashMapOf(" event" to " connected" ))
5961 }
6062
61- is IProov .IProovState .Processing -> {
63+ is IProov .State .Processing -> {
6264 eventSink?.success(
6365 hashMapOf(
6466 " event" to " processing" ,
@@ -68,7 +70,7 @@ class IProovSDKPlugin : FlutterPlugin {
6870 )
6971 }
7072
71- is IProov .IProovState .Success -> {
73+ is IProov .State .Success -> {
7274 val frameArray = state.successResult.frame?.let { bmp ->
7375 val stream = ByteArrayOutputStream ()
7476 bmp.compress(Bitmap .CompressFormat .PNG , 100 , stream)
@@ -86,7 +88,7 @@ class IProovSDKPlugin : FlutterPlugin {
8688 eventSink?.endOfStream()
8789 }
8890
89- is IProov .IProovState .Failure -> {
91+ is IProov .State .Failure -> {
9092 val context = flutterPluginBinding!! .applicationContext
9193
9294 val frameArray = state.failureResult.frame?.let { bmp ->
@@ -108,12 +110,12 @@ class IProovSDKPlugin : FlutterPlugin {
108110 eventSink?.endOfStream()
109111 }
110112
111- is IProov .IProovState .Error -> {
113+ is IProov .State .Error -> {
112114 eventSink?.success(state.exception.serialize())
113115 eventSink?.endOfStream()
114116 }
115117
116- is IProov .IProovState .Canceled -> {
118+ is IProov .State .Canceled -> {
117119 eventSink?.success(
118120 hashMapOf(
119121 " event" to " canceled" ,
@@ -125,32 +127,33 @@ class IProovSDKPlugin : FlutterPlugin {
125127 }
126128 }
127129 }
128- }
129130 }
130131 }
131132 }
132133
133- private fun sessionUIStateListener () {
134- coroutineScope.launch {
135- launcher.sessionsUIStates.collect { sessionUIState ->
136- sessionUIState?.let {
137- withContext(Dispatchers .Main ) {
138- when (sessionUIState.state) {
139- IProov .IProovUIState .NotStarted -> {
140- uiEventSink?.success(hashMapOf(" uiEvent" to " not_started" ))
141- }
134+ private fun observeSessionUIState (session : IProov .Session ) {
135+ sessionUIStateJob?.cancel()
136+ sessionUIStateJob = coroutineScope.launch(Dispatchers .IO ) {
137+ kotlin.runCatching {
138+ session.uiState
139+ .collect { sessionUIState ->
140+ withContext(Dispatchers .Main ) {
141+ when (sessionUIState) {
142+ IProov .UIState .NotStarted -> {
143+ uiEventSink?.success(hashMapOf(" uiEvent" to " not_started" ))
144+ }
142145
143- IProov .IProovUIState .Started -> {
144- uiEventSink?.success(hashMapOf(" uiEvent" to " started" ))
145- }
146+ IProov .UIState .Started -> {
147+ uiEventSink?.success(hashMapOf(" uiEvent" to " started" ))
148+ }
146149
147- IProov .IProovUIState .Ended -> {
148- uiEventSink?.success(hashMapOf(" uiEvent" to " ended" ))
149- uiEventSink?.endOfStream()
150+ IProov .UIState .Ended -> {
151+ uiEventSink?.success(hashMapOf(" uiEvent" to " ended" ))
152+ uiEventSink?.endOfStream()
153+ }
150154 }
151155 }
152156 }
153- }
154157 }
155158 }
156159 }
@@ -171,23 +174,23 @@ class IProovSDKPlugin : FlutterPlugin {
171174 " keyPair.sign" -> {
172175 val data = call.arguments
173176 if (data is ByteArray ) {
174- val signature = launcher .getKeyPair(context!! ).sign(data)
177+ val signature = IProov .getKeyPair(context!! ).sign(data)
175178 result.success(signature)
176179 } else {
177180 result.error(" INVALID" , " Invalid argument passed" , null )
178181 }
179182 }
180183
181- " keyPair.publicKey.getPem" -> result.success(launcher .getKeyPair(context!! ).publicKey.pem)
182- " keyPair.publicKey.getDer" -> result.success(launcher .getKeyPair(context!! ).publicKey.der)
184+ " keyPair.publicKey.getPem" -> result.success(IProov .getKeyPair(context!! ).publicKey.pem)
185+ " keyPair.publicKey.getDer" -> result.success(IProov .getKeyPair(context!! ).publicKey.der)
183186 " cancel" -> cancelSession()
184187 else -> result.notImplemented()
185188 }
186189 }
187190
188191 private fun cancelSession () {
189192 coroutineScope.launch {
190- launcher.currentSession() ?.cancel()
193+ IProov .session ?.cancel()
191194 }
192195 }
193196
@@ -227,13 +230,23 @@ class IProovSDKPlugin : FlutterPlugin {
227230 }
228231
229232 coroutineScope.launch {
230- launcher.launch(context, streamingUrl, token, options)
233+ IProov .createSession(context, streamingUrl, token, options).let { session ->
234+ // Observe first, then start
235+ observeSession(session) {
236+ session.start()
237+ }
238+ }
231239 }
232240 }
233241 }
234242 }
235243 }
236244
245+ private fun observeSession (session : IProov .Session , whenReady : (() -> Unit )? = null) {
246+ observeSessionState(session, whenReady)
247+ observeSessionUIState(session)
248+ }
249+
237250 override fun onAttachedToEngine (flutterPluginBinding : FlutterPlugin .FlutterPluginBinding ) {
238251 this .flutterPluginBinding = flutterPluginBinding
239252
@@ -255,7 +268,7 @@ class IProovSDKPlugin : FlutterPlugin {
255268
256269 override fun onCancel (arguments : Any? ) {
257270 coroutineScope.launch {
258- launcher.currentSession() ?.cancel()
271+ IProov .session ?.cancel()
259272 }
260273 eventSink = null
261274 }
0 commit comments