react-native-mapp-plugin 1.4.2 → 2.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BREAKING_CHANGES.md +126 -0
- package/CHANGELOG.md +22 -0
- package/MIGRATION_2.0.md +100 -0
- package/Mapp.js +7 -8
- package/README.md +138 -75
- package/RNMappPlugin.podspec +10 -4
- package/android/build.gradle +137 -7
- package/android/gradle.properties +0 -2
- package/android/settings.gradle +5 -6
- package/android/src/main/AndroidManifest.xml +8 -1
- package/android/src/main/java/com/reactlibrary/MappEngagementDispatcher.java +102 -0
- package/android/src/main/java/com/reactlibrary/MappPushHelper.java +126 -0
- package/android/src/main/java/com/reactlibrary/MessageService.java +3 -23
- package/android/src/main/java/com/reactlibrary/RNMappPluginModule.java +94 -28
- package/app.plugin.js +4 -0
- package/ios/RNMappEventEmmiter.m +21 -2
- package/ios/RNMappPluginModule.h +8 -1
- package/ios/{RNMappPluginModule.m → RNMappPluginModule.mm} +123 -39
- package/package.json +31 -8
- package/plugin/build/android.d.ts +4 -0
- package/plugin/build/android.js +53 -0
- package/plugin/build/index.d.ts +8 -0
- package/plugin/build/index.js +24 -0
- package/plugin/build/ios.d.ts +5 -0
- package/plugin/build/ios.js +77 -0
- package/plugin/build/types.d.ts +32 -0
- package/plugin/build/types.js +2 -0
- package/plugin/build/validation.d.ts +3 -0
- package/plugin/build/validation.js +76 -0
- package/specs/NativeRNMappPluginModule.js +3 -0
package/android/build.gradle
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
apply plugin: "com.android.library"
|
|
2
2
|
|
|
3
|
+
import groovy.json.JsonSlurper
|
|
4
|
+
|
|
3
5
|
def getExtOrDefault = { name, fallback ->
|
|
4
6
|
rootProject.ext.has(name) ? rootProject.ext.get(name) : fallback
|
|
5
7
|
}
|
|
6
8
|
|
|
9
|
+
def reactNativePackage = [
|
|
10
|
+
file("../node_modules/react-native/package.json"),
|
|
11
|
+
file("../../react-native/package.json")
|
|
12
|
+
].find { it.exists() }
|
|
13
|
+
if (reactNativePackage == null) {
|
|
14
|
+
throw new GradleException("react-native-mapp-plugin could not resolve react-native/package.json")
|
|
15
|
+
}
|
|
16
|
+
def resolvedReactNativeVersion = new JsonSlurper().parse(reactNativePackage).version
|
|
17
|
+
|
|
7
18
|
android {
|
|
8
19
|
namespace "com.reactlibrary"
|
|
9
20
|
compileSdk = getExtOrDefault("compileSdkVersion", 36)
|
|
@@ -29,34 +40,153 @@ android {
|
|
|
29
40
|
}
|
|
30
41
|
|
|
31
42
|
dependencies {
|
|
32
|
-
|
|
33
|
-
|
|
43
|
+
implementation "com.facebook.react:react-android:${resolvedReactNativeVersion}"
|
|
44
|
+
api platform("org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.11.0")
|
|
45
|
+
api enforcedPlatform("org.jetbrains.kotlin:kotlin-bom:2.1.20")
|
|
34
46
|
constraints {
|
|
35
|
-
|
|
47
|
+
api("androidx.core:core") {
|
|
36
48
|
version {
|
|
37
49
|
strictly "1.18.0"
|
|
38
50
|
}
|
|
39
51
|
because "androidx.core 1.19.0 requires AGP 9.1+, while React Native dependencies currently require the app to stay on AGP 8"
|
|
40
52
|
}
|
|
41
|
-
|
|
53
|
+
api("androidx.core:core-ktx") {
|
|
42
54
|
version {
|
|
43
55
|
strictly "1.18.0"
|
|
44
56
|
}
|
|
45
|
-
|
|
57
|
+
because "androidx.core-ktx 1.19.0 requires AGP 9.1+, while React Native dependencies currently require the app to stay on AGP 8"
|
|
58
|
+
}
|
|
59
|
+
["work-runtime", "work-runtime-ktx"].each { module ->
|
|
60
|
+
api("androidx.work:${module}") {
|
|
61
|
+
version { strictly "2.10.5" }
|
|
62
|
+
because "Expo SDK 57 uses AGP 8.12 and cannot consume WorkManager 2.11 metadata"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
[
|
|
66
|
+
"lifecycle-common",
|
|
67
|
+
"lifecycle-common-java8",
|
|
68
|
+
"lifecycle-livedata-core",
|
|
69
|
+
"lifecycle-livedata-core-ktx",
|
|
70
|
+
"lifecycle-process",
|
|
71
|
+
"lifecycle-runtime",
|
|
72
|
+
"lifecycle-runtime-android",
|
|
73
|
+
"lifecycle-runtime-ktx",
|
|
74
|
+
"lifecycle-service",
|
|
75
|
+
"lifecycle-viewmodel",
|
|
76
|
+
"lifecycle-viewmodel-android",
|
|
77
|
+
"lifecycle-viewmodel-ktx",
|
|
78
|
+
"lifecycle-viewmodel-savedstate"
|
|
79
|
+
].each { module ->
|
|
80
|
+
api("androidx.lifecycle:${module}") {
|
|
81
|
+
version { strictly "2.10.0" }
|
|
82
|
+
because "Expo SDK 57 uses AGP 8.12 and cannot consume Lifecycle 2.11 metadata"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
api("com.google.android.gms:play-services-location") {
|
|
86
|
+
version { strictly "21.3.0" }
|
|
87
|
+
because "21.4.0 requires an Android toolchain newer than the Expo SDK 57 baseline"
|
|
88
|
+
}
|
|
89
|
+
["kotlinx-coroutines-android", "kotlinx-coroutines-core", "kotlinx-coroutines-core-jvm"].each { module ->
|
|
90
|
+
api("org.jetbrains.kotlinx:${module}") {
|
|
91
|
+
version { strictly "1.11.0" }
|
|
92
|
+
because "Mapp Engage 7.1.2 native in-app UI requires the coroutines 1.11 Job ABI"
|
|
93
|
+
}
|
|
46
94
|
}
|
|
47
95
|
}
|
|
48
96
|
implementation 'com.google.code.gson:gson:2.14.0'
|
|
49
97
|
implementation 'androidx.appcompat:appcompat:1.7.1'
|
|
50
98
|
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7'
|
|
51
|
-
implementation platform('com.google.firebase:firebase-bom:33.16.0')
|
|
52
99
|
implementation('com.google.firebase:firebase-messaging')
|
|
53
100
|
api('com.google.android.gms:play-services-location:21.3.0')
|
|
54
101
|
implementation 'androidx.media:media:1.8.0'
|
|
55
102
|
implementation 'androidx.legacy:legacy-support-v13:1.0.0'
|
|
56
|
-
implementation("com.mapp.sdk:engage-android:7.1.2")
|
|
103
|
+
implementation("com.mapp.sdk:engage-android:7.1.2") {
|
|
104
|
+
exclude group: "androidx.lifecycle", module: "lifecycle-extensions"
|
|
105
|
+
}
|
|
57
106
|
testImplementation 'junit:junit:4.13.2'
|
|
58
107
|
testImplementation 'org.mockito:mockito-core:5.23.0'
|
|
59
108
|
testImplementation 'org.mockito:mockito-inline:5.2.0'
|
|
60
109
|
testImplementation 'org.json:json:20260522'
|
|
61
110
|
testImplementation 'org.robolectric:robolectric:4.16.1'
|
|
62
111
|
}
|
|
112
|
+
|
|
113
|
+
tasks.register("verifyExpo57RuntimeDependencies") {
|
|
114
|
+
group = "verification"
|
|
115
|
+
description = "Checks the Expo SDK 57 runtime pins and Mapp's required coroutines ABI."
|
|
116
|
+
doLast {
|
|
117
|
+
def expected = [
|
|
118
|
+
"androidx.core:core": "1.18.0",
|
|
119
|
+
"androidx.core:core-ktx": "1.18.0",
|
|
120
|
+
"androidx.work:work-runtime": "2.10.5",
|
|
121
|
+
"androidx.lifecycle:lifecycle-runtime": "2.10.0",
|
|
122
|
+
"com.google.android.gms:play-services-location": "21.3.0",
|
|
123
|
+
"org.jetbrains.kotlin:kotlin-stdlib": "2.1.20",
|
|
124
|
+
"org.jetbrains.kotlinx:kotlinx-coroutines-android": "1.11.0",
|
|
125
|
+
"org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm": "1.11.0"
|
|
126
|
+
]
|
|
127
|
+
def artifacts = configurations.debugRuntimeClasspath.resolvedConfiguration.resolvedArtifacts
|
|
128
|
+
def selected = configurations.debugRuntimeClasspath.incoming.resolutionResult.allComponents
|
|
129
|
+
.findAll { it.moduleVersion != null }
|
|
130
|
+
.collectEntries { component ->
|
|
131
|
+
[("${component.moduleVersion.group}:${component.moduleVersion.name}".toString()): component.moduleVersion.version]
|
|
132
|
+
}
|
|
133
|
+
expected.each { module, version ->
|
|
134
|
+
if (selected[module] != version) {
|
|
135
|
+
throw new GradleException("Expected ${module}:${version}, resolved ${selected[module] ?: 'nothing'}")
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
selected.findAll { module, ignored -> module.startsWith("androidx.lifecycle:") }.each { module, version ->
|
|
139
|
+
if (module != "androidx.lifecycle:lifecycle-extensions" && version != "2.10.0") {
|
|
140
|
+
throw new GradleException("Expected Lifecycle 2.10.0, resolved ${module}:${version}")
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (selected.containsKey("androidx.lifecycle:lifecycle-extensions")) {
|
|
144
|
+
throw new GradleException("lifecycle-extensions must not be present in the runtime graph")
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
def coroutineJar = artifacts.find {
|
|
148
|
+
it.moduleVersion.id.group == "org.jetbrains.kotlinx"
|
|
149
|
+
&& it.moduleVersion.id.name == "kotlinx-coroutines-core-jvm"
|
|
150
|
+
}?.file
|
|
151
|
+
if (coroutineJar == null) {
|
|
152
|
+
throw new GradleException("Could not inspect kotlinx-coroutines-core-jvm")
|
|
153
|
+
}
|
|
154
|
+
def javap = new ProcessBuilder(
|
|
155
|
+
"${System.getProperty('java.home')}/bin/javap",
|
|
156
|
+
"-classpath",
|
|
157
|
+
coroutineJar.absolutePath,
|
|
158
|
+
"kotlinx.coroutines.Job"
|
|
159
|
+
).redirectErrorStream(true).start()
|
|
160
|
+
def javapOutput = javap.inputStream.getText("UTF-8")
|
|
161
|
+
if (javap.waitFor() != 0) {
|
|
162
|
+
throw new GradleException("Unable to inspect the resolved coroutines Job ABI:\n${javapOutput}")
|
|
163
|
+
}
|
|
164
|
+
if (!javapOutput.contains('cancel$default(kotlinx.coroutines.Job, java.util.concurrent.CancellationException, int, java.lang.Object)')) {
|
|
165
|
+
throw new GradleException("Resolved coroutines Job is missing Mapp's required cancel\$default ABI")
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
def apiElements = configurations.getByName("releaseApiElements")
|
|
169
|
+
def exportedConstraints = apiElements.allDependencyConstraints.collect {
|
|
170
|
+
"${it.group}:${it.name}:${it.versionConstraint.strictVersion}".toString()
|
|
171
|
+
}
|
|
172
|
+
[
|
|
173
|
+
"androidx.work:work-runtime:2.10.5",
|
|
174
|
+
"androidx.lifecycle:lifecycle-runtime:2.10.0",
|
|
175
|
+
"org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.11.0"
|
|
176
|
+
].each { constraint ->
|
|
177
|
+
if (!exportedConstraints.contains(constraint)) {
|
|
178
|
+
throw new GradleException("Compatibility constraint is not exported: ${constraint}")
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
def exportedDependencies = apiElements.allDependencies.collect {
|
|
182
|
+
"${it.group}:${it.name}:${it.version}".toString()
|
|
183
|
+
}
|
|
184
|
+
if (!exportedDependencies.contains("org.jetbrains.kotlin:kotlin-bom:2.1.20")) {
|
|
185
|
+
throw new GradleException("The Expo Kotlin compatibility platform is not exported")
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
tasks.named("check").configure {
|
|
191
|
+
dependsOn("verifyExpo57RuntimeDependencies")
|
|
192
|
+
}
|
package/android/settings.gradle
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
pluginManagement {
|
|
2
|
+
includeBuild("../node_modules/@react-native/gradle-plugin")
|
|
2
3
|
repositories {
|
|
3
4
|
google()
|
|
4
5
|
mavenCentral()
|
|
5
6
|
gradlePluginPortal()
|
|
6
7
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
plugins {
|
|
11
|
+
id("com.android.library") version("8.12.0") apply false
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
dependencyResolutionManagement {
|
|
@@ -17,6 +18,4 @@ dependencyResolutionManagement {
|
|
|
17
18
|
mavenCentral()
|
|
18
19
|
}
|
|
19
20
|
}
|
|
20
|
-
includeBuild("../node_modules/@react-native/gradle-plugin")
|
|
21
|
-
|
|
22
21
|
rootProject.name="MappEngagePlugin"
|
|
@@ -42,6 +42,14 @@
|
|
|
42
42
|
|
|
43
43
|
</intent-filter>
|
|
44
44
|
</activity>
|
|
45
|
+
<service
|
|
46
|
+
android:name="com.appoxee.shared.MappMessagingService"
|
|
47
|
+
tools:node="remove"
|
|
48
|
+
android:exported="false">
|
|
49
|
+
<intent-filter>
|
|
50
|
+
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
|
51
|
+
</intent-filter>
|
|
52
|
+
</service>
|
|
45
53
|
<service
|
|
46
54
|
android:name="com.appoxee.push.fcm.MappMessagingService"
|
|
47
55
|
tools:node="remove"
|
|
@@ -71,4 +79,3 @@
|
|
|
71
79
|
</application>
|
|
72
80
|
|
|
73
81
|
</manifest>
|
|
74
|
-
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
package com.reactlibrary;
|
|
2
|
+
|
|
3
|
+
import android.app.Application;
|
|
4
|
+
import android.os.Handler;
|
|
5
|
+
import android.os.Looper;
|
|
6
|
+
import android.util.Log;
|
|
7
|
+
|
|
8
|
+
import androidx.annotation.NonNull;
|
|
9
|
+
import androidx.annotation.Nullable;
|
|
10
|
+
|
|
11
|
+
import com.appoxee.Appoxee;
|
|
12
|
+
import com.appoxee.shared.AppoxeeOptions;
|
|
13
|
+
|
|
14
|
+
import java.util.concurrent.CountDownLatch;
|
|
15
|
+
import java.util.concurrent.TimeUnit;
|
|
16
|
+
import java.util.concurrent.atomic.AtomicBoolean;
|
|
17
|
+
|
|
18
|
+
/** Keeps every Appoxee.engage call on Android's main looper. */
|
|
19
|
+
final class MappEngagementDispatcher {
|
|
20
|
+
private static final String TAG = "MappEngage";
|
|
21
|
+
static final long ENGAGE_TIMEOUT_MILLIS = 5_000;
|
|
22
|
+
|
|
23
|
+
private MappEngagementDispatcher() {}
|
|
24
|
+
|
|
25
|
+
static void engageAsync(
|
|
26
|
+
@NonNull Application application,
|
|
27
|
+
@Nullable AppoxeeOptions options,
|
|
28
|
+
@Nullable Runnable afterEngage
|
|
29
|
+
) {
|
|
30
|
+
Runnable operation = () -> {
|
|
31
|
+
if (engageNow(application, options) && afterEngage != null) {
|
|
32
|
+
afterEngage.run();
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
if (Looper.myLooper() == Looper.getMainLooper()) {
|
|
36
|
+
operation.run();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (!new Handler(Looper.getMainLooper()).post(operation)) {
|
|
40
|
+
Log.e(TAG, "Unable to post Mapp initialization to the main looper");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
static boolean engageBlocking(@NonNull Application application, @Nullable AppoxeeOptions options) {
|
|
45
|
+
return engageBlocking(
|
|
46
|
+
application,
|
|
47
|
+
options,
|
|
48
|
+
new Handler(Looper.getMainLooper()),
|
|
49
|
+
ENGAGE_TIMEOUT_MILLIS
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static boolean engageBlocking(
|
|
54
|
+
@NonNull Application application,
|
|
55
|
+
@Nullable AppoxeeOptions options,
|
|
56
|
+
@NonNull Handler mainHandler,
|
|
57
|
+
long timeoutMillis
|
|
58
|
+
) {
|
|
59
|
+
if (Looper.myLooper() == Looper.getMainLooper()) {
|
|
60
|
+
return engageNow(application, options);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
CountDownLatch completion = new CountDownLatch(1);
|
|
64
|
+
AtomicBoolean engaged = new AtomicBoolean(false);
|
|
65
|
+
boolean posted = mainHandler.post(() -> {
|
|
66
|
+
try {
|
|
67
|
+
engaged.set(engageNow(application, options));
|
|
68
|
+
} finally {
|
|
69
|
+
completion.countDown();
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
if (!posted) {
|
|
73
|
+
Log.e(TAG, "Unable to post Mapp initialization to the main looper");
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
if (!completion.await(timeoutMillis, TimeUnit.MILLISECONDS)) {
|
|
79
|
+
Log.e(TAG, "Mapp initialization timed out on the main looper");
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
return engaged.get();
|
|
83
|
+
} catch (InterruptedException interrupted) {
|
|
84
|
+
Thread.currentThread().interrupt();
|
|
85
|
+
Log.w(TAG, "Interrupted while waiting for Mapp initialization", interrupted);
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private static boolean engageNow(
|
|
91
|
+
@NonNull Application application,
|
|
92
|
+
@Nullable AppoxeeOptions options
|
|
93
|
+
) {
|
|
94
|
+
try {
|
|
95
|
+
Appoxee.engage(application, options);
|
|
96
|
+
return true;
|
|
97
|
+
} catch (RuntimeException error) {
|
|
98
|
+
Log.e(TAG, "Mapp initialization failed", error);
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
package com.reactlibrary;
|
|
2
|
+
|
|
3
|
+
import android.app.Application;
|
|
4
|
+
import android.os.Handler;
|
|
5
|
+
import android.util.Log;
|
|
6
|
+
|
|
7
|
+
import androidx.annotation.NonNull;
|
|
8
|
+
|
|
9
|
+
import com.appoxee.Appoxee;
|
|
10
|
+
import com.google.firebase.messaging.RemoteMessage;
|
|
11
|
+
|
|
12
|
+
import java.util.concurrent.TimeUnit;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Native entry points for applications that own their FirebaseMessagingService.
|
|
16
|
+
* This API does not require a running React Native JavaScript runtime.
|
|
17
|
+
*/
|
|
18
|
+
public final class MappPushHelper {
|
|
19
|
+
private static final String TAG = "MappPushHelper";
|
|
20
|
+
private static final int READY_ATTEMPTS = 15;
|
|
21
|
+
private static final long READY_INTERVAL_MILLIS = 300;
|
|
22
|
+
|
|
23
|
+
private MappPushHelper() {}
|
|
24
|
+
|
|
25
|
+
/** Engage Mapp using AppoxeeConfig/native defaults if it has not been engaged yet. */
|
|
26
|
+
public static boolean initialize(@NonNull Application application) {
|
|
27
|
+
return MappEngagementDispatcher.engageBlocking(application, null);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static boolean initialize(@NonNull Application application, @NonNull Handler handler, long timeoutMillis) {
|
|
31
|
+
return MappEngagementDispatcher.engageBlocking(application, null, handler, timeoutMillis);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Return true only when the native Mapp SDK identifies this payload as its own. */
|
|
35
|
+
public static boolean isMappMessage(@NonNull RemoteMessage remoteMessage) {
|
|
36
|
+
try {
|
|
37
|
+
return Appoxee.instance().isPushMessageFromMapp(remoteMessage);
|
|
38
|
+
} catch (RuntimeException error) {
|
|
39
|
+
Log.e(TAG, "Unable to inspect remote message", error);
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Forward a Mapp message. Returns false for non-Mapp payloads or SDK failures. */
|
|
45
|
+
public static boolean handleMessage(@NonNull Application application, @NonNull RemoteMessage remoteMessage) {
|
|
46
|
+
return handleMessage(application, remoteMessage, null, MappEngagementDispatcher.ENGAGE_TIMEOUT_MILLIS);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static boolean handleMessage(
|
|
50
|
+
@NonNull Application application,
|
|
51
|
+
@NonNull RemoteMessage remoteMessage,
|
|
52
|
+
Handler handler,
|
|
53
|
+
long timeoutMillis
|
|
54
|
+
) {
|
|
55
|
+
boolean initialized = handler == null
|
|
56
|
+
? initialize(application)
|
|
57
|
+
: initialize(application, handler, timeoutMillis);
|
|
58
|
+
if (!initialized) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
if (!isMappMessage(remoteMessage) || !waitUntilReady()) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
Appoxee.instance().handlePushMessage(remoteMessage);
|
|
66
|
+
return true;
|
|
67
|
+
} catch (RuntimeException error) {
|
|
68
|
+
Log.e(TAG, "Unable to forward remote message", error);
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Forward a refreshed native FCM token without requiring JavaScript. */
|
|
74
|
+
public static boolean handleNewToken(@NonNull Application application, @NonNull String token) {
|
|
75
|
+
return handleNewToken(application, token, null, MappEngagementDispatcher.ENGAGE_TIMEOUT_MILLIS);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static boolean handleNewToken(
|
|
79
|
+
@NonNull Application application,
|
|
80
|
+
@NonNull String token,
|
|
81
|
+
Handler handler,
|
|
82
|
+
long timeoutMillis
|
|
83
|
+
) {
|
|
84
|
+
if (token.trim().isEmpty()) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
boolean initialized = handler == null
|
|
88
|
+
? initialize(application)
|
|
89
|
+
: initialize(application, handler, timeoutMillis);
|
|
90
|
+
if (!initialized) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
if (!waitUntilReady()) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
Appoxee.instance().updateFirebaseToken(token).enqueue(result -> {});
|
|
98
|
+
return true;
|
|
99
|
+
} catch (RuntimeException error) {
|
|
100
|
+
Log.e(TAG, "Unable to forward Firebase token", error);
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
public static boolean waitUntilReady() {
|
|
106
|
+
for (int attempt = 0; attempt <= READY_ATTEMPTS; attempt++) {
|
|
107
|
+
try {
|
|
108
|
+
if (Appoxee.instance().isReady()) {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
if (attempt < READY_ATTEMPTS) {
|
|
112
|
+
TimeUnit.MILLISECONDS.sleep(READY_INTERVAL_MILLIS);
|
|
113
|
+
}
|
|
114
|
+
} catch (InterruptedException interrupted) {
|
|
115
|
+
Thread.currentThread().interrupt();
|
|
116
|
+
Log.w(TAG, "Interrupted while waiting for Mapp initialization", interrupted);
|
|
117
|
+
return false;
|
|
118
|
+
} catch (RuntimeException error) {
|
|
119
|
+
Log.e(TAG, "Mapp initialization failed", error);
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
Log.w(TAG, "Mapp was not ready before the bounded wait expired");
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -4,13 +4,9 @@ import android.util.Log;
|
|
|
4
4
|
|
|
5
5
|
import androidx.annotation.NonNull;
|
|
6
6
|
|
|
7
|
-
import com.appoxee.Appoxee;
|
|
8
|
-
import com.appoxee.shared.AppoxeeOptions;
|
|
9
7
|
import com.google.firebase.messaging.FirebaseMessagingService;
|
|
10
8
|
import com.google.firebase.messaging.RemoteMessage;
|
|
11
9
|
|
|
12
|
-
import java.util.concurrent.TimeUnit;
|
|
13
|
-
|
|
14
10
|
|
|
15
11
|
/**
|
|
16
12
|
* Updated for Engage SDK v7:
|
|
@@ -23,36 +19,20 @@ public class MessageService extends FirebaseMessagingService {
|
|
|
23
19
|
@Override
|
|
24
20
|
public void onCreate() {
|
|
25
21
|
super.onCreate();
|
|
26
|
-
|
|
22
|
+
MappPushHelper.initialize(getApplication());
|
|
27
23
|
}
|
|
28
24
|
|
|
29
25
|
@Override
|
|
30
26
|
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
|
|
31
27
|
Log.d("onMessageReceived", remoteMessage.toString());
|
|
32
|
-
if (
|
|
33
|
-
waitInitialization();
|
|
34
|
-
Appoxee.instance().handlePushMessage(remoteMessage);
|
|
35
|
-
} else {
|
|
28
|
+
if (!MappPushHelper.handleMessage(getApplication(), remoteMessage)) {
|
|
36
29
|
super.onMessageReceived(remoteMessage);
|
|
37
30
|
}
|
|
38
31
|
}
|
|
39
32
|
|
|
40
33
|
@Override
|
|
41
34
|
public void onNewToken(@NonNull String token) {
|
|
42
|
-
|
|
43
|
-
Appoxee.instance().updateFirebaseToken(token).enqueue(result -> {});
|
|
35
|
+
MappPushHelper.handleNewToken(getApplication(), token);
|
|
44
36
|
super.onNewToken(token);
|
|
45
37
|
}
|
|
46
|
-
|
|
47
|
-
private void waitInitialization() {
|
|
48
|
-
int limit = 15;
|
|
49
|
-
try {
|
|
50
|
-
while (limit >= 0 && !Appoxee.instance().isReady()) {
|
|
51
|
-
TimeUnit.MILLISECONDS.sleep(300);
|
|
52
|
-
limit--;
|
|
53
|
-
}
|
|
54
|
-
} catch (Exception e) {
|
|
55
|
-
Log.e("MessageService", "waitInitialization interrupted", e);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
38
|
}
|