@react-native-firebase/messaging 25.1.0 → 26.0.0
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/CHANGELOG.md +29 -0
- package/RNFBMessaging.podspec +20 -6
- package/android/build.gradle +24 -0
- package/android/src/main/java/io/invertase/firebase/messaging/{ReactNativeFirebaseMessagingModule.java → NativeRNFBTurboMessaging.java} +143 -81
- package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingPackage.java +1 -1
- package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingReceiver.java +16 -0
- package/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingStoreImpl.java +50 -11
- package/android/src/main/java/io/invertase/firebase/messaging/generated/java/com/facebook/fbreact/specs/NativeRNFBTurboMessagingSpec.java +151 -0
- package/android/src/main/java/io/invertase/firebase/messaging/generated/jni/CMakeLists.txt +36 -0
- package/android/src/main/java/io/invertase/firebase/messaging/generated/jni/RNFBMessagingTurboModules-generated.cpp +152 -0
- package/android/src/main/java/io/invertase/firebase/messaging/generated/jni/RNFBMessagingTurboModules.h +31 -0
- package/android/src/main/java/io/invertase/firebase/messaging/generated/jni/react/renderer/components/RNFBMessagingTurboModules/RNFBMessagingTurboModulesJSI-generated.cpp +161 -0
- package/android/src/main/java/io/invertase/firebase/messaging/generated/jni/react/renderer/components/RNFBMessagingTurboModules/RNFBMessagingTurboModulesJSI.h +356 -0
- package/app.plugin.js +1 -1
- package/dist/module/index.js +622 -7
- package/dist/module/index.js.map +1 -1
- package/dist/module/statics.js +1 -1
- package/dist/module/types/internal.js +4 -0
- package/dist/module/types/internal.js.map +1 -0
- package/dist/module/types/messaging.js +0 -15
- package/dist/module/types/messaging.js.map +1 -1
- package/dist/module/version.js +1 -1
- package/dist/typescript/lib/index.d.ts +182 -5
- package/dist/typescript/lib/index.d.ts.map +1 -1
- package/dist/typescript/lib/types/internal.d.ts +41 -0
- package/dist/typescript/lib/types/internal.d.ts.map +1 -0
- package/dist/typescript/lib/types/messaging.d.ts +7 -55
- package/dist/typescript/lib/types/messaging.d.ts.map +1 -1
- package/dist/typescript/lib/version.d.ts +1 -1
- package/ios/RNFBMessaging/RNFBMessaging+AppDelegate.h +24 -2
- package/ios/RNFBMessaging/RNFBMessaging+AppDelegate.m +82 -12
- package/ios/RNFBMessaging/RNFBMessaging+NSNotificationCenter.m +14 -4
- package/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m +31 -28
- package/ios/RNFBMessaging/RNFBMessagingModule.h +3 -2
- package/ios/RNFBMessaging/RNFBMessagingModule.mm +500 -0
- package/ios/RNFBMessaging.xcodeproj/project.pbxproj +8 -8
- package/ios/generated/RCTAppDependencyProvider.h +25 -0
- package/ios/generated/RCTAppDependencyProvider.mm +55 -0
- package/ios/generated/RCTModulesConformingToProtocolsProvider.h +18 -0
- package/ios/generated/RCTModulesConformingToProtocolsProvider.mm +33 -0
- package/ios/generated/RCTThirdPartyComponentsProvider.h +16 -0
- package/ios/generated/RCTThirdPartyComponentsProvider.mm +23 -0
- package/ios/generated/RNFBMessagingTurboModules/RNFBMessagingTurboModules-generated.mm +184 -0
- package/ios/generated/RNFBMessagingTurboModules/RNFBMessagingTurboModules.h +222 -0
- package/ios/generated/RNFBMessagingTurboModulesJSI-generated.cpp +161 -0
- package/ios/generated/RNFBMessagingTurboModulesJSI.h +356 -0
- package/ios/generated/ReactAppDependencyProvider.podspec +34 -0
- package/lib/index.ts +821 -15
- package/lib/statics.ts +1 -1
- package/lib/types/internal.ts +59 -0
- package/lib/types/messaging.ts +7 -72
- package/lib/version.ts +1 -1
- package/package.json +30 -5
- package/plugin/build/app.plugin.d.ts +2 -0
- package/plugin/build/app.plugin.js +6 -0
- package/plugin/src/app.plugin.ts +3 -0
- package/plugin/tsconfig.tsbuildinfo +1 -1
- package/react-native.config.js +10 -0
- package/specs/NativeRNFBTurboMessaging.ts +46 -0
- package/typedoc.json +2 -19
- package/dist/module/modular.js +0 -396
- package/dist/module/modular.js.map +0 -1
- package/dist/module/namespaced.js +0 -415
- package/dist/module/namespaced.js.map +0 -1
- package/dist/typescript/lib/modular.d.ts +0 -255
- package/dist/typescript/lib/modular.d.ts.map +0 -1
- package/dist/typescript/lib/namespaced.d.ts +0 -12
- package/dist/typescript/lib/namespaced.d.ts.map +0 -1
- package/ios/RNFBMessaging/RNFBMessagingModule.m +0 -439
- package/lib/modular.ts +0 -455
- package/lib/namespaced.ts +0 -593
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,35 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [26.0.0](https://github.com/invertase/react-native-firebase/compare/v25.1.0...v26.0.0) (2026-07-29)
|
|
7
|
+
|
|
8
|
+
### ⚠ BREAKING CHANGES
|
|
9
|
+
|
|
10
|
+
- **messaging, ios:** make APNs registration timeout independent of main queue
|
|
11
|
+
- **messaging:** messaging requires the React Native New Architecture.
|
|
12
|
+
- **app:** App/Core modules native bridge requires New Architecture.
|
|
13
|
+
|
|
14
|
+
Migrate RNFBAppModule and RNFBUtilsModule to Codegen TurboModules with
|
|
15
|
+
unified resolver, lazy Proxy wrapper, and committed generated artifacts.
|
|
16
|
+
Includes functions codegenConfig rename (NewArch-AD-7), test harness
|
|
17
|
+
overrides, architecture decisions, and validation workflow hardening.
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
- **app:** migrate app modules to TurboModules incl general migration infra ([978168d](https://github.com/invertase/react-native-firebase/commit/978168dacecf4925d347d9757eff73ee43e1484f))
|
|
22
|
+
- **messaging:** migrate messaging to TurboModules ([e56c7f4](https://github.com/invertase/react-native-firebase/commit/e56c7f406920a21c07ccd1810b0315ec0953aeff))
|
|
23
|
+
|
|
24
|
+
### Bug Fixes
|
|
25
|
+
|
|
26
|
+
- add ResultT codegen type alias ([ff2d68f](https://github.com/invertase/react-native-firebase/commit/ff2d68ff8f73092f8ba3c75e007049dd31be822f))
|
|
27
|
+
- emit messaging_notification_opened only for default notification action on iOS. ([#8945](https://github.com/invertase/react-native-firebase/issues/8945)) ([2aec61f](https://github.com/invertase/react-native-firebase/commit/2aec61fff6b888f18379b2ba12807fd9d163b8cc))
|
|
28
|
+
- **ios:** private codegen headers and bridging-safe AppCheck module ([266d7e1](https://github.com/invertase/react-native-firebase/commit/266d7e10020662bfd357d1795bc5f6cfde54f7b7))
|
|
29
|
+
- **ios:** set IPHONEOS_DEPLOYMENT_TARGET to 15.0, update platform support docs/conditionals ([#9108](https://github.com/invertase/react-native-firebase/issues/9108)) ([99d0899](https://github.com/invertase/react-native-firebase/commit/99d089908e3eec6155d73ecf05ff7274ad33c46e)), closes [#8882](https://github.com/invertase/react-native-firebase/issues/8882)
|
|
30
|
+
- **messaging, android:** ignore non-message broadcasts in messaging receiver ([#9105](https://github.com/invertase/react-native-firebase/issues/9105)) ([da17208](https://github.com/invertase/react-native-firebase/commit/da1720836622625acdfe8a5f0f870db688348c08)), closes [firebase-android-sdk#5410](https://github.com/invertase/firebase-android-sdk/issues/5410) [#8040](https://github.com/invertase/react-native-firebase/issues/8040)
|
|
31
|
+
- **messaging, android:** make max stored notifications configurable ([#9111](https://github.com/invertase/react-native-firebase/issues/9111)) ([dc5771f](https://github.com/invertase/react-native-firebase/commit/dc5771f75e599db362c2c9916490284734746ec0)), closes [#8771](https://github.com/invertase/react-native-firebase/issues/8771)
|
|
32
|
+
- **messaging, ios:** make APNs registration timeout independent of main queue ([4cbb19c](https://github.com/invertase/react-native-firebase/commit/4cbb19c68d082d2e632c8db134c79160d18aeb02))
|
|
33
|
+
- **messaging:** willPresentNotification custom notification to work alongside default notification ([#9094](https://github.com/invertase/react-native-firebase/issues/9094)) ([1bad118](https://github.com/invertase/react-native-firebase/commit/1bad118f85aadc600757255d1f9ed525b11d655b))
|
|
34
|
+
|
|
6
35
|
## [25.1.0](https://github.com/invertase/react-native-firebase/compare/v25.0.1...v25.1.0) (2026-06-25)
|
|
7
36
|
|
|
8
37
|
**Note:** Version bump only for package @react-native-firebase/messaging
|
package/RNFBMessaging.podspec
CHANGED
|
@@ -10,6 +10,7 @@ if coreVersionDetected != coreVersionRequired
|
|
|
10
10
|
end
|
|
11
11
|
firebase_ios_target = appPackage['sdkVersions']['ios']['iosTarget']
|
|
12
12
|
firebase_macos_target = appPackage['sdkVersions']['ios']['macosTarget']
|
|
13
|
+
firebase_tvos_target = appPackage['sdkVersions']['ios']['tvosTarget']
|
|
13
14
|
|
|
14
15
|
Pod::Spec.new do |s|
|
|
15
16
|
s.name = "RNFBMessaging"
|
|
@@ -25,15 +26,28 @@ Pod::Spec.new do |s|
|
|
|
25
26
|
s.social_media_url = 'http://twitter.com/invertaseio'
|
|
26
27
|
s.ios.deployment_target = firebase_ios_target
|
|
27
28
|
s.macos.deployment_target = firebase_macos_target
|
|
28
|
-
s.
|
|
29
|
+
s.tvos.deployment_target = firebase_tvos_target
|
|
30
|
+
s.source_files = 'ios/**/*.{h,m,mm,cpp,swift}'
|
|
31
|
+
s.public_header_files = [
|
|
32
|
+
'ios/RNFBMessaging/RNFBMessagingModule.h',
|
|
33
|
+
]
|
|
34
|
+
s.private_header_files = [
|
|
35
|
+
'ios/RNFBMessaging/RNFBMessaging+*.h',
|
|
36
|
+
'ios/RNFBMessaging/RNFBMessagingSerializer.h',
|
|
37
|
+
'ios/generated/**/*.h',
|
|
38
|
+
]
|
|
39
|
+
s.exclude_files = 'ios/generated/RCTThirdPartyComponentsProvider.*', 'ios/generated/RCTAppDependencyProvider.*', 'ios/generated/RCTModuleProviders.*', 'ios/generated/RCTModulesConformingToProtocolsProvider.*', 'ios/generated/RCTUnstableModulesRequiringMainQueueSetupProvider.*'
|
|
40
|
+
|
|
41
|
+
s.pod_target_xcconfig = {
|
|
42
|
+
'HEADER_SEARCH_PATHS' => '"$(PODS_TARGET_SRCROOT)/ios/generated/RNFBMessagingTurboModules" "$(PODS_TARGET_SRCROOT)/ios/generated"',
|
|
43
|
+
}
|
|
29
44
|
|
|
30
45
|
s.dependency 'RNFBApp'
|
|
31
46
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
s.dependency "React-Core"
|
|
47
|
+
install_modules_dependencies(s);
|
|
48
|
+
|
|
49
|
+
if defined?(ENV["RCT_NEW_ARCH_ENABLED"]) != nil && (ENV["RCT_NEW_ARCH_ENABLED"] == '0')
|
|
50
|
+
raise "#{s.name} requires New Architecture. Enable New Architecture to use this module"
|
|
37
51
|
end
|
|
38
52
|
|
|
39
53
|
if defined?($FirebaseSDKVersion)
|
package/android/build.gradle
CHANGED
|
@@ -130,6 +130,12 @@ android {
|
|
|
130
130
|
targetCompatibility = JavaVersion.VERSION_11
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
|
+
|
|
134
|
+
sourceSets {
|
|
135
|
+
main {
|
|
136
|
+
java.excludes = ['**/generated/jni/**']
|
|
137
|
+
}
|
|
138
|
+
}
|
|
133
139
|
}
|
|
134
140
|
|
|
135
141
|
repositories {
|
|
@@ -147,3 +153,21 @@ ReactNative.shared.applyPackageVersion()
|
|
|
147
153
|
ReactNative.shared.applyDefaultExcludes()
|
|
148
154
|
ReactNative.module.applyAndroidVersions()
|
|
149
155
|
ReactNative.module.applyReactNativeDependency("api")
|
|
156
|
+
|
|
157
|
+
def isNewArchitectureDisabled() {
|
|
158
|
+
return project.hasProperty("newArchEnabled") && project.newArchEnabled != "true"
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (isNewArchitectureDisabled()) {
|
|
162
|
+
def ANSI_RED = "\u001B[31m";
|
|
163
|
+
def ANSI_RESET = "\u001B[0m";
|
|
164
|
+
|
|
165
|
+
println("\n\n\n")
|
|
166
|
+
println(ANSI_RED + "**************************************************************************************************************")
|
|
167
|
+
println("\n\n\n")
|
|
168
|
+
println("New Architecture support is required for @react-native-firebase/messaging")
|
|
169
|
+
println("\n\n\n")
|
|
170
|
+
println("**************************************************************************************************************" + ANSI_RESET)
|
|
171
|
+
println("\n\n\n")
|
|
172
|
+
System.exit(1)
|
|
173
|
+
}
|
|
@@ -21,10 +21,10 @@ import android.app.Activity;
|
|
|
21
21
|
import android.content.Intent;
|
|
22
22
|
import android.util.Log;
|
|
23
23
|
import androidx.core.app.NotificationManagerCompat;
|
|
24
|
+
import com.facebook.fbreact.specs.NativeRNFBTurboMessagingSpec;
|
|
24
25
|
import com.facebook.react.bridge.ActivityEventListener;
|
|
25
26
|
import com.facebook.react.bridge.Promise;
|
|
26
27
|
import com.facebook.react.bridge.ReactApplicationContext;
|
|
27
|
-
import com.facebook.react.bridge.ReactMethod;
|
|
28
28
|
import com.facebook.react.bridge.ReadableMap;
|
|
29
29
|
import com.facebook.react.bridge.WritableMap;
|
|
30
30
|
import com.facebook.react.bridge.WritableNativeMap;
|
|
@@ -34,20 +34,29 @@ import com.google.firebase.messaging.FirebaseMessaging;
|
|
|
34
34
|
import com.google.firebase.messaging.RemoteMessage;
|
|
35
35
|
import io.invertase.firebase.common.ReactNativeFirebaseEventEmitter;
|
|
36
36
|
import io.invertase.firebase.common.ReactNativeFirebaseModule;
|
|
37
|
+
import io.invertase.firebase.common.TaskExecutorService;
|
|
37
38
|
import java.util.HashMap;
|
|
38
39
|
import java.util.Map;
|
|
40
|
+
import java.util.concurrent.ExecutorService;
|
|
41
|
+
import javax.annotation.Nullable;
|
|
39
42
|
|
|
40
|
-
public class
|
|
43
|
+
public class NativeRNFBTurboMessaging extends NativeRNFBTurboMessagingSpec
|
|
41
44
|
implements ActivityEventListener {
|
|
42
45
|
private static final String TAG = "Messaging";
|
|
43
46
|
ReadableMap initialNotification = null;
|
|
44
|
-
private HashMap<String, Boolean> initialNotificationMap = new HashMap<>();
|
|
47
|
+
private final HashMap<String, Boolean> initialNotificationMap = new HashMap<>();
|
|
48
|
+
private final TaskExecutorService executorService;
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
super(reactContext
|
|
50
|
+
public NativeRNFBTurboMessaging(ReactApplicationContext reactContext) {
|
|
51
|
+
super(reactContext);
|
|
52
|
+
executorService = new TaskExecutorService("NativeRNFBTurboMessaging");
|
|
48
53
|
reactContext.addActivityEventListener(this);
|
|
49
54
|
}
|
|
50
55
|
|
|
56
|
+
private ExecutorService getExecutor() {
|
|
57
|
+
return executorService.getExecutor();
|
|
58
|
+
}
|
|
59
|
+
|
|
51
60
|
private WritableMap popRemoteMessageMapFromMessagingStore(String messageId) {
|
|
52
61
|
ReactNativeFirebaseMessagingStore messagingStore =
|
|
53
62
|
ReactNativeFirebaseMessagingStoreHelper.getInstance().getMessagingStore();
|
|
@@ -56,54 +65,110 @@ public class ReactNativeFirebaseMessagingModule extends ReactNativeFirebaseModul
|
|
|
56
65
|
return remoteMessageMap;
|
|
57
66
|
}
|
|
58
67
|
|
|
59
|
-
@
|
|
68
|
+
@Override
|
|
69
|
+
protected Map<String, Object> getTypedExportedConstants() {
|
|
70
|
+
final Map<String, Object> constants = new HashMap<>();
|
|
71
|
+
constants.put("isAutoInitEnabled", FirebaseMessaging.getInstance().isAutoInitEnabled());
|
|
72
|
+
constants.put(
|
|
73
|
+
"isDeliveryMetricsExportToBigQueryEnabled",
|
|
74
|
+
FirebaseMessaging.getInstance().deliveryMetricsExportToBigQueryEnabled());
|
|
75
|
+
constants.put(
|
|
76
|
+
"isNotificationDelegationEnabled",
|
|
77
|
+
FirebaseMessaging.getInstance().isNotificationDelegationEnabled());
|
|
78
|
+
return constants;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@Override
|
|
82
|
+
public void getDidOpenSettingsForNotification(Promise promise) {
|
|
83
|
+
promise.resolve(false);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@Override
|
|
87
|
+
public void signalBackgroundMessageHandlerSet() {
|
|
88
|
+
// iOS-only; no-op on Android
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@Override
|
|
92
|
+
public void completeNotificationProcessing() {
|
|
93
|
+
// iOS-only; no-op on Android
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@Override
|
|
97
|
+
public void getAPNSToken(Promise promise) {
|
|
98
|
+
promise.resolve(null);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@Override
|
|
102
|
+
public void setAPNSToken(String token, @Nullable String type, Promise promise) {
|
|
103
|
+
promise.resolve(null);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@Override
|
|
107
|
+
public void getIsHeadless(Promise promise) {
|
|
108
|
+
promise.resolve(false);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@Override
|
|
112
|
+
public void requestPermission(ReadableMap permissions, Promise promise) {
|
|
113
|
+
promise.resolve(1);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@Override
|
|
117
|
+
public void registerForRemoteNotifications(Promise promise) {
|
|
118
|
+
promise.resolve(null);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@Override
|
|
122
|
+
public void unregisterForRemoteNotifications(Promise promise) {
|
|
123
|
+
promise.resolve(null);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@Override
|
|
60
127
|
public void getInitialNotification(Promise promise) {
|
|
61
128
|
if (initialNotification != null) {
|
|
62
129
|
promise.resolve(initialNotification);
|
|
63
130
|
initialNotification = null;
|
|
64
131
|
return;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
Activity activity = getCurrentActivity();
|
|
135
|
+
|
|
136
|
+
if (activity != null) {
|
|
137
|
+
Intent intent = activity.getIntent();
|
|
138
|
+
|
|
139
|
+
if (intent != null && intent.getExtras() != null) {
|
|
140
|
+
String messageId = intent.getExtras().getString("google.message_id");
|
|
141
|
+
if (messageId == null) messageId = intent.getExtras().getString("message_id");
|
|
142
|
+
|
|
143
|
+
if (messageId != null && initialNotificationMap.get(messageId) == null) {
|
|
144
|
+
WritableMap remoteMessageMap;
|
|
145
|
+
RemoteMessage remoteMessage =
|
|
146
|
+
ReactNativeFirebaseMessagingReceiver.notifications.get(messageId);
|
|
147
|
+
if (remoteMessage == null) {
|
|
148
|
+
remoteMessageMap = popRemoteMessageMapFromMessagingStore(messageId);
|
|
149
|
+
} else {
|
|
150
|
+
remoteMessageMap =
|
|
151
|
+
ReactNativeFirebaseMessagingSerializer.remoteMessageToWritableMap(remoteMessage);
|
|
152
|
+
}
|
|
153
|
+
if (remoteMessageMap != null) {
|
|
154
|
+
promise.resolve(remoteMessageMap);
|
|
155
|
+
initialNotificationMap.put(messageId, true);
|
|
156
|
+
return;
|
|
92
157
|
}
|
|
93
158
|
}
|
|
94
|
-
} else {
|
|
95
|
-
Log.w(
|
|
96
|
-
TAG,
|
|
97
|
-
"Attempt to call getInitialNotification failed. The current activity is not ready, try"
|
|
98
|
-
+ " calling the method later in the React lifecycle.");
|
|
99
159
|
}
|
|
160
|
+
} else {
|
|
161
|
+
Log.w(
|
|
162
|
+
TAG,
|
|
163
|
+
"Attempt to call getInitialNotification failed. The current activity is not ready, try"
|
|
164
|
+
+ " calling the method later in the React lifecycle.");
|
|
100
165
|
}
|
|
101
166
|
|
|
102
167
|
promise.resolve(null);
|
|
103
168
|
}
|
|
104
169
|
|
|
105
|
-
@
|
|
106
|
-
public void setAutoInitEnabled(
|
|
170
|
+
@Override
|
|
171
|
+
public void setAutoInitEnabled(boolean enabled, Promise promise) {
|
|
107
172
|
Tasks.call(
|
|
108
173
|
getExecutor(),
|
|
109
174
|
() -> {
|
|
@@ -115,31 +180,29 @@ public class ReactNativeFirebaseMessagingModule extends ReactNativeFirebaseModul
|
|
|
115
180
|
if (task.isSuccessful()) {
|
|
116
181
|
promise.resolve(FirebaseMessaging.getInstance().isAutoInitEnabled());
|
|
117
182
|
} else {
|
|
118
|
-
rejectPromiseWithExceptionMap(
|
|
183
|
+
ReactNativeFirebaseModule.rejectPromiseWithExceptionMap(
|
|
184
|
+
promise, task.getException());
|
|
119
185
|
}
|
|
120
186
|
});
|
|
121
187
|
}
|
|
122
188
|
|
|
123
|
-
@
|
|
189
|
+
@Override
|
|
124
190
|
public void isNotificationDelegationEnabled(Promise promise) {
|
|
125
191
|
Tasks.call(
|
|
126
|
-
getExecutor(),
|
|
127
|
-
() -> {
|
|
128
|
-
FirebaseMessaging.getInstance().isNotificationDelegationEnabled();
|
|
129
|
-
return null;
|
|
130
|
-
})
|
|
192
|
+
getExecutor(), () -> FirebaseMessaging.getInstance().isNotificationDelegationEnabled())
|
|
131
193
|
.addOnCompleteListener(
|
|
132
194
|
task -> {
|
|
133
195
|
if (task.isSuccessful()) {
|
|
134
196
|
promise.resolve(task.getResult());
|
|
135
197
|
} else {
|
|
136
|
-
rejectPromiseWithExceptionMap(
|
|
198
|
+
ReactNativeFirebaseModule.rejectPromiseWithExceptionMap(
|
|
199
|
+
promise, task.getException());
|
|
137
200
|
}
|
|
138
201
|
});
|
|
139
202
|
}
|
|
140
203
|
|
|
141
|
-
@
|
|
142
|
-
public void setNotificationDelegationEnabled(
|
|
204
|
+
@Override
|
|
205
|
+
public void setNotificationDelegationEnabled(boolean enabled, Promise promise) {
|
|
143
206
|
Tasks.call(
|
|
144
207
|
getExecutor(),
|
|
145
208
|
() -> {
|
|
@@ -151,12 +214,13 @@ public class ReactNativeFirebaseMessagingModule extends ReactNativeFirebaseModul
|
|
|
151
214
|
if (task.isSuccessful()) {
|
|
152
215
|
promise.resolve(FirebaseMessaging.getInstance().isNotificationDelegationEnabled());
|
|
153
216
|
} else {
|
|
154
|
-
rejectPromiseWithExceptionMap(
|
|
217
|
+
ReactNativeFirebaseModule.rejectPromiseWithExceptionMap(
|
|
218
|
+
promise, task.getException());
|
|
155
219
|
}
|
|
156
220
|
});
|
|
157
221
|
}
|
|
158
222
|
|
|
159
|
-
@
|
|
223
|
+
@Override
|
|
160
224
|
public void getToken(String appName, String senderId, Promise promise) {
|
|
161
225
|
FirebaseMessaging messagingInstance =
|
|
162
226
|
FirebaseApp.getInstance(appName).get(FirebaseMessaging.class);
|
|
@@ -166,12 +230,13 @@ public class ReactNativeFirebaseMessagingModule extends ReactNativeFirebaseModul
|
|
|
166
230
|
if (task.isSuccessful()) {
|
|
167
231
|
promise.resolve(task.getResult());
|
|
168
232
|
} else {
|
|
169
|
-
rejectPromiseWithExceptionMap(
|
|
233
|
+
ReactNativeFirebaseModule.rejectPromiseWithExceptionMap(
|
|
234
|
+
promise, task.getException());
|
|
170
235
|
}
|
|
171
236
|
});
|
|
172
237
|
}
|
|
173
238
|
|
|
174
|
-
@
|
|
239
|
+
@Override
|
|
175
240
|
public void deleteToken(String appName, String senderId, Promise promise) {
|
|
176
241
|
FirebaseMessaging messagingInstance =
|
|
177
242
|
FirebaseApp.getInstance(appName).get(FirebaseMessaging.class);
|
|
@@ -186,12 +251,13 @@ public class ReactNativeFirebaseMessagingModule extends ReactNativeFirebaseModul
|
|
|
186
251
|
if (task.isSuccessful()) {
|
|
187
252
|
promise.resolve(task.getResult());
|
|
188
253
|
} else {
|
|
189
|
-
rejectPromiseWithExceptionMap(
|
|
254
|
+
ReactNativeFirebaseModule.rejectPromiseWithExceptionMap(
|
|
255
|
+
promise, task.getException());
|
|
190
256
|
}
|
|
191
257
|
});
|
|
192
258
|
}
|
|
193
259
|
|
|
194
|
-
@
|
|
260
|
+
@Override
|
|
195
261
|
public void hasPermission(Promise promise) {
|
|
196
262
|
Tasks.call(
|
|
197
263
|
getExecutor(),
|
|
@@ -203,12 +269,13 @@ public class ReactNativeFirebaseMessagingModule extends ReactNativeFirebaseModul
|
|
|
203
269
|
if (task.isSuccessful()) {
|
|
204
270
|
promise.resolve(task.getResult() ? 1 : 0);
|
|
205
271
|
} else {
|
|
206
|
-
rejectPromiseWithExceptionMap(
|
|
272
|
+
ReactNativeFirebaseModule.rejectPromiseWithExceptionMap(
|
|
273
|
+
promise, task.getException());
|
|
207
274
|
}
|
|
208
275
|
});
|
|
209
276
|
}
|
|
210
277
|
|
|
211
|
-
@
|
|
278
|
+
@Override
|
|
212
279
|
public void sendMessage(ReadableMap remoteMessageMap, Promise promise) {
|
|
213
280
|
Tasks.call(
|
|
214
281
|
getExecutor(),
|
|
@@ -224,12 +291,13 @@ public class ReactNativeFirebaseMessagingModule extends ReactNativeFirebaseModul
|
|
|
224
291
|
if (task.isSuccessful()) {
|
|
225
292
|
promise.resolve(task.getResult());
|
|
226
293
|
} else {
|
|
227
|
-
rejectPromiseWithExceptionMap(
|
|
294
|
+
ReactNativeFirebaseModule.rejectPromiseWithExceptionMap(
|
|
295
|
+
promise, task.getException());
|
|
228
296
|
}
|
|
229
297
|
});
|
|
230
298
|
}
|
|
231
299
|
|
|
232
|
-
@
|
|
300
|
+
@Override
|
|
233
301
|
public void subscribeToTopic(String topic, Promise promise) {
|
|
234
302
|
FirebaseMessaging.getInstance()
|
|
235
303
|
.subscribeToTopic(topic)
|
|
@@ -238,12 +306,13 @@ public class ReactNativeFirebaseMessagingModule extends ReactNativeFirebaseModul
|
|
|
238
306
|
if (task.isSuccessful()) {
|
|
239
307
|
promise.resolve(task.getResult());
|
|
240
308
|
} else {
|
|
241
|
-
rejectPromiseWithExceptionMap(
|
|
309
|
+
ReactNativeFirebaseModule.rejectPromiseWithExceptionMap(
|
|
310
|
+
promise, task.getException());
|
|
242
311
|
}
|
|
243
312
|
});
|
|
244
313
|
}
|
|
245
314
|
|
|
246
|
-
@
|
|
315
|
+
@Override
|
|
247
316
|
public void unsubscribeFromTopic(String topic, Promise promise) {
|
|
248
317
|
FirebaseMessaging.getInstance()
|
|
249
318
|
.unsubscribeFromTopic(topic)
|
|
@@ -252,13 +321,14 @@ public class ReactNativeFirebaseMessagingModule extends ReactNativeFirebaseModul
|
|
|
252
321
|
if (task.isSuccessful()) {
|
|
253
322
|
promise.resolve(task.getResult());
|
|
254
323
|
} else {
|
|
255
|
-
rejectPromiseWithExceptionMap(
|
|
324
|
+
ReactNativeFirebaseModule.rejectPromiseWithExceptionMap(
|
|
325
|
+
promise, task.getException());
|
|
256
326
|
}
|
|
257
327
|
});
|
|
258
328
|
}
|
|
259
329
|
|
|
260
|
-
@
|
|
261
|
-
public void setDeliveryMetricsExportToBigQuery(
|
|
330
|
+
@Override
|
|
331
|
+
public void setDeliveryMetricsExportToBigQuery(boolean enabled, Promise promise) {
|
|
262
332
|
Tasks.call(
|
|
263
333
|
getExecutor(),
|
|
264
334
|
() -> {
|
|
@@ -271,24 +341,12 @@ public class ReactNativeFirebaseMessagingModule extends ReactNativeFirebaseModul
|
|
|
271
341
|
promise.resolve(
|
|
272
342
|
FirebaseMessaging.getInstance().deliveryMetricsExportToBigQueryEnabled());
|
|
273
343
|
} else {
|
|
274
|
-
rejectPromiseWithExceptionMap(
|
|
344
|
+
ReactNativeFirebaseModule.rejectPromiseWithExceptionMap(
|
|
345
|
+
promise, task.getException());
|
|
275
346
|
}
|
|
276
347
|
});
|
|
277
348
|
}
|
|
278
349
|
|
|
279
|
-
@Override
|
|
280
|
-
public Map<String, Object> getConstants() {
|
|
281
|
-
final Map<String, Object> constants = new HashMap<>();
|
|
282
|
-
constants.put("isAutoInitEnabled", FirebaseMessaging.getInstance().isAutoInitEnabled());
|
|
283
|
-
constants.put(
|
|
284
|
-
"isDeliveryMetricsExportToBigQueryEnabled",
|
|
285
|
-
FirebaseMessaging.getInstance().deliveryMetricsExportToBigQueryEnabled());
|
|
286
|
-
constants.put(
|
|
287
|
-
"isNotificationDelegationEnabled",
|
|
288
|
-
FirebaseMessaging.getInstance().isNotificationDelegationEnabled());
|
|
289
|
-
return constants;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
350
|
@Override
|
|
293
351
|
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
|
|
294
352
|
// noop
|
|
@@ -313,8 +371,6 @@ public class ReactNativeFirebaseMessagingModule extends ReactNativeFirebaseModul
|
|
|
313
371
|
}
|
|
314
372
|
|
|
315
373
|
if (remoteMessageMap != null) {
|
|
316
|
-
// WritableNativeMap not be consumed twice. But it is resolved in future and in event
|
|
317
|
-
// below. Make a copy - issue #5231
|
|
318
374
|
WritableNativeMap newInitialNotification = new WritableNativeMap();
|
|
319
375
|
newInitialNotification.merge(remoteMessageMap);
|
|
320
376
|
initialNotification = newInitialNotification;
|
|
@@ -329,4 +385,10 @@ public class ReactNativeFirebaseMessagingModule extends ReactNativeFirebaseModul
|
|
|
329
385
|
}
|
|
330
386
|
}
|
|
331
387
|
}
|
|
388
|
+
|
|
389
|
+
@Override
|
|
390
|
+
public void invalidate() {
|
|
391
|
+
super.invalidate();
|
|
392
|
+
executorService.shutdown();
|
|
393
|
+
}
|
|
332
394
|
}
|
|
@@ -30,7 +30,7 @@ public class ReactNativeFirebaseMessagingPackage implements ReactPackage {
|
|
|
30
30
|
@Override
|
|
31
31
|
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
|
|
32
32
|
List<NativeModule> modules = new ArrayList<>();
|
|
33
|
-
modules.add(new
|
|
33
|
+
modules.add(new NativeRNFBTurboMessaging(reactContext));
|
|
34
34
|
return modules;
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -26,6 +26,22 @@ public class ReactNativeFirebaseMessagingReceiver extends BroadcastReceiver {
|
|
|
26
26
|
Log.e(TAG, "broadcast intent received with no extras");
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
|
+
// Mirror the routing guards of the official FirebaseMessagingService: the
|
|
30
|
+
// c2dm RECEIVE action also carries control broadcasts (deleted_messages,
|
|
31
|
+
// send_event, send_error) and non-message intents such as the wrapped
|
|
32
|
+
// NOTIFICATION_DISMISS analytics intent that FCM attaches as deleteIntent
|
|
33
|
+
// to notifications it displays itself. The official SDK routes those to
|
|
34
|
+
// dedicated callbacks and never surfaces them through onMessageReceived;
|
|
35
|
+
// without these guards they are emitted to JS as empty remote messages.
|
|
36
|
+
String messageType = intent.getStringExtra("message_type");
|
|
37
|
+
if (messageType != null && !"gcm".equals(messageType)) {
|
|
38
|
+
Log.d(TAG, "broadcast ignored, non-message type: " + messageType);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (intent.getStringExtra("google.message_id") == null) {
|
|
42
|
+
Log.d(TAG, "broadcast ignored, no google.message_id (not an FCM message)");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
29
45
|
RemoteMessage remoteMessage = new RemoteMessage(intent.getExtras());
|
|
30
46
|
ReactNativeFirebaseEventEmitter emitter = ReactNativeFirebaseEventEmitter.getSharedInstance();
|
|
31
47
|
|
|
@@ -5,9 +5,13 @@ import static io.invertase.firebase.messaging.JsonConvert.reactToJSON;
|
|
|
5
5
|
import static io.invertase.firebase.messaging.ReactNativeFirebaseMessagingSerializer.remoteMessageFromReadableMap;
|
|
6
6
|
import static io.invertase.firebase.messaging.ReactNativeFirebaseMessagingSerializer.remoteMessageToWritableMap;
|
|
7
7
|
|
|
8
|
+
import android.util.Log;
|
|
8
9
|
import com.facebook.react.bridge.ReadableMap;
|
|
9
10
|
import com.facebook.react.bridge.WritableMap;
|
|
10
11
|
import com.google.firebase.messaging.RemoteMessage;
|
|
12
|
+
import io.invertase.firebase.common.ReactNativeFirebaseJSON;
|
|
13
|
+
import io.invertase.firebase.common.ReactNativeFirebaseMeta;
|
|
14
|
+
import io.invertase.firebase.common.ReactNativeFirebasePreferences;
|
|
11
15
|
import io.invertase.firebase.common.UniversalFirebasePreferences;
|
|
12
16
|
import java.util.ArrayList;
|
|
13
17
|
import java.util.Arrays;
|
|
@@ -17,31 +21,68 @@ import org.json.JSONObject;
|
|
|
17
21
|
|
|
18
22
|
public class ReactNativeFirebaseMessagingStoreImpl implements ReactNativeFirebaseMessagingStore {
|
|
19
23
|
|
|
24
|
+
private static final String TAG = "RNFirebaseMsgStore";
|
|
25
|
+
private static final String KEY_MAX_STORED_NOTIFICATIONS = "messaging_max_stored_notifications";
|
|
20
26
|
private static final String S_KEY_ALL_NOTIFICATION_IDS = "all_notification_ids";
|
|
21
|
-
private static final int
|
|
27
|
+
private static final int DEFAULT_MAX_SIZE_NOTIFICATIONS = 100;
|
|
22
28
|
private final String DELIMITER = ",";
|
|
29
|
+
private static volatile int maxNotificationSize = -1;
|
|
30
|
+
|
|
31
|
+
private static int resolveMaxNotificationSize() {
|
|
32
|
+
int maxSize = DEFAULT_MAX_SIZE_NOTIFICATIONS;
|
|
33
|
+
String source = "default";
|
|
34
|
+
ReactNativeFirebaseJSON json = ReactNativeFirebaseJSON.getSharedInstance();
|
|
35
|
+
ReactNativeFirebaseMeta meta = ReactNativeFirebaseMeta.getSharedInstance();
|
|
36
|
+
ReactNativeFirebasePreferences prefs = ReactNativeFirebasePreferences.getSharedInstance();
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
if (prefs.contains(KEY_MAX_STORED_NOTIFICATIONS)) {
|
|
40
|
+
maxSize = prefs.getIntValue(KEY_MAX_STORED_NOTIFICATIONS, DEFAULT_MAX_SIZE_NOTIFICATIONS);
|
|
41
|
+
source = "SharedPreferences";
|
|
42
|
+
} else if (json.contains(KEY_MAX_STORED_NOTIFICATIONS)) {
|
|
43
|
+
maxSize = json.getIntValue(KEY_MAX_STORED_NOTIFICATIONS, DEFAULT_MAX_SIZE_NOTIFICATIONS);
|
|
44
|
+
source = "firebase.json";
|
|
45
|
+
} else if (meta.contains(KEY_MAX_STORED_NOTIFICATIONS)) {
|
|
46
|
+
maxSize = meta.getIntValue(KEY_MAX_STORED_NOTIFICATIONS, DEFAULT_MAX_SIZE_NOTIFICATIONS);
|
|
47
|
+
source = "AndroidManifest";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
Log.d(TAG, "messaging_max_stored_notifications: " + maxSize + " (from " + source + ")");
|
|
51
|
+
return maxSize;
|
|
52
|
+
} catch (Exception e) {
|
|
53
|
+
Log.w(
|
|
54
|
+
TAG,
|
|
55
|
+
"Error resolving max notification size, using default: " + DEFAULT_MAX_SIZE_NOTIFICATIONS,
|
|
56
|
+
e);
|
|
57
|
+
return DEFAULT_MAX_SIZE_NOTIFICATIONS;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private static int getMaxNotificationSize() {
|
|
62
|
+
if (maxNotificationSize == -1) {
|
|
63
|
+
maxNotificationSize = resolveMaxNotificationSize();
|
|
64
|
+
}
|
|
65
|
+
return maxNotificationSize;
|
|
66
|
+
}
|
|
23
67
|
|
|
24
68
|
@Override
|
|
25
69
|
public void storeFirebaseMessage(RemoteMessage remoteMessage) {
|
|
26
70
|
try {
|
|
27
71
|
String remoteMessageString =
|
|
28
72
|
reactToJSON(remoteMessageToWritableMap(remoteMessage)).toString();
|
|
29
|
-
// Log.d("storeFirebaseMessage", remoteMessageString);
|
|
30
73
|
UniversalFirebasePreferences preferences = UniversalFirebasePreferences.getSharedInstance();
|
|
31
74
|
|
|
32
|
-
|
|
75
|
+
int limit = getMaxNotificationSize();
|
|
33
76
|
String notificationIds = preferences.getStringValue(S_KEY_ALL_NOTIFICATION_IDS, "");
|
|
34
77
|
List<String> allNotificationList = convertToArray(notificationIds);
|
|
35
|
-
while (allNotificationList.size() >
|
|
78
|
+
while (allNotificationList.size() > limit - 1) {
|
|
36
79
|
clearFirebaseMessage(allNotificationList.get(0));
|
|
37
80
|
allNotificationList.remove(0);
|
|
38
81
|
}
|
|
39
82
|
|
|
40
|
-
// now refetch the ids after possible removals, and store the new message
|
|
41
83
|
notificationIds = preferences.getStringValue(S_KEY_ALL_NOTIFICATION_IDS, "");
|
|
42
84
|
preferences.setStringValue(remoteMessage.getMessageId(), remoteMessageString);
|
|
43
|
-
|
|
44
|
-
notificationIds += remoteMessage.getMessageId() + DELIMITER; // append to last
|
|
85
|
+
notificationIds += remoteMessage.getMessageId() + DELIMITER;
|
|
45
86
|
preferences.setStringValue(S_KEY_ALL_NOTIFICATION_IDS, notificationIds);
|
|
46
87
|
} catch (JSONException e) {
|
|
47
88
|
e.printStackTrace();
|
|
@@ -63,10 +104,9 @@ public class ReactNativeFirebaseMessagingStoreImpl implements ReactNativeFirebas
|
|
|
63
104
|
String remoteMessageString =
|
|
64
105
|
UniversalFirebasePreferences.getSharedInstance().getStringValue(remoteMessageId, null);
|
|
65
106
|
if (remoteMessageString != null) {
|
|
66
|
-
// Log.d("getFirebaseMessage", remoteMessageString);
|
|
67
107
|
try {
|
|
68
108
|
WritableMap remoteMessageMap = jsonToReact(new JSONObject(remoteMessageString));
|
|
69
|
-
remoteMessageMap.putString("to", remoteMessageId);
|
|
109
|
+
remoteMessageMap.putString("to", remoteMessageId);
|
|
70
110
|
return remoteMessageMap;
|
|
71
111
|
} catch (JSONException e) {
|
|
72
112
|
e.printStackTrace();
|
|
@@ -79,10 +119,9 @@ public class ReactNativeFirebaseMessagingStoreImpl implements ReactNativeFirebas
|
|
|
79
119
|
public void clearFirebaseMessage(String remoteMessageId) {
|
|
80
120
|
UniversalFirebasePreferences preferences = UniversalFirebasePreferences.getSharedInstance();
|
|
81
121
|
preferences.remove(remoteMessageId).apply();
|
|
82
|
-
// check and remove old notifications message
|
|
83
122
|
String notificationIds = preferences.getStringValue(S_KEY_ALL_NOTIFICATION_IDS, "");
|
|
84
123
|
if (!notificationIds.isEmpty()) {
|
|
85
|
-
notificationIds = removeRemoteMessageId(remoteMessageId, notificationIds);
|
|
124
|
+
notificationIds = removeRemoteMessageId(remoteMessageId, notificationIds);
|
|
86
125
|
preferences.setStringValue(S_KEY_ALL_NOTIFICATION_IDS, notificationIds);
|
|
87
126
|
}
|
|
88
127
|
}
|