Skip to content

Commit 3ecd501

Browse files
authored
Merge pull request #124 from mindbox-cloud/release/2.14.3
Release 2.14.3
2 parents 274c32f + 137d194 commit 3ecd501

17 files changed

+466
-17
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## [Unreleased]
4+
5+
### Changes
6+
- Upgrade Android SDK dependency to v2.14.2
7+
- Upgrade iOS SDK dependency to v2.14.3
8+
9+
310
## [2.14.1] - 2025-09-12
411

512
### Changes

MindboxSdk.podspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ Pod::Spec.new do |s|
1717

1818
s.dependency "React-Core"
1919

20-
s.dependency "Mindbox", "2.14.1"
21-
s.dependency "MindboxNotifications", "2.14.1"
20+
s.dependency "Mindbox", "2.14.3"
21+
s.dependency "MindboxNotifications", "2.14.3"
2222
end

android/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ android {
3333
targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
3434
versionCode 1
3535
versionName "1.0"
36+
consumerProguardFiles 'consumer-rules.pro'
3637
}
3738

3839
buildTypes {
@@ -126,5 +127,5 @@ dependencies {
126127
// noinspection GradleDynamicVersion
127128
api 'com.facebook.react:react-native:+'
128129
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
129-
api 'cloud.mindbox:mobile-sdk:2.14.1'
130+
api 'cloud.mindbox:mobile-sdk:2.14.2'
130131
}

android/consumer-rules.pro

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-keep class com.facebook.react.ReactHost { *; }
2+
-keep interface com.facebook.react.ReactInstanceEventListener { *; }
3+
-keep interface com.facebook.react.ReactApplication {
4+
public com.facebook.react.ReactHost getReactHost();
5+
}
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
22
package="com.mindboxsdk">
3-
3+
<application>
4+
<provider
5+
android:name="com.mindboxsdk.MindboxSdkInitProvider"
6+
android:authorities="${applicationId}.mindbox.init"
7+
android:exported="false" />
8+
</application>
49
</manifest>
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.mindboxsdk
2+
3+
import android.app.Activity
4+
import android.app.Application
5+
import android.content.Context
6+
import android.content.Intent
7+
import android.util.Log
8+
import com.facebook.react.ReactApplication
9+
import com.facebook.react.ReactInstanceManager
10+
import com.facebook.react.bridge.ReactContext
11+
import com.facebook.react.ReactActivity
12+
import cloud.mindbox.mobile_sdk.Mindbox
13+
import cloud.mindbox.mobile_sdk.logger.Level
14+
15+
internal class MindboxEventEmitter (
16+
private val application: Application
17+
) : MindboxEventSubscriber {
18+
19+
private var jsDelivery: MindboxJsDelivery? = null
20+
21+
override fun onEvent(event: MindboxSdkLifecycleEvent) {
22+
when (event) {
23+
is MindboxSdkLifecycleEvent.NewIntent -> handleNewIntent(event.reactContext, event.intent)
24+
is MindboxSdkLifecycleEvent.ActivityCreated -> handleActivityCreated(event.reactContext, event.activity)
25+
is MindboxSdkLifecycleEvent.ActivityDestroyed -> handleActivityDestroyed()
26+
}
27+
}
28+
29+
private fun handleNewIntent(context: ReactContext, intent: Intent) {
30+
Mindbox.writeLog("[RN] Handle new intent in event emitter. ", Level.INFO)
31+
Mindbox.onNewIntent(intent)
32+
Mindbox.onPushClicked(context, intent)
33+
jsDelivery?.sendPushClicked(intent)
34+
}
35+
36+
private fun handleActivityCreated(reactContext:ReactContext, activity: Activity) {
37+
Mindbox.writeLog("[RN] Handle activity created", Level.INFO)
38+
runCatching {
39+
reactContext.let { reactContext ->
40+
initializeAndSendIntent(reactContext, activity)
41+
}
42+
}
43+
}
44+
45+
private fun initializeAndSendIntent(context: ReactContext, activity: Activity) {
46+
Mindbox.writeLog("[RN] Initialize MindboxJsDelivery", Level.INFO)
47+
jsDelivery = MindboxJsDelivery.Shared.getInstance(context)
48+
val currentActivity = context.currentActivity ?: activity
49+
currentActivity.intent?.let { handleNewIntent(context, it) }
50+
}
51+
52+
private fun handleActivityDestroyed() {
53+
jsDelivery = null
54+
}
55+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.mindboxsdk
2+
3+
internal interface MindboxEventSubscriber {
4+
fun onEvent(event: MindboxSdkLifecycleEvent)
5+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package com.mindboxsdk
2+
3+
import android.os.Bundle
4+
import android.util.Log
5+
import cloud.mindbox.mobile_sdk.pushes.MindboxPushService
6+
7+
internal class MindboxPushServicesDiscovery(private val meta: Bundle?) {
8+
9+
companion object {
10+
private const val TAG = "MindboxPushServicesDiscovery"
11+
private const val PUSH_PROVIDER_PREFIX = "cloud.mindbox.push.provider."
12+
}
13+
14+
private val providerPriority: Map<String, Int> by lazy(LazyThreadSafetyMode.NONE) {
15+
mapOf("FCM" to 0, "HCM" to 1, "RuStore" to 2)
16+
}
17+
18+
val services: List<MindboxPushService> by lazy(LazyThreadSafetyMode.NONE) {
19+
if (meta == null) {
20+
return@lazy emptyList()
21+
}
22+
meta.keySet()
23+
.asSequence()
24+
.filter { it.startsWith(PUSH_PROVIDER_PREFIX) }
25+
.mapNotNull { key -> meta.getString(key)?.takeIf { it.isNotBlank() } }
26+
.mapNotNull { className -> loadPushService(className) }
27+
.distinctBy { it::class.java.name }
28+
.sortedWith(
29+
compareBy<MindboxPushService> { providerPriority[it.tag] ?: Int.MAX_VALUE }
30+
.thenBy { it.tag }
31+
)
32+
.toList()
33+
.also { list ->
34+
Log.i(TAG, "Found ${list.size} push services: ${list.joinToString { it.tag }}")
35+
list
36+
}
37+
}
38+
39+
private fun loadPushService(className: String): MindboxPushService? {
40+
return runCatching {
41+
val clazz = Class.forName(className)
42+
43+
if (!MindboxPushService::class.java.isAssignableFrom(clazz)) {
44+
Log.w(TAG, "Class $className does not implement MindboxPushService")
45+
return@runCatching null
46+
}
47+
getPushServiceInstance(clazz)?.also {
48+
Log.i(TAG, "Loaded push provider: $className")
49+
} ?: run {
50+
Log.e(TAG, "Failed to create instance for provider: $className")
51+
null
52+
}
53+
}.getOrElse { exception ->
54+
when (exception) {
55+
is ClassNotFoundException -> Log.e(TAG, "Push provider class not found: $className", exception)
56+
else -> Log.e(TAG, "Failed to load push provider: $className", exception)
57+
}
58+
null
59+
}
60+
}
61+
62+
private fun getPushServiceInstance(clazz: Class<*>): MindboxPushService? {
63+
return runCatching {
64+
val instanceField = clazz.getDeclaredField("INSTANCE")
65+
instanceField.isAccessible = true
66+
instanceField.get(null) as? MindboxPushService
67+
}.getOrElse {
68+
Log.w(TAG, "Failed to get instance for ${clazz.name}")
69+
null
70+
}
71+
}
72+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.mindboxsdk
2+
3+
import android.app.Application
4+
import android.content.ContentProvider
5+
import android.content.ContentValues
6+
import android.content.pm.PackageManager
7+
import android.database.Cursor
8+
import android.net.Uri
9+
import android.os.Bundle
10+
import android.util.Log
11+
import cloud.mindbox.mobile_sdk.pushes.MindboxPushService
12+
import cloud.mindbox.mobile_sdk.Mindbox
13+
14+
internal class MindboxSdkInitProvider : ContentProvider() {
15+
16+
companion object {
17+
private const val AUTO_INIT_ENABLED_KEY = "com.mindbox.sdk.AUTO_INIT_ENABLED"
18+
private const val TAG = "MindboxSdkInitProvider"
19+
}
20+
21+
override fun onCreate(): Boolean {
22+
runCatching {
23+
Log.i(TAG, "onCreate initProvider.")
24+
(context?.applicationContext as? Application)?.let { application ->
25+
val meta = application.readMetaData()
26+
if (isAutoInitEnabled(application, meta)) {
27+
Log.i(TAG, "Automatic initialization is enabled.")
28+
Mindbox.initPushServices(application, MindboxPushServicesDiscovery(meta).services)
29+
MindboxSdkLifecycleListener.register(application)
30+
} else {
31+
Log.i(TAG, "Automatic initialization is disabled.")
32+
}
33+
}
34+
}.onFailure { error ->
35+
Log.e(TAG, "Automatic initialization failed", error)
36+
}
37+
return true
38+
}
39+
40+
private fun isAutoInitEnabled(application: Application, metaData: Bundle?): Boolean =
41+
metaData
42+
?.getBoolean(AUTO_INIT_ENABLED_KEY, false)
43+
?: false
44+
45+
private fun Application.readMetaData(): Bundle? = runCatching {
46+
packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA).metaData
47+
}.getOrNull()
48+
49+
override fun query(
50+
uri: Uri,
51+
projection: Array<String>?,
52+
selection: String?,
53+
selectionArgs: Array<String>?,
54+
sortOrder: String?
55+
): Cursor? = null
56+
57+
override fun getType(uri: Uri): String? = null
58+
override fun insert(uri: Uri, values: ContentValues?): Uri? = null
59+
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int = 0
60+
override fun update(
61+
uri: Uri,
62+
values: ContentValues?,
63+
selection: String?,
64+
selectionArgs: Array<String>?
65+
): Int = 0
66+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.mindboxsdk
2+
3+
import android.app.Activity
4+
import android.content.Intent
5+
import com.facebook.react.bridge.ReactContext
6+
7+
internal sealed class MindboxSdkLifecycleEvent {
8+
data class NewIntent(val reactContext: ReactContext, val intent: Intent) : MindboxSdkLifecycleEvent()
9+
data class ActivityCreated(val reactContext: ReactContext, val activity: Activity) : MindboxSdkLifecycleEvent()
10+
data class ActivityDestroyed(val activity: Activity) : MindboxSdkLifecycleEvent()
11+
}

0 commit comments

Comments
 (0)