├── .gitattributes
├── .gitignore
├── App.tsx
├── LICENSE
├── NotifeeApp.tsx
├── README.md
├── index.js
├── make-demo.sh
├── notifee-demo.sh
├── patches
├── .gitkeep
└── @react-native-community+cli-platform-apple+18.0.0.patch
└── rnfbdemo.entitlements
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 |
3 | *.sh text eol=lf
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 | project.xcworkspace
24 | ios/pods/
25 |
26 | # Android/IntelliJ
27 | #
28 | build/
29 | .idea
30 | .gradle
31 | local.properties
32 | *.iml
33 | android/app/src/main/assets
34 | android/app/src/main/res/drawable-mdpi
35 |
36 | # node.js
37 | #
38 | node_modules/
39 | npm-debug.log
40 | yarn-error.log
41 |
42 | # BUCK
43 | buck-out/
44 | \.buckd/
45 | *.keystore
46 |
47 | # fastlane
48 | #
49 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
50 | # screenshots whenever they are needed.
51 | # For more information about the recommended setup visit:
52 | # https://docs.fastlane.tools/best-practices/source-control/
53 |
54 | */fastlane/report.xml
55 | */fastlane/Preview.html
56 | */fastlane/screenshots
57 |
58 | # Bundle artifact
59 | *.jsbundle
60 |
61 | # Firebase
62 | google-services.json*
63 | GoogleService-Info.plist*
64 |
65 | # Example
66 | rnfbdemo
67 | notifeedemo
68 | notifeewebdemo
--------------------------------------------------------------------------------
/App.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Sample React Native App
3 | * https://github.com/facebook/react-native
4 | *
5 | * @format
6 | */
7 |
8 | import React, {useEffect, useState} from 'react';
9 | import type {PropsWithChildren} from 'react';
10 | import {
11 | Button,
12 | SafeAreaView,
13 | ScrollView,
14 | StatusBar,
15 | StyleSheet,
16 | Text,
17 | useColorScheme,
18 | View,
19 | } from 'react-native';
20 |
21 | import {Colors, Header} from 'react-native/Libraries/NewAppScreen';
22 |
23 | import {getApp, getApps} from '@react-native-firebase/app';
24 | import {getAnalytics} from '@react-native-firebase/analytics';
25 | import appCheck, {initializeAppCheck} from '@react-native-firebase/app-check';
26 | import {getAppDistribution} from '@react-native-firebase/app-distribution';
27 | import {
28 | connectAuthEmulator,
29 | FirebaseAuthTypes,
30 | getAuth,
31 | onAuthStateChanged,
32 | signInAnonymously,
33 | signOut,
34 | } from '@react-native-firebase/auth';
35 | import {getCrashlytics} from '@react-native-firebase/crashlytics';
36 | import {getDatabase} from '@react-native-firebase/database';
37 | import {getDynamicLinks} from '@react-native-firebase/dynamic-links';
38 | import {getFirestore} from '@react-native-firebase/firestore';
39 | import {getFunctions} from '@react-native-firebase/functions';
40 | import {getInAppMessaging} from '@react-native-firebase/in-app-messaging';
41 | import {getInstallations} from '@react-native-firebase/installations';
42 | import {
43 | getMessaging,
44 | getToken,
45 | isDeviceRegisteredForRemoteMessages,
46 | onMessage,
47 | registerDeviceForRemoteMessages,
48 | requestPermission,
49 | } from '@react-native-firebase/messaging';
50 | import {getPerformance} from '@react-native-firebase/perf';
51 | import {getRemoteConfig} from '@react-native-firebase/remote-config';
52 | import {getStorage} from '@react-native-firebase/storage';
53 | import {getVertexAI} from '@react-native-firebase/vertexai';
54 |
55 | type SectionProps = PropsWithChildren<{
56 | title: string;
57 | }>;
58 |
59 | function Section({children, title}: SectionProps): JSX.Element {
60 | const isDarkMode = useColorScheme() === 'dark';
61 | return (
62 |
63 |
70 | {title}
71 |
72 |
79 | {children}
80 |
81 |
82 | );
83 | }
84 |
85 | onMessage(getMessaging(), message => {
86 | console.log('messaging.onMessage received: ' + JSON.stringify(message));
87 | });
88 |
89 | connectAuthEmulator(getAuth(), 'http://localhost:9099');
90 |
91 | onAuthStateChanged(getAuth(), (user: FirebaseAuthTypes.User) => {
92 | console.log(
93 | 'onAuthStateChanged was called with user uid ' + (user?.uid ?? '(no user)'),
94 | );
95 | });
96 |
97 | function App(): JSX.Element {
98 | const isDarkMode = useColorScheme() === 'dark';
99 | const [appCheckPresent, setAppCheckPresent] = useState(false);
100 |
101 | useEffect(() => {
102 | console.log('initializating AppCheck...');
103 | const rnfbProvider = appCheck().newReactNativeFirebaseAppCheckProvider();
104 | rnfbProvider.configure({
105 | android: {
106 | provider: __DEV__ ? 'debug' : 'playIntegrity',
107 | debugToken: 'invalid debug token',
108 | },
109 | apple: {
110 | provider: __DEV__ ? 'debug' : 'appAttestWithDeviceCheckFallback',
111 | debugToken: 'invalid debug token',
112 | },
113 | web: {
114 | provider: 'reCaptchaV3',
115 | siteKey: 'unknown',
116 | },
117 | });
118 | initializeAppCheck(getApp(), {provider: rnfbProvider}).then(() => {
119 | console.log('AppCheck is initialized.');
120 | setAppCheckPresent(true);
121 | });
122 |
123 | console.log('Requesting basic notification permission');
124 | requestPermission(getMessaging(), {alert: true, badge: true}).then(() =>
125 | console.log('Permission for notifications handled'),
126 | );
127 |
128 | console.log('Initializing messaging for notifications...');
129 | registerDeviceForRemoteMessages(getMessaging())
130 | .then(() =>
131 | console.log(
132 | 'Registered for remote messages: ' +
133 | isDeviceRegisteredForRemoteMessages(getMessaging()),
134 | ),
135 | )
136 | .catch(e =>
137 | console.error('could not register for remote notifications: ' + e),
138 | );
139 | }, []);
140 |
141 | const backgroundStyle = {
142 | backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
143 | };
144 |
145 | const dynStyles = StyleSheet.create({
146 | colors: {
147 | color: isDarkMode ? Colors.white : Colors.black,
148 | },
149 | });
150 |
151 | const sendSilent = async () => {
152 | console.log('sending a silent notification now');
153 | try {
154 | console.log('Getting our token for message send');
155 | const token = await getToken(getMessaging());
156 | console.log('sending a visible notification now');
157 | const fcmRequest = await fetch(
158 | 'https://us-central1-react-native-firebase-testing.cloudfunctions.net/sendFCM',
159 | {
160 | method: 'POST',
161 | headers: {
162 | 'Content-Type': 'application/json',
163 | },
164 | body: JSON.stringify({
165 | data: {
166 | delay: 10000,
167 | message: {
168 | token,
169 | data: {
170 | message: 'hello from data block',
171 | },
172 | apns: {
173 | payload: {
174 | aps: {
175 | 'content-available': 1,
176 | },
177 | },
178 | },
179 | android: {
180 | priority: 'high',
181 | },
182 | },
183 | },
184 | }),
185 | redirect: 'follow',
186 | },
187 | );
188 | console.log('request sent, waiting for response');
189 | const {result} = await fcmRequest.json();
190 | console.log('got sendFCM result: ' + JSON.stringify(result, null, 2));
191 | } catch (e) {
192 | console.error('something went wrong? ' + e);
193 | }
194 | };
195 |
196 | const sendVisible = async () => {
197 | try {
198 | console.log('Getting our token for message send');
199 | const token = await getToken(getMessaging());
200 | console.log('sending a visible notification now');
201 | const fcmRequest = await fetch(
202 | 'https://us-central1-react-native-firebase-testing.cloudfunctions.net/sendFCM',
203 | {
204 | method: 'POST',
205 | headers: {
206 | 'Content-Type': 'application/json',
207 | },
208 | body: JSON.stringify({
209 | data: {
210 | delay: 10000,
211 | message: {
212 | token,
213 | notification: {
214 | title: 'hello world title',
215 | body: 'hello world body',
216 | },
217 | data: {
218 | message: 'hello from data block',
219 | },
220 | },
221 | },
222 | }),
223 | redirect: 'follow',
224 | },
225 | );
226 | console.log('request sent, waiting for response');
227 | const {result} = await fcmRequest.json();
228 | console.log('got sendFCM result: ' + JSON.stringify(result, null, 2));
229 | } catch (e) {
230 | console.error('something went wrong? ' + e);
231 | }
232 | };
233 |
234 | return (
235 |
236 |
240 |
243 |
334 |
335 | );
336 | }
337 |
338 | const styles = StyleSheet.create({
339 | sectionContainer: {
340 | marginTop: 32,
341 | paddingHorizontal: 24,
342 | },
343 | sectionTitle: {
344 | fontSize: 24,
345 | fontWeight: '600',
346 | },
347 | sectionDescription: {
348 | marginTop: 8,
349 | fontSize: 18,
350 | fontWeight: '400',
351 | },
352 | highlight: {
353 | fontWeight: '700',
354 | },
355 | });
356 |
357 | export default App;
358 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/NotifeeApp.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Sample React Native App
3 | * https://github.com/facebook/react-native
4 | *
5 | * @format
6 | * @flow
7 | */
8 |
9 | import React, {useEffect} from 'react';
10 | import {Button, Platform, StyleSheet, Text, View} from 'react-native';
11 | import notifee, {
12 | AndroidLaunchActivityFlag,
13 | AuthorizationStatus,
14 | EventType,
15 | } from '@notifee/react-native';
16 |
17 | notifee.onBackgroundEvent(async ({type, detail}) => {
18 | const {notification, pressAction} = detail;
19 | console.log(
20 | `[onBackgroundEvent] notification id: ${
21 | notification !== undefined ? notification.id : 'undefined'
22 | }, event type: ${EventType[type]}, press action: ${pressAction?.id}`,
23 | );
24 | });
25 |
26 | async function createChannel() {
27 | let channelId = 'default';
28 | try {
29 | channelId = await notifee.createChannel({
30 | id: 'default',
31 | name: 'Default Channel',
32 | });
33 | } catch (e) {
34 | console.log('Unable to create a channel: ', JSON.stringify(e));
35 | }
36 | return channelId;
37 | }
38 |
39 | async function requestPermissions() {
40 | try {
41 | const settings = await notifee.requestPermission();
42 |
43 | if (settings.authorizationStatus === AuthorizationStatus.DENIED) {
44 | console.log('User denied permissions request');
45 | } else if (
46 | settings.authorizationStatus === AuthorizationStatus.AUTHORIZED
47 | ) {
48 | console.log('User granted permissions request');
49 | } else if (
50 | settings.authorizationStatus === AuthorizationStatus.PROVISIONAL
51 | ) {
52 | console.log('User provisionally granted permissions request');
53 | }
54 | } catch (e) {
55 | console.log('Unable to request permissions: ', JSON.stringify(e));
56 | }
57 | }
58 |
59 | async function onDisplayNotification() {
60 | try {
61 | const channelId = await createChannel();
62 | await requestPermissions();
63 |
64 | // Display a notification
65 | await notifee.displayNotification({
66 | title: 'Notification Title',
67 | body: 'Main body content of the notification',
68 | android: {
69 | channelId,
70 | pressAction: {
71 | id: 'default',
72 | launchActivity: 'default',
73 | launchActivityFlags: [AndroidLaunchActivityFlag.SINGLE_TOP],
74 | },
75 | },
76 | });
77 | } catch (e) {
78 | console.log('Failed to display notification?', e);
79 | }
80 | }
81 |
82 | async function setCategories() {
83 | await notifee.setNotificationCategories([
84 | {
85 | id: 'post',
86 | actions: [
87 | {
88 | id: 'like',
89 | title: 'Like Post',
90 | },
91 | {
92 | id: 'dislike',
93 | title: 'Dislike Post',
94 | },
95 | ],
96 | },
97 | ]);
98 | }
99 |
100 | async function onDisplayNotificationWithActions() {
101 | // Create a channel
102 | try {
103 | const channelId = await createChannel();
104 | await requestPermissions();
105 |
106 | // Display a notification
107 | await notifee.displayNotification({
108 | title: 'New post from John',
109 | body: 'Hey everyone! Check out my new blog post on my website.',
110 | ios: {
111 | categoryId: 'post',
112 | },
113 | android: {
114 | channelId,
115 | actions: [
116 | {
117 | title: 'Like',
118 | pressAction: {
119 | id: 'like',
120 | launchActivity: 'default',
121 | launchActivityFlags: [AndroidLaunchActivityFlag.SINGLE_TOP],
122 | },
123 | },
124 | {
125 | title: 'Dislike',
126 | pressAction: {
127 | id: 'dislike',
128 | launchActivity: 'default',
129 | launchActivityFlags: [AndroidLaunchActivityFlag.SINGLE_TOP],
130 | },
131 | },
132 | ],
133 | pressAction: {
134 | id: 'default',
135 | launchActivity: 'default',
136 | launchActivityFlags: [AndroidLaunchActivityFlag.SINGLE_TOP],
137 | },
138 | },
139 | });
140 | } catch (e) {
141 | console.log('Failed to display notification?', e);
142 | }
143 | }
144 |
145 | const instructions = Platform.select({
146 | ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
147 | android:
148 | 'Double tap R on your keyboard to reload,\n' +
149 | 'Shake or press menu button for dev menu',
150 | });
151 |
152 | export default function App() {
153 | useEffect(() => {
154 | setCategories();
155 | return notifee.onForegroundEvent(({type, detail}) => {
156 | const {notification, pressAction} = detail;
157 | const pressActionLabel = pressAction
158 | ? `, press action: ${pressAction?.id}`
159 | : '';
160 | console.log(
161 | `[onForegroundEvent] notification id: ${
162 | notification !== undefined ? notification.id : 'undefined'
163 | }, event type: ${EventType[type]}${pressActionLabel}`,
164 | );
165 |
166 | switch (type) {
167 | case EventType.DISMISSED:
168 | console.log(
169 | '[onForegroundEvent] User dismissed notification',
170 | notification,
171 | );
172 | break;
173 | case EventType.PRESS:
174 | console.log(
175 | '[onForegroundEvent] User pressed notification',
176 | notification,
177 | );
178 | break;
179 | case EventType.ACTION_PRESS:
180 | console.log(
181 | '[onForegroundEvent] User pressed an action',
182 | notification,
183 | detail.pressAction,
184 | );
185 | // On Android the notification does not dismiss automatically if it was an interaction press, so we dismiss it ourselves
186 | console.log(
187 | '[onBackgroundEvent] ACTION_PRESS: cancelling notification',
188 | );
189 | if (notification !== undefined && notification.id !== undefined) {
190 | notifee.cancelNotification(notification.id);
191 | }
192 | break;
193 | }
194 | });
195 | }, []);
196 |
197 | return (
198 |
199 | Notifee React Native Demo
200 | To get started, edit App.js
201 | {instructions}
202 | onDisplayNotification()}
205 | />
206 | onDisplayNotificationWithActions()}
209 | />
210 |
211 | );
212 | }
213 |
214 | const styles = StyleSheet.create({
215 | container: {
216 | flex: 1,
217 | justifyContent: 'center',
218 | alignItems: 'center',
219 | backgroundColor: '#F5FCFF',
220 | },
221 | welcome: {
222 | fontSize: 20,
223 | textAlign: 'center',
224 | margin: 10,
225 | },
226 | instructions: {
227 | textAlign: 'center',
228 | color: '#333333',
229 | marginBottom: 5,
230 | },
231 | });
232 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # rnfb-demo
2 |
3 | Demonstrator App for react-native-firebase - reasonably up to date with current stable versions
4 |
5 | ## Install / use
6 |
7 | ### Windows pre-install steps
8 |
9 | Maintaining the script for both a Unix-style and non-Unix-style is not feasible with time available.
10 | So the way to run this on Windows is to make Windows behave more Unix-style.
11 |
12 | 1. Install "WSL" - the Windows Subsystem For Linux (Ubuntu 20LTS flavor)
13 | 1. Open your Ubuntu WSL shell and install the [Node Version Manager / "nvm"](https://github.com/nvm-sh/nvm/blob/master/README.md#installing-and-updating)
14 | 1. `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.0/install.sh | bash`
15 |
16 | ### macOS / Linux (developed on Ubuntu 20) / Windows WSL steps
17 |
18 | 1. Fork and clone the repo
19 | 1. Make sure yarn is installed (`npm i -g yarn`)
20 | 1. Do the various Config section steps below
21 | 1. run `make-demo.sh`
22 |
23 | ## One-time Configuration steps
24 |
25 | ### Firebase Config
26 |
27 | Go to the Firebase Console, create a new project, and set up demo apps
28 |
29 | 1. Android package name must be 'com.rnfbdemo'
30 | 1. iOS bundle name must be 'com.rnfbdemo'
31 | 1. Download / install the google-services.json for your new rnfbdemo android app to the root of this repo (it will be copied into place)
32 | 1. Drop the Google-services.plist file the root of this repo (it will be copied in to place)
33 |
34 | ### Apple Developer Config
35 |
36 | To test remote notifications while offline, you'll have to do a lot of Apple setup. I'm not going to help anyone with this, sorry, but here are the requirements:
37 |
38 | 1. You must have an developer account with apple
39 | 1. You will need to configure a push notification certificate and key
40 | 1. You will need a provisioning profile with background-fetch and push notifications entitlements
41 | 1. You will need to add that push notification key to your firebase cloud messaging configuration
42 | 1. You might want to make an actual test application so you can distribute it with testflight to test things
43 | 1. You will have to do all that yourself. Maybe create wiki pages in this project to share tips, but Apple/XCode/iOS profile / cert / entitlements issues are not issues for this repo
44 |
45 | ## Current status
46 |
47 | Currently this repo demonstrates:
48 |
49 | 1. How to correctly install and link the most popular modules in a react-native-firebase project
50 | 1. Has a very basic App.js that just shows they were installed correctly so you can see the app boots and loads native modules
51 |
52 | ...and that's it for now, but it's enough to show the basics on what you need to do to integrate react-native-firebase with your project
53 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @format
3 | */
4 |
5 | import {AppRegistry} from 'react-native';
6 | import {
7 | getMessaging,
8 | setBackgroundMessageHandler,
9 | } from '@react-native-firebase/messaging';
10 | import App from './App';
11 | import {name as appName} from './app.json';
12 |
13 | setBackgroundMessageHandler(getMessaging(), async (message) => {
14 | setImmediate(() => {
15 | console.log(
16 | 'This is running from setBackgroundMessageHandler::setImmediate',
17 | );
18 | });
19 |
20 | console.log(
21 | 'setBackgroundMessageHandler JS executing. Received message: ' +
22 | JSON.stringify(message),
23 | );
24 |
25 | // // Display a notification
26 | // await notifee.displayNotification({
27 | // title: 'Notification Title',
28 | // body: 'Main body content of the notification',
29 | // android: {
30 | // channelId: 'misc',
31 | // // pressAction is needed if you want the notification to open the app when pressed
32 | // pressAction: {
33 | // id: 'default',
34 | // },
35 | // },
36 | // });
37 | });
38 |
39 | // notifee.onBackgroundEvent(async event => {
40 | // setImmediate(() => {
41 | // console.log('This is running from notifee.onBacgroundEvent::setImmediate');
42 | // });
43 |
44 | // console.log('notifee.onBackgroundEvent with event: ' + JSON.stringify(event));
45 | // });
46 |
47 | AppRegistry.registerComponent(appName, () => App);
48 |
--------------------------------------------------------------------------------
/make-demo.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | RN_VER=0.79.2
5 | RNFB_VER=22.2.0
6 | FB_IOS_VER=11.14.0
7 | FB_ANDROID_VER=33.14.0
8 | FB_GRADLE_SERVICES_VER=4.4.2 # Test 5.0.0 ?
9 | FB_GRADLE_PERF_VER=1.4.2
10 | FB_GRADLE_CRASH_VER=3.0.3
11 | FB_GRADLE_APP_DIST_VER=5.1.1
12 |
13 | # This should match what you have defined in firebase console, so that
14 | # it matches what is in your google-services.json and GoogleService-Info.plist
15 |
16 | # These will work if you have access to the Invertase Apple Development team,
17 | # If you do not have access to that account and want to test on real devices
18 | # (macCatalyst to you rmac, or a real iOS device) you'll need a bundle ID that
19 | # is unclaimed and your device will need to be registered with the XCODE_DEVELOPMENT_TEAM
20 | # you use
21 | FB_ANDROID_PACKAGE_NAME="com.invertase.testing"
22 | FB_IOS_PACKAGE_NAME="io.invertase.testing"
23 |
24 | #######################################################################################################
25 | #######################################################################################################
26 | # This whole section is test setup, and environment verification, it does not represent integration yet
27 | # Test: We need to verify our environment first, so we fail fast for easily detectable things
28 | if [ "$(uname)" == "Darwin" ]; then
29 | # If the keychain is unlocked then this fails in the middle, let's check that now and fail fast
30 | if ! security show-keychain-info login.keychain > /dev/null 2>&1; then
31 | echo "Login keychain is not unlocked, codesigning will fail so macCatalyst build wll fail."
32 | echo "run 'security unlock-keychain login.keychain' to unlock the login keychain then re-run"
33 | exit 1
34 | fi
35 |
36 | # We do not want to run under Rosetta 2, brew doesn't work and compiles might not work after
37 | arch_name="$(uname -m)"
38 | if [ "${arch_name}" = "x86_64" ]; then
39 | if [ "$(sysctl -in sysctl.proc_translated)" = "1" ]; then
40 | echo "Running on Rosetta 2"
41 | echo "This is not supported. Run \`env /usr/bin/arch -arm64 /bin/bash --login\` then try again"
42 | exit 1
43 | else
44 | echo "Running on native Intel"
45 | fi
46 | elif [ "${arch_name}" = "arm64" ]; then
47 | echo "Running on ARM"
48 | else
49 | echo "Unknown architecture: ${arch_name}"
50 | fi
51 | fi
52 |
53 | # Test: Previous compiles may confound future compiles, erase...
54 | \rm -fr "$HOME/Library/Developer/Xcode/DerivedData/rnfbdemo*"
55 |
56 | # Test: Basic template create, rnfb install, link
57 | \rm -fr rnfbdemo
58 |
59 | echo "Testing react-native ${RN_VER} + react-native-firebase ${RNFB_VER} + firebase-ios-sdk ${FB_IOS_VER} + firebase-android-sdk ${FB_ANDROID_VER}"
60 |
61 | if ! YARN_VERSION=$(yarn --version|cut -f1 -d'.') || ([ "$YARN_VERSION" != "3" ] && [ "$YARN_VERSION" != "4" ]); then
62 | echo "This script uses yarn@^4+, please install yarn (for example \`corepack enable && corepack prepare yarn@^4 --activate\` and re-try"
63 | exit 1
64 | fi
65 | #######################################################################################################
66 | #######################################################################################################
67 |
68 |
69 |
70 | # Let's test react-native-firebase integration! Here is how you do it.
71 |
72 |
73 | # Initialize a fresh project.
74 | # We say "skip-install" because we control our ruby version and cocoapods (part of install) does not like it
75 | echo Y | yarn dlx @react-native-community/cli init rnfbdemo --pm yarn --package-name ${FB_ANDROID_PACKAGE_NAME} --skip-install --skip-git-init --version=${RN_VER}
76 |
77 | cd rnfbdemo
78 |
79 | # New versions of react-native include annoying Ruby stuff that forces use of old rubies. Obliterate.
80 | if [ -f Gemfile ]; then
81 | rm -f Gemfile* .ruby*
82 | fi
83 |
84 | # Now run our initial dependency install
85 | touch yarn.lock
86 | yarn
87 |
88 | if [ "$(uname)" == "Darwin" ]; then
89 | echo "Setting Apple PRODUCT_BUNDLE_IDENTIFIER to ${FB_IOS_PACKAGE_NAME}"
90 | # It is difficult to change the Android package name, so we use it for init.
91 | # The iOS name is trivial though, just a PRODUCT_BUNDLE_IDENTIFIER change in pbxproj
92 | sed -i -e "s/${FB_ANDROID_PACKAGE_NAME}/${FB_IOS_PACKAGE_NAME}/"g ios/rnfbdemo.xcodeproj/project.pbxproj
93 | rm -f ios/rnfbdemo.xcodeproj/project.pbxproj-e
94 | npm_config_yes=true npx pod-install
95 | fi
96 |
97 | # At this point we have a clean react-native project. Absolutely stock from the upstream template.
98 |
99 | # Required: This is the most basic part of the integration - include google services plugin and call to firebase init on iOS
100 | echo "Adding react-native-firebase core app package"
101 | yarn add "@react-native-firebase/app@${RNFB_VER}"
102 | echo "Adding basic iOS integration - AppDelegate import and config call"
103 | sed -i -e $'s/import UIKit/import UIKit\\\nimport FirebaseCore/' ios/rnfbdemo/AppDelegate.swift
104 | rm -f ios/rnfbdemo/AppDelegate.swift-e
105 | sed -i -e $'s/let delegate/FirebaseApp.configure()\\\n let delegate/' ios/rnfbdemo/AppDelegate.swift
106 | rm -f ios/rnfbdemo/AppDelegate.swift-e
107 | echo "Adding basic java integration - gradle plugin dependency and call"
108 | sed -i -e $"s/dependencies {/dependencies {\n classpath \"com.google.gms:google-services:${FB_GRADLE_SERVICES_VER}\"/" android/build.gradle
109 | rm -f android/build.gradle??
110 | sed -i -e $'s/apply plugin: "com.android.application"/apply plugin: "com.android.application"\\\napply plugin: "com.google.gms.google-services"/' android/app/build.gradle
111 | rm -f android/app/build.gradle??
112 |
113 | #############################################################################################################
114 | # Required: Static Frameworks linkage set up in cocoapods, and various related workarounds for compatibility.
115 | #############################################################################################################
116 |
117 | # You have two options here:
118 | # - One is to dynamically turn on static frameworks with environment variables at build time
119 | # - Two is to permanently turn on static frameworks with Podfile edits
120 |
121 | # The default way a new react-native app is built from template uses method One, environment variables.
122 | # I worry that some developer somewhere will not have these environment variables set correctly though,
123 | # causing an unexpected build failure.
124 |
125 | # So we choose option Two, where we permanently enable static frameworks in the Podfile.
126 |
127 | # Required: turn on static frameworks with static linkage, and tell react-native-firebase that is how we are linking
128 | sed -i -e $'s/config = use_native_modules!/config = use_native_modules!\\\n use_frameworks! :linkage => :static\\\n $RNFirebaseAsStaticFramework = true/' ios/Podfile
129 | rm -f ios/Podfile??
130 |
131 | # Required: copy your Firebase config files in - you must supply them, downloaded from firebase web console
132 | echo "For this demo to work, you must create an \`rnfbdemo\` project in your firebase console,"
133 | echo "then download the android json and iOS plist app definition files to the root directory"
134 | echo "of this repository"
135 |
136 | echo "Copying in Firebase android json and iOS plist app definition files downloaded from console"
137 |
138 | if [ "$(uname)" == "Darwin" ]; then
139 | if [ -f "../GoogleService-Info.plist" ]; then
140 | cp ../GoogleService-Info.plist ios/rnfbdemo/
141 | else
142 | echo "Unable to locate the file 'GoogleServices-Info.plist', did you create the firebase project and download the iOS file?"
143 | exit 1
144 | fi
145 | fi
146 | if [ -f "../google-services.json" ]; then
147 | cp ../google-services.json android/app/
148 | else
149 | echo "Unable to locate the file 'google-services.json', did you create the firebase project and download the android file?"
150 | exit 1
151 | fi
152 |
153 |
154 | ##################################################################################################
155 | # This section is only required for the script to work fully automatic.
156 | # In your project you will use Xcode user interface to add your GoogleService-Info.plist file
157 | ##################################################################################################
158 | # Set up python virtual environment so we can do some local mods to Xcode project with mod-pbxproj
159 | # FIXME need to verify that python3 exists (recommend brew) and has venv module installed
160 | if [ "$(uname)" == "Darwin" ]; then
161 | echo "Setting up python virtual environment + mod-pbxproj for Xcode project edits"
162 | python3 -m venv virtualenv
163 | # shellcheck disable=SC1091
164 | source virtualenv/bin/activate
165 | pip install pbxproj
166 |
167 | # Add our Google Services file to the Xcode project
168 | pbxproj file ios/rnfbdemo.xcodeproj rnfbdemo/GoogleService-Info.plist --target rnfbdemo
169 |
170 | # Toggle on iPad: add build flag: TARGETED_DEVICE_FAMILY = "1,2"
171 | pbxproj flag ios/rnfbdemo.xcodeproj --target rnfbdemo TARGETED_DEVICE_FAMILY "1,2"
172 | fi
173 | ##################################################################################################
174 |
175 |
176 | # From this point on we are adding optional modules. We test them all so we add them all. You only need to add what you need.
177 | # First set up all the modules that need no further config for the demo
178 | echo "Adding packages: Analytics, App Check, Auth, Database, Dynamic Links, Firestore, Functions, In App Messaging, Installations, Messaging, ML, Remote Config, Storage"
179 | yarn add \
180 | @react-native-firebase/analytics@${RNFB_VER} \
181 | @react-native-firebase/app-check@${RNFB_VER} \
182 | @react-native-firebase/auth@${RNFB_VER} \
183 | @react-native-firebase/database@${RNFB_VER} \
184 | @react-native-firebase/dynamic-links@${RNFB_VER} \
185 | @react-native-firebase/firestore@${RNFB_VER} \
186 | @react-native-firebase/functions@${RNFB_VER} \
187 | @react-native-firebase/in-app-messaging@${RNFB_VER} \
188 | @react-native-firebase/installations@${RNFB_VER} \
189 | @react-native-firebase/messaging@${RNFB_VER} \
190 | @react-native-firebase/ml@${RNFB_VER} \
191 | @react-native-firebase/remote-config@${RNFB_VER} \
192 | @react-native-firebase/storage@${RNFB_VER} \
193 | @react-native-firebase/vertexai@${RNFB_VER}
194 |
195 | # Optional: Crashlytics - repo, classpath, plugin, dependency, import, init
196 | echo "Setting up Crashlytics - package, gradle plugin"
197 | yarn add "@react-native-firebase/crashlytics@${RNFB_VER}"
198 | sed -i -e $"s/dependencies {/dependencies {\n classpath \"com.google.firebase:firebase-crashlytics-gradle:${FB_GRADLE_CRASH_VER}\"/" android/build.gradle
199 | rm -f android/build.gradle??
200 | sed -i -e $'s/"com.google.gms.google-services"/"com.google.gms.google-services"\\\napply plugin: "com.google.firebase.crashlytics"/' android/app/build.gradle
201 | rm -f android/app/build.gradle??
202 | sed -i -e $'s/proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"/proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"\\\n firebaseCrashlytics {\\\n nativeSymbolUploadEnabled true\\\n unstrippedNativeLibsDir "build\/intermediates\/merged_native_libs\/release\/out\/lib"\\\n }/' android/app/build.gradle
203 | rm -f android/app/build.gradle??
204 |
205 | # Optional: Performance - classpath, plugin, dependency, import, init
206 | echo "Setting up Performance - package, gradle plugin"
207 | yarn add "@react-native-firebase/perf@${RNFB_VER}"
208 | rm -f android/app/build.gradle??
209 | sed -i -e $"s/dependencies {/dependencies {\n classpath \"com.google.firebase:perf-plugin:${FB_GRADLE_PERF_VER}\"/" android/build.gradle
210 | rm -f android/build.gradle??
211 | sed -i -e $'s/"com.google.gms.google-services"/"com.google.gms.google-services"\\\napply plugin: "com.google.firebase.firebase-perf"/' android/app/build.gradle
212 | rm -f android/app/build.gradle??
213 |
214 | # Optional: App Distribution - classpath, plugin, dependency, import, init
215 | echo "Setting up App Distribution - package, gradle plugin"
216 | yarn add "@react-native-firebase/app-distribution@${RNFB_VER}"
217 | sed -i -e $"s/dependencies {/dependencies {\n classpath \"com.google.firebase:firebase-appdistribution-gradle:${FB_GRADLE_APP_DIST_VER}\"/" android/build.gradle
218 | rm -f android/build.gradle??
219 | sed -i -e $'s/"com.google.gms.google-services"/"com.google.gms.google-services"\\\napply plugin: "com.google.firebase.appdistribution"/' android/app/build.gradle
220 | rm -f android/app/build.gradle??
221 |
222 | # Required for Firestore - android build tweak - or gradle runs out of memory during the build
223 | echo "Increasing memory available to gradle for android java build"
224 | echo "org.gradle.jvmargs=-Xmx3072m -Dfile.encoding=UTF-8" >> android/gradle.properties
225 |
226 | # I'm not going to demonstrate messaging and notifications. Everyone gets it wrong because it's hard.
227 | # You've got to read the docs and test *EVERYTHING* one feature at a time.
228 | # But you have to do a *lot* of work in the AndroidManifest.xml, and make sure your MainActivity *is* the launch intent receiver
229 | # I include it for compile testing only.
230 |
231 | # Optional: do you want to configure firebase behavior via firebase.json?
232 | echo "Creating default firebase.json (with settings that allow iOS crashlytics to report crashes even in debug mode)"
233 | printf "{\n \"react-native\": {\n \"crashlytics_disable_auto_disabler\": true,\n \"crashlytics_debug_enabled\": true\n }\n}" > firebase.json
234 |
235 | # Optional: allow explicit SDK version control by specifying our iOS Pods and Android Firebase Bill of Materials
236 | echo "Adding upstream SDK overrides for precise version control"
237 | echo "project.ext{set('react-native',[versions:[firebase:[bom:'${FB_ANDROID_VER}'],],])}" >> android/build.gradle
238 | sed -i -e $"s/target 'rnfbdemo' do/\$FirebaseSDKVersion = '${FB_IOS_VER}'\ntarget 'rnfbdemo' do/" ios/Podfile
239 | rm -f ios/Podfile??
240 |
241 | # Optional: build performance - use pre-built version of Firestore - https://github.com/invertase/firestore-ios-sdk-frameworks
242 | # If you are using firestore and database you *may* end up with duplicate symbol build errors referencing "leveldb", the FirebaseFirestoreExcludeLeveldb boolean fixes that.
243 | #sed -i -e $'s/target \'rnfbdemo\' do/target \'rnfbdemo\' do\\\n $FirebaseFirestoreExcludeLeveldb = true\\\n pod \'FirebaseFirestore\', :git => \'https:\\/\\/github.com\\/invertase\\/firestore-ios-sdk-frameworks.git\', :tag => $FirebaseSDKVersion\\\n/' ios/Podfile
244 | #rm -f ios/Podfile??
245 |
246 | # Required for AppCheck on iOS - need to add the initializer into the AppDelegate
247 | echo "Adding basic iOS integration - AppDelegate import and config call"
248 | sed -i -e $'s/import UIKit/import UIKit\\\nimport RNFBAppCheck/' ios/rnfbdemo/AppDelegate.swift
249 | rm -f ios/rnfbdemo/AppDelegate.swift-e
250 | sed -i -e $'s/FirebaseApp.configure/RNFBAppCheckModule.sharedInstance()\\\n FirebaseApp.configure/' ios/rnfbdemo/AppDelegate.swift
251 | rm -f ios/rnfbdemo/AppDelegate.swift-e
252 |
253 | # Optional: build performance optimization to use ccache - asks xcodebuild to use clang and clang++ without the fully-qualified path
254 | # That means that you can then make a symlink in your path with clang or clang++ and have it use a different binary
255 | # In that way you can install ccache or buildcache and get much faster compiles...
256 | sed -i -e $'s/# :ccache_enabled/:ccache_enabled/' ios/Podfile
257 | rm -f ios/Podfile??
258 | if [ -e ~/.ccache/ccache.conf ]; then
259 | echo "Using local ccache.conf in preference to built-in react-native conf"
260 | export CCACHE_CONFIGPATH=~/.ccache/ccache.conf
261 | fi
262 |
263 | # Optional: Cleaner build logs - libevent pulled in by react core items are ridiculously noisy otherwise
264 | sed -i -e $'s/post_install do |installer|/post_install do |installer|\\\n installer.pods_project.targets.each do |target|\\\n target.build_configurations.each do |config|\\\n config.build_settings["GCC_WARN_INHIBIT_ALL_WARNINGS"] = "YES"\\\n end\\\n end\\\n/' ios/Podfile
265 | rm -f ios/Podfile??
266 |
267 | # Test: Copy in our demonstrator App.tsx and index.js
268 | echo "Copying demonstrator App.tsx and index.js"
269 | rm ./App.tsx ./index.js && cp ../App.tsx ./App.tsx && cp ../index.js ./index.js
270 |
271 | # Test: You have to re-run patch-package after yarn since it is not integrated into postinstall
272 | echo "Running any patches necessary to compile successfully"
273 | cp -rv ../patches .
274 | npm_config_yes=true npx patch-package
275 |
276 | # Test: Run the thing for iOS
277 | if [ "$(uname)" == "Darwin" ]; then
278 |
279 | #################################################################################################
280 | # This section is so the script may work fully automatic.
281 | # If you are targeting macCatalyst, you will use the Xcode UI to add your development team.
282 | # add file rnfbdemo/rnfbdemo.entitlements, with reference to rnfbdemo target, but no build phase
283 | echo "Adding macCatalyst entitlements file / build flags to Xcode project"
284 | cp ../rnfbdemo.entitlements ios/rnfbdemo/
285 | pbxproj file ios/rnfbdemo.xcodeproj rnfbdemo/rnfbdemo.entitlements --target rnfbdemo -C
286 | # add build flag: CODE_SIGN_ENTITLEMENTS = rnfbdemo/rnfbdemo.entitlements
287 | pbxproj flag ios/rnfbdemo.xcodeproj --target rnfbdemo CODE_SIGN_ENTITLEMENTS rnfbdemo/rnfbdemo.entitlements
288 | # add build flag: SUPPORTS_MACCATALYST = YES
289 | pbxproj flag ios/rnfbdemo.xcodeproj --target rnfbdemo SUPPORTS_MACCATALYST YES
290 | # for local signing / no dev team: add build flag CODE_SIGN_IDENTITY = "-";
291 | pbxproj flag ios/rnfbdemo.xcodeproj --target rnfbdemo CODE_SIGN_IDENTITY "-"
292 | # Only "-" may be added by pbxproj (it cannot handle ""), but only "" works. Adjust it.
293 | sed -i -e $'s/CODE_SIGN_IDENTITY = "-"/CODE_SIGN_IDENTITY = ""/g' ios/rnfbdemo.xcodeproj/project.pbxproj
294 | rm -f ios/rnfbdemo.xcodeproj/project.pbxproj??
295 |
296 | # These are the background modes you need for push notifications and processing (just in case)
297 | /usr/libexec/PlistBuddy -c "Add :UIBackgroundModes array" ios/rnfbdemo/Info.plist
298 | /usr/libexec/PlistBuddy -c "Add :UIBackgroundModes:0 string fetch" ios/rnfbdemo/Info.plist
299 | /usr/libexec/PlistBuddy -c "Add :UIBackgroundModes:0 string processing" ios/rnfbdemo/Info.plist
300 | /usr/libexec/PlistBuddy -c "Add :UIBackgroundModes:0 string remote-notification" ios/rnfbdemo/Info.plist
301 |
302 |
303 | echo "Installing pods and running iOS app in debug mode"
304 | pod repo update
305 | npm_config_yes=true npx pod-install
306 |
307 | # Check iOS debug mode compile
308 | npx react-native run-ios --mode Debug --simulator "iPhone 16"
309 |
310 | # Check iOS release mode compile
311 | echo "Installing pods and running iOS app in release mode"
312 | npx react-native run-ios --mode Release --simulator "iPhone 16"
313 |
314 | # New architecture disable: RCT_NEW_ARCH_ENABLED=0 env var then pod install
315 |
316 | # Check catalyst build
317 |
318 | # Required for macCatalyst: Podfile workarounds for signing and library paths are built-in 0.70+ with a specific flag:
319 | sed -i -e $'s/mac_catalyst_enabled => false/mac_catalyst_enabled => true/' ios/Podfile
320 | rm -f ios/Podfile??
321 |
322 | echo "Installing pods and running iOS app in macCatalyst mode"
323 | npm_config_yes=true npx pod-install
324 |
325 | # Now run it with our mac device name as device target, that triggers catalyst build
326 | # Need to check if the development team id is valid? error 70 indicates team not added as account / cert not present / xcode does not have access to keychain?
327 |
328 | # For some reason, the device id returned if you use the computer name is wrong.
329 | # It is also wrong from ios-deploy or xcrun xctrace list devices
330 | # The only way I have found to get the right ID is to provide the wrong one then parse out the available one
331 | CATALYST_DESTINATION=$(xcodebuild -workspace ios/rnfbdemo.xcworkspace -configuration Debug -scheme rnfbdemo -destination id=7153382A-C92B-5798-BEA3-D82D195F25F8 2>&1|grep macOS|grep Catalyst|head -1 |cut -d':' -f5 |cut -d' ' -f1 |cut -d',' -f1)
332 |
333 | # FIXME This requires a CLI patch to the iOS platform to accept a UDID it cannot probe, and to set type to catalyst
334 | npx react-native run-ios --udid "$CATALYST_DESTINATION" --mode Debug
335 |
336 | # Optional: workaround for poorly setup Android SDK environments on macs
337 | USER=$(whoami)
338 | echo "sdk.dir=/Users/$USER/Library/Android/sdk" > android/local.properties
339 | fi
340 |
341 | # Test: make sure proguard works
342 | echo "Configuring Android release build for ABI splits and code shrinking"
343 | sed -i -e $'s/def enableProguardInReleaseBuilds = false/def enableProguardInReleaseBuilds = true/' android/app/build.gradle
344 | rm -f android/app/build.gradle??
345 |
346 | # Test: If we are on WSL the user needs to now run it from the Windows side
347 | # Getting it to run from WSL is a real mess (it is possible, but not recommended)
348 | # So we will stop now that we've done all the installation and file editing
349 | if [ "$(uname -a | grep Linux | grep -c microsoft)" == "1" ]; then
350 | echo "Detected Windows Subsystem for Linux. Stopping now."
351 |
352 | # Windows has some sort of gradle error with gradle-8.10.2 but gradle 8.12 works
353 | # "java.io.UncheckedIOException: Could not move temporary workspace"
354 | sed -i -e $'s/8.10.2/8.12/' android/gradle/gradle-wrapper.properties
355 | rm -f android/gradle/gradle-wrapper.properties
356 |
357 | # Clear out the unix-y node_modules
358 | \rm -fr node_modules
359 | echo "To run the app use Windows Powershell in the rnfbdemo directory with these commands:"
360 | echo "npm i"
361 | echo "npx react-native run-android --mode debug"
362 | exit
363 | fi
364 |
365 | # Test: uninstall it (just in case, otherwise ABI-split-generated version codes will prevent debug from installing)
366 | pushd android
367 | ./gradlew uninstallRelease
368 | popd
369 |
370 | # Test: Run it for Android (assumes you have an android emulator running)
371 | echo "Running android app in release mode"
372 | npx react-native run-android --mode release
373 |
374 | # Test: Let it start up, then uninstall it (otherwise ABI-split-generated version codes will prevent debug from installing)
375 | sleep 30
376 | pushd android
377 | ./gradlew uninstallRelease
378 | popd
379 |
380 | # Test: may or may not be commented out, depending on if have an emulator available
381 | # I run it manually in testing when I have one, comment if you like
382 | echo "Running android app in debug mode"
383 | npx react-native run-android --mode debug
384 |
385 |
386 | # new architecture put this in android/gradle.properties +newArchEnabled=true
387 |
--------------------------------------------------------------------------------
/notifee-demo.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | RN_VER=0.76.1
5 | NOTIFEE_VER=9.1.2
6 |
7 | # Basic template create, notifee install, link
8 | \rm -fr notifeedemo notifeewebdemo
9 |
10 | echo "Testing react-native ${RN_VER} + notifee ${NOTIFEE_VER}"
11 | npm_config_yes=true npx @react-native-community/cli init notifeedemo --skip-install --skip-git-init --version=${RN_VER}
12 | cd notifeedemo
13 |
14 | # New versions of react-native include annoying Ruby stuff that forces use of old rubies. Obliterate.
15 | if [ -f Gemfile ]; then
16 | rm -f Gemfile* .ruby*
17 | fi
18 |
19 | # Now run our initial dependency install
20 | touch yarn.lock
21 | yarn
22 | npm_config_yes=true npx pod-install
23 |
24 | # At this point we have a clean react-native project. Absolutely stock from the upstream template.
25 |
26 | # This is the most basic integration - adding the package - local maven repo not needed with modern notifee
27 | echo "Adding Notifee app package"
28 | yarn add "@notifee/react-native@${NOTIFEE_VER}"
29 |
30 | # Optional: build performance optimization to use ccache - asks xcodebuild to use clang and clang++ without the fully-qualified path
31 | # That means that you can then make a symlink in your path with clang or clang++ and have it use a different binary
32 | # In that way you can install ccache or buildcache and get much faster compiles...
33 | sed -i -e $'s/post_install do |installer|/post_install do |installer|\\\n installer.pods_project.targets.each do |target|\\\n target.build_configurations.each do |config|\\\n config.build_settings["CC"] = "clang"\\\n config.build_settings["LD"] = "clang"\\\n config.build_settings["CXX"] = "clang++"\\\n config.build_settings["LDPLUSPLUS"] = "clang++"\\\n end\\\n end\\\n/' ios/Podfile
34 | rm -f ios/Podfile??
35 |
36 | # Optional: Cleaner build logs - libevent pulled in by react core items are ridiculously noisy otherwise
37 | sed -i -e $'s/post_install do |installer|/post_install do |installer|\\\n installer.pods_project.targets.each do |target|\\\n target.build_configurations.each do |config|\\\n config.build_settings["GCC_WARN_INHIBIT_ALL_WARNINGS"] = "YES"\\\n end\\\n end\\\n/' ios/Podfile
38 | rm -f ios/Podfile??
39 |
40 | # Copy in our demonstrator App
41 | echo "Copying demonstrator App"
42 | rm ./App.tsx && cp ../NotifeeApp.tsx ./App.tsx
43 |
44 | # Test: You have to re-run patch-package after yarn since it is not integrated into postinstall
45 | echo "Running any patches necessary to compile successfully"
46 | cp -rv ../patches .
47 | npm_config_yes=true npx patch-package
48 |
49 | # Run the thing for iOS
50 | if [ "$(uname)" == "Darwin" ]; then
51 |
52 | echo "Installing pods and running iOS app"
53 | pod repo update
54 | npm_config_yes=true npx pod-install
55 | # Check iOS debug mode compile
56 | npx react-native run-ios --mode Debug --simulator "iPhone 16"
57 |
58 | # Check iOS release mode compile
59 | echo "Installing pods and running iOS app in release mode"
60 | npx react-native run-ios --mode Release --simulator "iPhone 16"
61 |
62 | # New architecture enable: RCT_NEW_ARCH_ENABLED=1 env var then pod install
63 |
64 | # Optional: workaround for poorly setup Android SDK environments on macs
65 | USER=$(whoami)
66 | echo "sdk.dir=/Users/$USER/Library/Android/sdk" > android/local.properties
67 | fi
68 |
69 | # Test: make sure proguard works
70 | echo "Configuring Android release build for ABI splits and code shrinking"
71 | sed -i -e $'s/def enableProguardInReleaseBuilds = false/def enableProguardInReleaseBuilds = true/' android/app/build.gradle
72 | rm -f android/app/build.gradle??
73 |
74 | # Test: Run it for Android (assumes you have an android emulator running)
75 | echo "Running android app in release mode"
76 | npx react-native run-android --mode release
77 |
78 | # Test: Let it start up, then uninstall it (otherwise ABI-split-generated version codes will prevent debug from installing)
79 | sleep 30
80 | pushd android
81 | ./gradlew uninstallRelease
82 | popd
83 |
84 | # Test: may or may not be commented out, depending on if have an emulator available
85 | # I run it manually in testing when I have one, comment if you like
86 | echo "Running android app in debug mode"
87 | npx react-native run-android --mode debug
88 |
89 |
90 | # new architecture put this in android/gradle.properties +newArchEnabled=true
91 |
92 | # Test web
93 | # cd ..
94 | # echo "Running android app in web mode"
95 | # npm_config_yes=true npx react-native init notifeewebdemo --template criszz77/luna --skip-install
96 | # cd notifeewebdemo
97 | # yarn
98 | # yarn add @notifee/react-native
99 |
100 | # # A quirk of this example, sometimes we have local example-specific patches
101 | # echo "Running any patches necessary to compile successfully"
102 | # cp -rv ../patches .
103 | # npm_config_yes=true npx patch-package
104 |
105 | # # Copy in our demonstrator App.js
106 | # echo "Copying demonstrator App.js"
107 | # rm -f ./src/App.tsx && cp ../NotifeeApp.js ./src/App.tsx
108 |
109 | # yarn web
--------------------------------------------------------------------------------
/patches/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikehardy/rnfbdemo/ec973628152a022fa39c018371fb20be60c35bd9/patches/.gitkeep
--------------------------------------------------------------------------------
/patches/@react-native-community+cli-platform-apple+18.0.0.patch:
--------------------------------------------------------------------------------
1 | diff --git a/node_modules/@react-native-community/cli-platform-apple/build/commands/runCommand/createRun.js b/node_modules/@react-native-community/cli-platform-apple/build/commands/runCommand/createRun.js
2 | index e779900..a225f24 100644
3 | --- a/node_modules/@react-native-community/cli-platform-apple/build/commands/runCommand/createRun.js
4 | +++ b/node_modules/@react-native-community/cli-platform-apple/build/commands/runCommand/createRun.js
5 | @@ -195,9 +195,17 @@ const createRun = ({
6 | return _cliTools().logger.error('The `device` and `udid` options are mutually exclusive.');
7 | }
8 | if (args.udid) {
9 | - const device = devices.find(d => d.udid === args.udid);
10 | + let device = devices.find(d => d.udid === args.udid);
11 | if (!device) {
12 | - return _cliTools().logger.error(`Could not find a device with udid: "${_chalk().default.bold(args.udid)}". ${(0, _matchingDevice.printFoundDevices)(devices)}`);
13 | + // FIXME - on arm64 machines, the catalyst UDID returned by 'xcrun xctrace list devices' is not correct
14 | + // xcodebuild will return an error indicating the UDID is unknown and offering a different one
15 | + // you may obtain it by running xcodebuild with the UDID you think works then parse out the other one from the returned error:
16 | + // CATALYST_DESTINATION=$(xcodebuild -workspace ios/rnfbdemo.xcworkspace -configuration Debug -scheme rnfbdemo -destination id=7153382A-C92B-5798-BEA3-D82D195F25F8 2>&1|grep macOS|grep Catalyst|head -1 |cut -d':' -f5 |cut -d' ' -f1)
17 | + //
18 | + // How to handle this? offer a command line to force udid (and type, so "catalyst" will launch the app correctly) ?
19 | + device = { "name":"unknown","udid":args.udid,"type":"catalyst"};
20 | + _cliTools().logger.warn(`Could not find a device with udid: "${_chalk().default.bold(args.udid)}".`);
21 | + _cliTools().logger.warn(`Running with provided udid anyway, and type "catalyst". 'xcodebuild' command may return error.`);
22 | }
23 | if (device.type === 'simulator') {
24 | return (0, _runOnSimulator.runOnSimulator)(xcodeProject, platformName, mode, scheme, args, fallbackSimulator);
25 |
--------------------------------------------------------------------------------
/rnfbdemo.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | aps-environment
6 | development
7 | com.apple.developer.associated-domains
8 |
9 | applinks:reactnativefirebase.page.link
10 |
11 | keychain-access-groups
12 |
13 | $(AppIdentifierPrefix)com.invertase.testing
14 |
15 | com.apple.security.app-sandbox
16 |
17 | com.apple.security.network.client
18 |
19 | com.apple.security.personal-information.location
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------