@@ -61,7 +61,12 @@ object Mindbox {
6161 private const val DELIVER_TOKEN_DELAY = 1L
6262
6363 private val mindboxJob = SupervisorJob ()
64- internal val mindboxScope = CoroutineScope (Default + mindboxJob)
64+ private val coroutineExceptionHandler = CoroutineExceptionHandler { _, throwable ->
65+ MindboxLoggerImpl .e(Mindbox , " Mindbox caught unhandled error" , throwable)
66+ }
67+ internal val mindboxScope = CoroutineScope (
68+ Default + mindboxJob + coroutineExceptionHandler,
69+ )
6570 private val tokenCallbacks = ConcurrentHashMap <String , (String ?) - > Unit > ()
6671 private val deviceUuidCallbacks = ConcurrentHashMap <String , (String ) - > Unit > ()
6772
@@ -186,7 +191,7 @@ object Mindbox {
186191 */
187192 fun updatePushToken (context : Context , token : String ) = LoggingExceptionHandler .runCatching {
188193 if (token.trim().isNotEmpty()) {
189- initComponents(context, pushServiceHandler )
194+ initComponents(context)
190195
191196 if (! MindboxPreferences .isFirstInitialize) {
192197 mindboxScope.launch {
@@ -204,7 +209,7 @@ object Mindbox {
204209 * @param uniqKey - unique identifier of push notification
205210 */
206211 fun onPushReceived (context : Context , uniqKey : String ) = LoggingExceptionHandler .runCatching {
207- initComponents(context, pushServiceHandler )
212+ initComponents(context)
208213 MindboxEventManager .pushDelivered(context, uniqKey)
209214
210215 if (! MindboxPreferences .isFirstInitialize) {
@@ -227,7 +232,7 @@ object Mindbox {
227232 uniqKey : String ,
228233 buttonUniqKey : String? ,
229234 ) = LoggingExceptionHandler .runCatching {
230- initComponents(context, pushServiceHandler )
235+ initComponents(context)
231236 MindboxEventManager .pushClicked(context, TrackClickData (uniqKey, buttonUniqKey))
232237
233238 if (! MindboxPreferences .isFirstInitialize) {
@@ -265,22 +270,25 @@ object Mindbox {
265270
266271 /* *
267272 * Initializes the SDK for further work.
268- * We recommend calling it in onCreate on an application class
273+ *
274+ * We recommend calling it synchronously in onCreate on an application class
275+ *
276+ * If you must call it the other way, invoke [Mindbox.setPushServiceHandler] in [Application.onCreate] or else pushes won't be shown when application is inactive
269277 *
270278 * @param context used to initialize the main tools
271279 * @param configuration contains the data that is needed to connect to the Mindbox
280+ * @param pushServices list, containing [MindboxPushService]s, i.e.
281+ * ```
282+ * listOf(MindboxFirebase, MindboxHuawei)
283+ * ```
272284 */
273285 fun init (
274286 context : Context ,
275287 configuration : MindboxConfiguration ,
276288 pushServices : List <MindboxPushService >,
277289 ) {
278290 LoggingExceptionHandler .runCatching {
279- val pushService = pushServices
280- .map { it.getServiceHandler(MindboxLoggerImpl , LoggingExceptionHandler ) }
281- .firstOrNull { it.isServiceAvailable(context) }
282-
283- initComponents(context, pushService)
291+ initComponents(context, pushServices)
284292
285293 mindboxScope.launch {
286294 if (MindboxPreferences .isFirstInitialize) {
@@ -310,6 +318,14 @@ object Mindbox {
310318 " Incorrect context type for calling init in this place" ,
311319 )
312320 }
321+ if (isApplicationResumed || context !is Application ) {
322+ MindboxLoggerImpl .w(
323+ this ,
324+ " We recommend to call Mindbox.init() synchronously from " +
325+ " Application.onCreate. If you can't do so, don't forget to " +
326+ " call Mindbox.initPushServices from Application.onCreate" ,
327+ )
328+ }
313329
314330 lifecycleManager = LifecycleManager (
315331 currentActivityName = activity?.javaClass?.name,
@@ -333,6 +349,75 @@ object Mindbox {
333349 }
334350 }
335351
352+ /* *
353+ * Method to initialise push services
354+ *
355+ * You must call this method in onCreate in your Application class if you call [Mindbox.init] not there
356+ *
357+ * @param context used to initialize the main tools
358+ * @param pushServices list, containing [MindboxPushService]s, i.e.
359+ * ```
360+ * listOf(MindboxFirebase, MindboxHuawei)
361+ * ```
362+ */
363+ fun initPushServices (
364+ context : Context ,
365+ pushServices : List <MindboxPushService >,
366+ ) = initComponents(context, pushServices)
367+
368+ private fun setPushServiceHandler (
369+ context : Context ,
370+ pushServices : List <MindboxPushService >? = null,
371+ ) = LoggingExceptionHandler .runCatching {
372+ if (pushServiceHandler == null && pushServices != null ) {
373+ val savedProvider = MindboxPreferences .notificationProvider
374+ selectPushServiceHandler(context, pushServices, savedProvider)
375+ ?.let { pushServiceHandler ->
376+ this .pushServiceHandler = pushServiceHandler
377+ pushServiceHandler.notificationProvider
378+ .takeIf { it != savedProvider }
379+ ?.let { newProvider ->
380+ MindboxPreferences .notificationProvider = newProvider
381+ if (! MindboxPreferences .isFirstInitialize) {
382+ mindboxScope.launch {
383+ updateAppInfo(context)
384+ }
385+ }
386+ }
387+ mindboxScope.launch {
388+ pushServiceHandler.initService(context)
389+ }
390+ }
391+ }
392+ }
393+
394+ private fun selectPushServiceHandler (
395+ context : Context ,
396+ pushServices : List <MindboxPushService >,
397+ savedProvider : String ,
398+ ): PushServiceHandler ? {
399+ val serviceHandlers = pushServices
400+ .map { it.getServiceHandler(MindboxLoggerImpl , LoggingExceptionHandler ) }
401+ return serviceHandlers.firstOrNull { it.notificationProvider == savedProvider }
402+ ? : initAvailablePushService(context, serviceHandlers, savedProvider)
403+ }
404+
405+ private fun initAvailablePushService (
406+ context : Context ,
407+ serviceHandlers : List <PushServiceHandler >,
408+ savedProvider : String ,
409+ ) = if (savedProvider.isBlank()) {
410+ serviceHandlers.firstOrNull { it.isServiceAvailable(context) }
411+ } else {
412+ MindboxLoggerImpl .e(
413+ Mindbox ,
414+ " Mindbox was previously initialized with $savedProvider push service but " +
415+ " Mindbox did not find it within pushServices. Check your Mindbox.init() and " +
416+ " Mindbox.initPushServices()" ,
417+ )
418+ null
419+ }
420+
336421 /* *
337422 * Send track visit event after link or push was clicked for [Activity] with launchMode equals
338423 * "singleTop" or "singleTask" or if a client used the [Intent.FLAG_ACTIVITY_SINGLE_TOP] or
@@ -560,13 +645,10 @@ object Mindbox {
560645 }, DELIVER_TOKEN_DELAY , TimeUnit .SECONDS )
561646 }
562647
563- internal fun initComponents (context : Context , pushServiceHandler : PushServiceHandler ? ) {
648+ internal fun initComponents (context : Context , pushServices : List < MindboxPushService > ? = null ) {
564649 SharedPreferencesManager .with (context)
565650 DbManager .init (context)
566- this .pushServiceHandler = pushServiceHandler
567- mindboxScope.launch {
568- pushServiceHandler?.initService(context)
569- }
651+ setPushServiceHandler(context, pushServices)
570652 }
571653
572654 private fun <T > asyncOperation (
@@ -596,7 +678,7 @@ object Mindbox {
596678 operationSystemName : String ,
597679 ) = LoggingExceptionHandler .runCatching(defaultValue = false ) {
598680 if (operationSystemName.matches(OPERATION_NAME_REGEX .toRegex())) {
599- initComponents(context, pushServiceHandler )
681+ initComponents(context)
600682 } else {
601683 MindboxLoggerImpl .w(
602684 this ,
@@ -628,6 +710,7 @@ object Mindbox {
628710 DbManager .saveConfigurations(Configuration (configuration))
629711
630712 val isTokenAvailable = ! pushToken.isNullOrEmpty()
713+ val notificationProvider = pushServiceHandler?.notificationProvider ? : " "
631714 val initData = InitData (
632715 token = pushToken ? : " " ,
633716 isTokenAvailable = isTokenAvailable,
@@ -636,13 +719,14 @@ object Mindbox {
636719 isNotificationsEnabled = isNotificationEnabled,
637720 subscribe = configuration.subscribeCustomerIfCreated,
638721 instanceId = instanceId,
639- notificationProvider = pushServiceHandler?. notificationProvider ? : " " ,
722+ notificationProvider = notificationProvider,
640723 )
641724
642725 MindboxPreferences .deviceUuid = deviceUuid
643726 MindboxPreferences .pushToken = pushToken
644727 MindboxPreferences .isNotificationEnabled = isNotificationEnabled
645728 MindboxPreferences .instanceId = instanceId
729+ MindboxPreferences .notificationProvider = notificationProvider
646730
647731 MindboxEventManager .appInstalled(context, initData, configuration.shouldCreateCustomer)
648732
0 commit comments