@fishonfire/bubbles-expo 0.1.1 → 0.1.3
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/README.md +3 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +19 -40
- package/dist/index.mjs +18 -44
- package/package.json +1 -1
- package/plugin/build/index.js +2 -0
- package/plugin/build/with-firebase-messaging-manifest.js +36 -0
- package/plugin/build/with-firebase-messaging-registration.d.ts +4 -0
- package/plugin/build/with-firebase-messaging-registration.js +118 -0
package/README.md
CHANGED
|
@@ -70,6 +70,8 @@ Plugin options:
|
|
|
70
70
|
|
|
71
71
|
For Android remote display, backend payloads must use the same `android.notification.channel_id` as `defaultChannelId`. The plugin writes Firebase's default-channel manifest metadata, and the package creates the actual Android notification channel when `BubblesNotificationsProvider`, `getNotificationPermissions()`, or `ensureDefaultNotificationChannel()` runs. On a fresh install, the app must be opened at least once before remote notifications can reliably use this configured channel; otherwise Android/Firebase may fall back to its own default behavior before JavaScript has created the channel.
|
|
72
72
|
|
|
73
|
+
Device registration uses the Firebase Installation ID (FID) as the push registration identifier. The package does not call Firebase Messaging's deprecated `getToken()` path for Bubbles device sync; the same FID value is sent as both `push_token` and `fid`. On Android, the config plugin also opts into FID-based Firebase Messaging registration and installs native startup code that calls `FirebaseMessaging.getInstance().register()` automatically.
|
|
74
|
+
|
|
73
75
|
## Background registration
|
|
74
76
|
|
|
75
77
|
Register the package-owned background notification handlers once from your app entrypoint:
|
|
@@ -162,7 +164,7 @@ export function EnableNotificationsButton() {
|
|
|
162
164
|
}
|
|
163
165
|
```
|
|
164
166
|
|
|
165
|
-
`useBubblesNotifications()` also exposes `addDeviceAttribute`, `deviceId`, `pushToken`, `permissionStatus`, `notificationsEnabled`, `tokenType`, and `error`.
|
|
167
|
+
`useBubblesNotifications()` also exposes `addDeviceAttribute`, `deviceId`, `pushToken`, `permissionStatus`, `notificationsEnabled`, `tokenType`, and `error`. When notifications are enabled, `pushToken` is the Firebase Installation ID and `tokenType` is `"fid"`.
|
|
166
168
|
|
|
167
169
|
If your app already requested notification permissions, call `registerDevice({ requestPermissions: false })`.
|
|
168
170
|
|
package/dist/index.d.mts
CHANGED
|
@@ -212,7 +212,7 @@ declare function ensureNotificationPermissions(options?: GetNotificationPermissi
|
|
|
212
212
|
|
|
213
213
|
type SupportedPlatform = 'android' | 'ios';
|
|
214
214
|
|
|
215
|
-
type NativeTokenType = '
|
|
215
|
+
type NativeTokenType = 'fid';
|
|
216
216
|
type GetDeviceTokenOptions = GetNotificationPermissionsOptions;
|
|
217
217
|
interface DeviceTokenResult {
|
|
218
218
|
platform: SupportedPlatform;
|
package/dist/index.d.ts
CHANGED
|
@@ -212,7 +212,7 @@ declare function ensureNotificationPermissions(options?: GetNotificationPermissi
|
|
|
212
212
|
|
|
213
213
|
type SupportedPlatform = 'android' | 'ios';
|
|
214
214
|
|
|
215
|
-
type NativeTokenType = '
|
|
215
|
+
type NativeTokenType = 'fid';
|
|
216
216
|
type GetDeviceTokenOptions = GetNotificationPermissionsOptions;
|
|
217
217
|
interface DeviceTokenResult {
|
|
218
218
|
platform: SupportedPlatform;
|
package/dist/index.js
CHANGED
|
@@ -1418,27 +1418,28 @@ function registerBubblesBackgroundHandlers() {
|
|
|
1418
1418
|
}
|
|
1419
1419
|
|
|
1420
1420
|
// src/runtime/tokens.ts
|
|
1421
|
-
var import_messaging2 = require("@react-native-firebase/messaging");
|
|
1422
1421
|
var import_react_native4 = require("react-native");
|
|
1423
|
-
|
|
1422
|
+
|
|
1423
|
+
// src/runtime/installations.ts
|
|
1424
|
+
var import_installations = require("@react-native-firebase/installations");
|
|
1425
|
+
async function getFirebaseInstallationId(platform) {
|
|
1424
1426
|
try {
|
|
1425
|
-
const
|
|
1426
|
-
|
|
1427
|
-
await (0, import_messaging2.registerDeviceForRemoteMessages)(messagingInstance);
|
|
1428
|
-
}
|
|
1429
|
-
const token = await (0, import_messaging2.getToken)(messagingInstance);
|
|
1427
|
+
const installationsInstance = (0, import_installations.getInstallations)();
|
|
1428
|
+
const installationId = await (0, import_installations.getId)(installationsInstance);
|
|
1430
1429
|
return getRequiredNonEmptyStringFromSource(
|
|
1431
|
-
|
|
1432
|
-
`${platform}
|
|
1430
|
+
installationId,
|
|
1431
|
+
`${platform} Firebase installation id from Firebase Installations`
|
|
1433
1432
|
);
|
|
1434
1433
|
} catch (error) {
|
|
1435
1434
|
const reason = getErrorMessage(error);
|
|
1436
|
-
const platformSpecificSetupHint = platform === "ios" ? " On iOS,
|
|
1435
|
+
const platformSpecificSetupHint = platform === "ios" ? " On iOS, ensure `expo.ios.googleServicesFile` is configured and the native app has been rebuilt." : " On Android, ensure `expo.android.googleServicesFile` is configured and the native app has been rebuilt.";
|
|
1437
1436
|
failWithBubblesError(
|
|
1438
|
-
`Failed to get a ${platform}
|
|
1437
|
+
`Failed to get a ${platform} Firebase installation id from Firebase Installations. Ensure "@react-native-firebase/app" and "@react-native-firebase/installations" are installed and Firebase is configured for this platform.${platformSpecificSetupHint} Original error: ${reason}`
|
|
1439
1438
|
);
|
|
1440
1439
|
}
|
|
1441
1440
|
}
|
|
1441
|
+
|
|
1442
|
+
// src/runtime/tokens.ts
|
|
1442
1443
|
async function getDeviceRegistrationState(options) {
|
|
1443
1444
|
const platform = getSupportedPlatform(import_react_native4.Platform.OS);
|
|
1444
1445
|
const permissions = await getNotificationPermissions(options);
|
|
@@ -1453,10 +1454,10 @@ async function getDeviceRegistrationState(options) {
|
|
|
1453
1454
|
notificationsEnabled: false
|
|
1454
1455
|
};
|
|
1455
1456
|
}
|
|
1456
|
-
const token = await
|
|
1457
|
+
const token = await getFirebaseInstallationId(platform);
|
|
1457
1458
|
return {
|
|
1458
1459
|
platform,
|
|
1459
|
-
tokenType: "
|
|
1460
|
+
tokenType: "fid",
|
|
1460
1461
|
token,
|
|
1461
1462
|
permissionStatus,
|
|
1462
1463
|
notificationsEnabled: true
|
|
@@ -1469,7 +1470,7 @@ async function getDeviceToken(options) {
|
|
|
1469
1470
|
}
|
|
1470
1471
|
return {
|
|
1471
1472
|
platform: registrationState.platform,
|
|
1472
|
-
tokenType: "
|
|
1473
|
+
tokenType: "fid",
|
|
1473
1474
|
token: registrationState.token
|
|
1474
1475
|
};
|
|
1475
1476
|
}
|
|
@@ -1683,7 +1684,7 @@ async function prepareBubblesNotificationPresentation(options) {
|
|
|
1683
1684
|
}
|
|
1684
1685
|
|
|
1685
1686
|
// src/runtime/foreground-message-observer.ts
|
|
1686
|
-
var
|
|
1687
|
+
var import_messaging2 = require("@react-native-firebase/messaging");
|
|
1687
1688
|
var import_react_native5 = require("react-native");
|
|
1688
1689
|
function supportsFirebaseForegroundMessages() {
|
|
1689
1690
|
return import_react_native5.Platform.OS === "android" || import_react_native5.Platform.OS === "ios";
|
|
@@ -1703,8 +1704,8 @@ function observeBubblesForegroundMessages() {
|
|
|
1703
1704
|
return () => {
|
|
1704
1705
|
};
|
|
1705
1706
|
}
|
|
1706
|
-
const unsubscribe = (0,
|
|
1707
|
-
(0,
|
|
1707
|
+
const unsubscribe = (0, import_messaging2.onMessage)(
|
|
1708
|
+
(0, import_messaging2.getMessaging)(),
|
|
1708
1709
|
(remoteMessage) => {
|
|
1709
1710
|
void handleFirebaseForegroundMessage(remoteMessage).catch(
|
|
1710
1711
|
(error) => {
|
|
@@ -1721,25 +1722,6 @@ function observeBubblesForegroundMessages() {
|
|
|
1721
1722
|
};
|
|
1722
1723
|
}
|
|
1723
1724
|
|
|
1724
|
-
// src/runtime/installations.ts
|
|
1725
|
-
var import_installations = require("@react-native-firebase/installations");
|
|
1726
|
-
async function getFirebaseInstallationId(platform) {
|
|
1727
|
-
try {
|
|
1728
|
-
const installationsInstance = (0, import_installations.getInstallations)();
|
|
1729
|
-
const installationId = await (0, import_installations.getId)(installationsInstance);
|
|
1730
|
-
return getRequiredNonEmptyStringFromSource(
|
|
1731
|
-
installationId,
|
|
1732
|
-
`${platform} Firebase installation id from Firebase Installations`
|
|
1733
|
-
);
|
|
1734
|
-
} catch (error) {
|
|
1735
|
-
const reason = getErrorMessage(error);
|
|
1736
|
-
const platformSpecificSetupHint = platform === "ios" ? " On iOS, ensure `expo.ios.googleServicesFile` is configured and the native app has been rebuilt." : " On Android, ensure `expo.android.googleServicesFile` is configured and the native app has been rebuilt.";
|
|
1737
|
-
failWithBubblesError(
|
|
1738
|
-
`Failed to get a ${platform} Firebase installation id from Firebase Installations. Ensure "@react-native-firebase/app" and "@react-native-firebase/installations" are installed and Firebase is configured for this platform.${platformSpecificSetupHint} Original error: ${reason}`
|
|
1739
|
-
);
|
|
1740
|
-
}
|
|
1741
|
-
}
|
|
1742
|
-
|
|
1743
1725
|
// src/runtime/transport.ts
|
|
1744
1726
|
function observeBubblesForegroundRemoteMessages() {
|
|
1745
1727
|
return observeBubblesForegroundMessages();
|
|
@@ -1747,9 +1729,6 @@ function observeBubblesForegroundRemoteMessages() {
|
|
|
1747
1729
|
async function getBubblesDeviceRegistrationState(options) {
|
|
1748
1730
|
return getDeviceRegistrationState(options);
|
|
1749
1731
|
}
|
|
1750
|
-
async function getBubblesInstallationId(platform) {
|
|
1751
|
-
return getFirebaseInstallationId(platform);
|
|
1752
|
-
}
|
|
1753
1732
|
|
|
1754
1733
|
// src/runtime/sync-device.ts
|
|
1755
1734
|
var BubblesNotificationsSyncError = class extends Error {
|
|
@@ -1812,7 +1791,7 @@ async function syncDeviceRegistrationState(options) {
|
|
|
1812
1791
|
options.registrationState
|
|
1813
1792
|
);
|
|
1814
1793
|
try {
|
|
1815
|
-
const installationId = options.registrationState.notificationsEnabled ?
|
|
1794
|
+
const installationId = options.registrationState.notificationsEnabled ? options.registrationState.token : null;
|
|
1816
1795
|
const syncResult = await syncBubblesDevice({
|
|
1817
1796
|
apiBaseUrl,
|
|
1818
1797
|
appId: options.appId,
|
package/dist/index.mjs
CHANGED
|
@@ -52,32 +52,28 @@ import {
|
|
|
52
52
|
} from "./chunk-3BAGWXHY.mjs";
|
|
53
53
|
|
|
54
54
|
// src/runtime/tokens.ts
|
|
55
|
-
import {
|
|
56
|
-
getMessaging,
|
|
57
|
-
getToken,
|
|
58
|
-
isDeviceRegisteredForRemoteMessages,
|
|
59
|
-
registerDeviceForRemoteMessages
|
|
60
|
-
} from "@react-native-firebase/messaging";
|
|
61
55
|
import { Platform } from "react-native";
|
|
62
|
-
|
|
56
|
+
|
|
57
|
+
// src/runtime/installations.ts
|
|
58
|
+
import { getId, getInstallations } from "@react-native-firebase/installations";
|
|
59
|
+
async function getFirebaseInstallationId(platform) {
|
|
63
60
|
try {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
await registerDeviceForRemoteMessages(messagingInstance);
|
|
67
|
-
}
|
|
68
|
-
const token = await getToken(messagingInstance);
|
|
61
|
+
const installationsInstance = getInstallations();
|
|
62
|
+
const installationId = await getId(installationsInstance);
|
|
69
63
|
return getRequiredNonEmptyStringFromSource(
|
|
70
|
-
|
|
71
|
-
`${platform}
|
|
64
|
+
installationId,
|
|
65
|
+
`${platform} Firebase installation id from Firebase Installations`
|
|
72
66
|
);
|
|
73
67
|
} catch (error) {
|
|
74
68
|
const reason = getErrorMessage(error);
|
|
75
|
-
const platformSpecificSetupHint = platform === "ios" ? " On iOS,
|
|
69
|
+
const platformSpecificSetupHint = platform === "ios" ? " On iOS, ensure `expo.ios.googleServicesFile` is configured and the native app has been rebuilt." : " On Android, ensure `expo.android.googleServicesFile` is configured and the native app has been rebuilt.";
|
|
76
70
|
failWithBubblesError(
|
|
77
|
-
`Failed to get a ${platform}
|
|
71
|
+
`Failed to get a ${platform} Firebase installation id from Firebase Installations. Ensure "@react-native-firebase/app" and "@react-native-firebase/installations" are installed and Firebase is configured for this platform.${platformSpecificSetupHint} Original error: ${reason}`
|
|
78
72
|
);
|
|
79
73
|
}
|
|
80
74
|
}
|
|
75
|
+
|
|
76
|
+
// src/runtime/tokens.ts
|
|
81
77
|
async function getDeviceRegistrationState(options) {
|
|
82
78
|
const platform = getSupportedPlatform(Platform.OS);
|
|
83
79
|
const permissions = await getNotificationPermissions(options);
|
|
@@ -92,10 +88,10 @@ async function getDeviceRegistrationState(options) {
|
|
|
92
88
|
notificationsEnabled: false
|
|
93
89
|
};
|
|
94
90
|
}
|
|
95
|
-
const token = await
|
|
91
|
+
const token = await getFirebaseInstallationId(platform);
|
|
96
92
|
return {
|
|
97
93
|
platform,
|
|
98
|
-
tokenType: "
|
|
94
|
+
tokenType: "fid",
|
|
99
95
|
token,
|
|
100
96
|
permissionStatus,
|
|
101
97
|
notificationsEnabled: true
|
|
@@ -108,7 +104,7 @@ async function getDeviceToken(options) {
|
|
|
108
104
|
}
|
|
109
105
|
return {
|
|
110
106
|
platform: registrationState.platform,
|
|
111
|
-
tokenType: "
|
|
107
|
+
tokenType: "fid",
|
|
112
108
|
token: registrationState.token
|
|
113
109
|
};
|
|
114
110
|
}
|
|
@@ -323,7 +319,7 @@ async function prepareBubblesNotificationPresentation(options) {
|
|
|
323
319
|
|
|
324
320
|
// src/runtime/foreground-message-observer.ts
|
|
325
321
|
import {
|
|
326
|
-
getMessaging
|
|
322
|
+
getMessaging,
|
|
327
323
|
onMessage
|
|
328
324
|
} from "@react-native-firebase/messaging";
|
|
329
325
|
import { Platform as Platform2 } from "react-native";
|
|
@@ -346,7 +342,7 @@ function observeBubblesForegroundMessages() {
|
|
|
346
342
|
};
|
|
347
343
|
}
|
|
348
344
|
const unsubscribe = onMessage(
|
|
349
|
-
|
|
345
|
+
getMessaging(),
|
|
350
346
|
(remoteMessage) => {
|
|
351
347
|
void handleFirebaseForegroundMessage(remoteMessage).catch(
|
|
352
348
|
(error) => {
|
|
@@ -363,25 +359,6 @@ function observeBubblesForegroundMessages() {
|
|
|
363
359
|
};
|
|
364
360
|
}
|
|
365
361
|
|
|
366
|
-
// src/runtime/installations.ts
|
|
367
|
-
import { getId, getInstallations } from "@react-native-firebase/installations";
|
|
368
|
-
async function getFirebaseInstallationId(platform) {
|
|
369
|
-
try {
|
|
370
|
-
const installationsInstance = getInstallations();
|
|
371
|
-
const installationId = await getId(installationsInstance);
|
|
372
|
-
return getRequiredNonEmptyStringFromSource(
|
|
373
|
-
installationId,
|
|
374
|
-
`${platform} Firebase installation id from Firebase Installations`
|
|
375
|
-
);
|
|
376
|
-
} catch (error) {
|
|
377
|
-
const reason = getErrorMessage(error);
|
|
378
|
-
const platformSpecificSetupHint = platform === "ios" ? " On iOS, ensure `expo.ios.googleServicesFile` is configured and the native app has been rebuilt." : " On Android, ensure `expo.android.googleServicesFile` is configured and the native app has been rebuilt.";
|
|
379
|
-
failWithBubblesError(
|
|
380
|
-
`Failed to get a ${platform} Firebase installation id from Firebase Installations. Ensure "@react-native-firebase/app" and "@react-native-firebase/installations" are installed and Firebase is configured for this platform.${platformSpecificSetupHint} Original error: ${reason}`
|
|
381
|
-
);
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
362
|
// src/runtime/transport.ts
|
|
386
363
|
function observeBubblesForegroundRemoteMessages() {
|
|
387
364
|
return observeBubblesForegroundMessages();
|
|
@@ -389,9 +366,6 @@ function observeBubblesForegroundRemoteMessages() {
|
|
|
389
366
|
async function getBubblesDeviceRegistrationState(options) {
|
|
390
367
|
return getDeviceRegistrationState(options);
|
|
391
368
|
}
|
|
392
|
-
async function getBubblesInstallationId(platform) {
|
|
393
|
-
return getFirebaseInstallationId(platform);
|
|
394
|
-
}
|
|
395
369
|
|
|
396
370
|
// src/runtime/sync-device.ts
|
|
397
371
|
var BubblesNotificationsSyncError = class extends Error {
|
|
@@ -454,7 +428,7 @@ async function syncDeviceRegistrationState(options) {
|
|
|
454
428
|
options.registrationState
|
|
455
429
|
);
|
|
456
430
|
try {
|
|
457
|
-
const installationId = options.registrationState.notificationsEnabled ?
|
|
431
|
+
const installationId = options.registrationState.notificationsEnabled ? options.registrationState.token : null;
|
|
458
432
|
const syncResult = await syncBubblesDevice({
|
|
459
433
|
apiBaseUrl,
|
|
460
434
|
appId: options.appId,
|
package/package.json
CHANGED
package/plugin/build/index.js
CHANGED
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const config_1 = require("./config");
|
|
7
7
|
const with_firebase_messaging_manifest_1 = __importDefault(require("./with-firebase-messaging-manifest"));
|
|
8
|
+
const with_firebase_messaging_registration_1 = __importDefault(require("./with-firebase-messaging-registration"));
|
|
8
9
|
const with_expo_notifications_1 = __importDefault(require("./with-expo-notifications"));
|
|
9
10
|
const with_runtime_defaults_1 = __importDefault(require("./with-runtime-defaults"));
|
|
10
11
|
const with_rnfirebase_disable_spm_1 = __importDefault(require("./with-rnfirebase-disable-spm"));
|
|
@@ -13,6 +14,7 @@ const withBubblesNotificationsExpo = (config, input) => {
|
|
|
13
14
|
config = (0, with_runtime_defaults_1.default)(config, options);
|
|
14
15
|
config = (0, with_expo_notifications_1.default)(config, options);
|
|
15
16
|
config = (0, with_firebase_messaging_manifest_1.default)(config, options);
|
|
17
|
+
config = (0, with_firebase_messaging_registration_1.default)(config, options);
|
|
16
18
|
config = (0, with_rnfirebase_disable_spm_1.default)(config);
|
|
17
19
|
return config;
|
|
18
20
|
};
|
|
@@ -3,6 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const config_plugins_1 = require("expo/config-plugins");
|
|
4
4
|
const FCM_DEFAULT_CHANNEL = 'com.google.firebase.messaging.default_notification_channel_id';
|
|
5
5
|
const FCM_DEFAULT_COLOR = 'com.google.firebase.messaging.default_notification_color';
|
|
6
|
+
const FCM_INSTALLATION_ID_ENABLED = 'firebase_messaging_installation_id_enabled';
|
|
7
|
+
const RN_FIREBASE_MESSAGING_SERVICE = 'io.invertase.firebase.messaging.ReactNativeFirebaseMessagingService';
|
|
8
|
+
const BUBBLES_FIREBASE_MESSAGING_SERVICE = '.BubblesFirebaseMessagingService';
|
|
9
|
+
const BUBBLES_FIREBASE_MESSAGING_REGISTRAR = '.BubblesFirebaseMessagingRegistrar';
|
|
6
10
|
const withFirebaseMessagingManifest = (config, options) => {
|
|
7
11
|
return (0, config_plugins_1.withAndroidManifest)(config, config => {
|
|
8
12
|
const manifest = config.modResults;
|
|
@@ -17,6 +21,8 @@ const withFirebaseMessagingManifest = (config, options) => {
|
|
|
17
21
|
if (channel) {
|
|
18
22
|
setToolsReplace(channel.$, 'android:value');
|
|
19
23
|
}
|
|
24
|
+
config_plugins_1.AndroidConfig.Manifest.addMetaDataItemToMainApplication(application, FCM_INSTALLATION_ID_ENABLED, 'true', 'value');
|
|
25
|
+
addBubblesFirebaseMessagingRegistrationEntries(application, getAndroidPackageName(config));
|
|
20
26
|
// Expo only creates the FCM color metadata when a notification
|
|
21
27
|
// color has actually been configured.
|
|
22
28
|
if (options.androidNotificationColor) {
|
|
@@ -29,6 +35,36 @@ const withFirebaseMessagingManifest = (config, options) => {
|
|
|
29
35
|
return config;
|
|
30
36
|
});
|
|
31
37
|
};
|
|
38
|
+
function getAndroidPackageName(config) {
|
|
39
|
+
const packageName = config.android?.package?.trim();
|
|
40
|
+
if (!packageName) {
|
|
41
|
+
throw new Error('[@fishonfire/bubbles-expo] "expo.android.package" is required to configure Android Firebase Messaging registration.');
|
|
42
|
+
}
|
|
43
|
+
return packageName;
|
|
44
|
+
}
|
|
45
|
+
function addBubblesFirebaseMessagingRegistrationEntries(application, packageName) {
|
|
46
|
+
application.service = application.service ?? [];
|
|
47
|
+
application.provider = application.provider ?? [];
|
|
48
|
+
removeManifestService(application, RN_FIREBASE_MESSAGING_SERVICE);
|
|
49
|
+
removeManifestService(application, BUBBLES_FIREBASE_MESSAGING_SERVICE);
|
|
50
|
+
upsertManifestProvider(application, {
|
|
51
|
+
$: {
|
|
52
|
+
'android:name': BUBBLES_FIREBASE_MESSAGING_REGISTRAR,
|
|
53
|
+
'android:authorities': `${packageName}.bubblesnotifications.fcmregistrar`,
|
|
54
|
+
'android:exported': 'false',
|
|
55
|
+
'android:initOrder': '100',
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function removeManifestService(application, serviceName) {
|
|
60
|
+
application.service = (application.service ?? []).filter(item => item.$['android:name'] !== serviceName);
|
|
61
|
+
}
|
|
62
|
+
function upsertManifestProvider(application, provider) {
|
|
63
|
+
application.provider = [
|
|
64
|
+
...(application.provider ?? []).filter(item => item.$['android:name'] !== provider.$['android:name']),
|
|
65
|
+
provider,
|
|
66
|
+
];
|
|
67
|
+
}
|
|
32
68
|
function setToolsReplace(attributes, value) {
|
|
33
69
|
attributes['tools:replace'] = value;
|
|
34
70
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ConfigPlugin } from 'expo/config-plugins';
|
|
2
|
+
import type { NormalizedBubblesNotificationsExpoPluginConfig } from './config';
|
|
3
|
+
declare const withFirebaseMessagingRegistration: ConfigPlugin<NormalizedBubblesNotificationsExpoPluginConfig>;
|
|
4
|
+
export default withFirebaseMessagingRegistration;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const config_plugins_1 = require("expo/config-plugins");
|
|
9
|
+
const REGISTRAR_CLASS = 'BubblesFirebaseMessagingRegistrar';
|
|
10
|
+
const withFirebaseMessagingRegistration = config => {
|
|
11
|
+
return (0, config_plugins_1.withDangerousMod)(config, [
|
|
12
|
+
'android',
|
|
13
|
+
async (config) => {
|
|
14
|
+
const packageName = getAndroidPackageName(config);
|
|
15
|
+
const sourceDirectory = node_path_1.default.join(config.modRequest.projectRoot, 'android', 'app', 'src', 'main', 'java', ...packageName.split('.'));
|
|
16
|
+
await promises_1.default.mkdir(sourceDirectory, { recursive: true });
|
|
17
|
+
await promises_1.default.writeFile(node_path_1.default.join(sourceDirectory, `${REGISTRAR_CLASS}.java`), buildFirebaseMessagingRegistrarSource(packageName));
|
|
18
|
+
return config;
|
|
19
|
+
},
|
|
20
|
+
]);
|
|
21
|
+
};
|
|
22
|
+
function getAndroidPackageName(config) {
|
|
23
|
+
const packageName = config.android?.package?.trim();
|
|
24
|
+
if (!packageName) {
|
|
25
|
+
throw new Error('[@fishonfire/bubbles-expo] "expo.android.package" is required to configure Android Firebase Messaging registration.');
|
|
26
|
+
}
|
|
27
|
+
return packageName;
|
|
28
|
+
}
|
|
29
|
+
function buildFirebaseMessagingRegistrarSource(packageName) {
|
|
30
|
+
return `package ${packageName};
|
|
31
|
+
|
|
32
|
+
import android.content.ContentProvider;
|
|
33
|
+
import android.content.ContentValues;
|
|
34
|
+
import android.database.Cursor;
|
|
35
|
+
import android.net.Uri;
|
|
36
|
+
import android.util.Log;
|
|
37
|
+
|
|
38
|
+
import androidx.annotation.NonNull;
|
|
39
|
+
import androidx.annotation.Nullable;
|
|
40
|
+
|
|
41
|
+
public final class ${REGISTRAR_CLASS} extends ContentProvider {
|
|
42
|
+
private static final String TAG = "BubblesFCMRegistrar";
|
|
43
|
+
|
|
44
|
+
@Override
|
|
45
|
+
public boolean onCreate() {
|
|
46
|
+
try {
|
|
47
|
+
Class<?> firebaseAppClass = Class.forName("com.google.firebase.FirebaseApp");
|
|
48
|
+
Class<?> firebaseMessagingClass = Class.forName("com.google.firebase.messaging.FirebaseMessaging");
|
|
49
|
+
|
|
50
|
+
if (getContext() != null) {
|
|
51
|
+
Object apps = firebaseAppClass
|
|
52
|
+
.getMethod("getApps", android.content.Context.class)
|
|
53
|
+
.invoke(null, getContext());
|
|
54
|
+
|
|
55
|
+
if (apps instanceof java.util.List && ((java.util.List<?>) apps).isEmpty()) {
|
|
56
|
+
firebaseAppClass
|
|
57
|
+
.getMethod("initializeApp", android.content.Context.class)
|
|
58
|
+
.invoke(null, getContext());
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
Object messaging = firebaseMessagingClass
|
|
63
|
+
.getMethod("getInstance")
|
|
64
|
+
.invoke(null);
|
|
65
|
+
|
|
66
|
+
firebaseMessagingClass
|
|
67
|
+
.getMethod("register")
|
|
68
|
+
.invoke(messaging);
|
|
69
|
+
} catch (ReflectiveOperationException | RuntimeException error) {
|
|
70
|
+
Log.w(TAG, "Failed to start Firebase Messaging registration.", error);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@Nullable
|
|
77
|
+
@Override
|
|
78
|
+
public Cursor query(
|
|
79
|
+
@NonNull Uri uri,
|
|
80
|
+
@Nullable String[] projection,
|
|
81
|
+
@Nullable String selection,
|
|
82
|
+
@Nullable String[] selectionArgs,
|
|
83
|
+
@Nullable String sortOrder) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@Nullable
|
|
88
|
+
@Override
|
|
89
|
+
public String getType(@NonNull Uri uri) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@Nullable
|
|
94
|
+
@Override
|
|
95
|
+
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@Override
|
|
100
|
+
public int delete(
|
|
101
|
+
@NonNull Uri uri,
|
|
102
|
+
@Nullable String selection,
|
|
103
|
+
@Nullable String[] selectionArgs) {
|
|
104
|
+
return 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@Override
|
|
108
|
+
public int update(
|
|
109
|
+
@NonNull Uri uri,
|
|
110
|
+
@Nullable ContentValues values,
|
|
111
|
+
@Nullable String selection,
|
|
112
|
+
@Nullable String[] selectionArgs) {
|
|
113
|
+
return 0;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
`;
|
|
117
|
+
}
|
|
118
|
+
exports.default = withFirebaseMessagingRegistration;
|