expo-beacon 0.10.2 → 0.10.4
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 +140 -26
- package/android/src/main/java/expo/modules/beacon/BeaconForegroundService.kt +74 -7
- package/android/src/main/java/expo/modules/beacon/ExpoBeaconModule.kt +552 -233
- package/build/ExpoBeacon.types.d.ts +29 -7
- package/build/ExpoBeacon.types.d.ts.map +1 -1
- package/build/ExpoBeacon.types.js.map +1 -1
- package/build/ExpoBeaconModule.d.ts +11 -1
- package/build/ExpoBeaconModule.d.ts.map +1 -1
- package/build/ExpoBeaconModule.js.map +1 -1
- package/build/ExpoBeaconModule.web.d.ts.map +1 -1
- package/build/ExpoBeaconModule.web.js +5 -1
- package/build/ExpoBeaconModule.web.js.map +1 -1
- package/build/hooks/useBeacon.d.ts +5 -1
- package/build/hooks/useBeacon.d.ts.map +1 -1
- package/build/hooks/useBeacon.js +4 -0
- package/build/hooks/useBeacon.js.map +1 -1
- package/build/hooks/useCarPlay.d.ts +3 -1
- package/build/hooks/useCarPlay.d.ts.map +1 -1
- package/build/hooks/useCarPlay.js +2 -0
- package/build/hooks/useCarPlay.js.map +1 -1
- package/build/index.d.ts +2 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js.map +1 -1
- package/ios/ExpoBeaconModule+Monitoring.swift +5 -7
- package/ios/ExpoBeaconModule+Notifications.swift +38 -2
- package/ios/ExpoBeaconModule.swift +17 -4
- package/package.json +1 -1
- package/src/ExpoBeacon.types.ts +34 -10
- package/src/ExpoBeaconModule.ts +26 -4
- package/src/ExpoBeaconModule.web.ts +28 -6
- package/src/hooks/useBeacon.ts +39 -2
- package/src/hooks/useCarPlay.ts +13 -0
- package/src/index.ts +3 -4
package/README.md
CHANGED
|
@@ -271,6 +271,8 @@ function BeaconScreen() {
|
|
|
271
271
|
| `getMonitoringConfig()` | Read the current monitoring config + active-state snapshot. |
|
|
272
272
|
| `getMonitoredDeviceState()` / `getMonitoredDeviceStates()` | Native state snapshot for one / all paired devices. |
|
|
273
273
|
| `setNotificationConfig()` | Persist notification configuration for monitoring sessions. |
|
|
274
|
+
| `setBeaconNotificationConfig()` | Persist only beacon notification settings. |
|
|
275
|
+
| `setCarPlayNotificationConfig()` | Persist only CarPlay / Android Auto notification settings. |
|
|
274
276
|
| `enableEventLogging()` / `disableEventLogging()` | Toggle SQLite logging (updates `isEventLoggingEnabled`). |
|
|
275
277
|
| `getEventLogs()` / `clearEventLogs()` / `destroyEventLogs()` | Read / clear / drop the persisted event log. |
|
|
276
278
|
| `setApiEndpoint()` / `getApiEndpoint()` | Configure / read the native event-forwarding endpoint. |
|
|
@@ -660,28 +662,57 @@ await ExpoBeacon.startMonitoring();
|
|
|
660
662
|
|
|
661
663
|
```ts
|
|
662
664
|
ExpoBeacon.setNotificationConfig({
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
665
|
+
beacons: {
|
|
666
|
+
// Enter/exit/timeout alert notifications (both platforms)
|
|
667
|
+
events: {
|
|
668
|
+
enabled: true, // Set false to suppress beacon alerts
|
|
669
|
+
enterTitle: "Beacon nearby",
|
|
670
|
+
exitTitle: "Beacon out of range",
|
|
671
|
+
timeoutTitle: "Beacon timed out",
|
|
672
|
+
body: "{identifier} {event}ed", // Placeholders: {identifier}, {event}
|
|
673
|
+
sound: true, // iOS only
|
|
674
|
+
icon: "ic_beacon_notification", // Android only — drawable resource name
|
|
675
|
+
},
|
|
676
|
+
|
|
677
|
+
// Persistent status-bar notification for beacon monitoring (Android only)
|
|
678
|
+
foregroundService: {
|
|
679
|
+
title: "My App — Beacon monitoring",
|
|
680
|
+
text: "Watching for nearby beacons",
|
|
681
|
+
icon: "ic_service",
|
|
682
|
+
},
|
|
672
683
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
684
|
+
// Android notification channel for beacon notifications
|
|
685
|
+
channel: {
|
|
686
|
+
name: "Proximity Alerts",
|
|
687
|
+
description: "Alerts when beacons enter or leave range",
|
|
688
|
+
importance: "default", // "low" | "default" | "high"
|
|
689
|
+
},
|
|
678
690
|
},
|
|
679
691
|
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
692
|
+
carPlay: {
|
|
693
|
+
// Connect/disconnect notifications (both platforms)
|
|
694
|
+
events: {
|
|
695
|
+
enabled: true, // Set false to suppress CarPlay alerts
|
|
696
|
+
connectedTitle: "CarPlay connected",
|
|
697
|
+
disconnectedTitle: "CarPlay disconnected",
|
|
698
|
+
body: "CarPlay {event} {transport}", // Placeholders: {event}, {transport}
|
|
699
|
+
sound: true, // iOS only
|
|
700
|
+
icon: "ic_carplay_notification", // Android only — drawable resource name
|
|
701
|
+
},
|
|
702
|
+
|
|
703
|
+
// Persistent status-bar notification in CarPlay-only mode (Android only)
|
|
704
|
+
foregroundService: {
|
|
705
|
+
title: "My App — Vehicle monitoring",
|
|
706
|
+
text: "Monitoring CarPlay / Android Auto",
|
|
707
|
+
icon: "ic_service",
|
|
708
|
+
},
|
|
709
|
+
|
|
710
|
+
// Android notification channel for CarPlay notifications
|
|
711
|
+
channel: {
|
|
712
|
+
name: "CarPlay Alerts",
|
|
713
|
+
description: "CarPlay and Android Auto connection notifications",
|
|
714
|
+
importance: "default",
|
|
715
|
+
},
|
|
685
716
|
},
|
|
686
717
|
});
|
|
687
718
|
```
|
|
@@ -1323,10 +1354,28 @@ setNotificationConfig(config: NotificationConfig): void
|
|
|
1323
1354
|
|
|
1324
1355
|
Persists notification configuration applied to **all subsequent monitoring sessions**. Survives app restarts.
|
|
1325
1356
|
|
|
1326
|
-
For one-off overrides, pass `notifications` inside `startMonitoring(options)` instead.
|
|
1357
|
+
For one-off overrides, pass `notifications` inside `startMonitoring(options)` instead. Monitoring-time notification overrides are merged into the persisted notification config, so omitted beacon or CarPlay sections are preserved.
|
|
1358
|
+
|
|
1359
|
+
Use the top-level `beacons` and `carPlay` sections to configure those notification streams independently. Legacy keys (`beaconEvents`, `carPlayEvents`, `foregroundService`, `channel`, `carPlayChannel`) are still accepted for existing apps.
|
|
1327
1360
|
|
|
1328
1361
|
See [`NotificationConfig`](#notificationconfig) for the full shape.
|
|
1329
1362
|
|
|
1363
|
+
### `setBeaconNotificationConfig(config)`
|
|
1364
|
+
|
|
1365
|
+
```ts
|
|
1366
|
+
setBeaconNotificationConfig(config: BeaconNotificationSettings | BeaconNotificationConfig): void
|
|
1367
|
+
```
|
|
1368
|
+
|
|
1369
|
+
Persists only beacon notification settings without replacing CarPlay settings. Passing a plain `BeaconNotificationConfig` is treated as `beacons.events`.
|
|
1370
|
+
|
|
1371
|
+
### `setCarPlayNotificationConfig(config)`
|
|
1372
|
+
|
|
1373
|
+
```ts
|
|
1374
|
+
setCarPlayNotificationConfig(config: CarPlayNotificationSettings | CarPlayNotificationConfig): void
|
|
1375
|
+
```
|
|
1376
|
+
|
|
1377
|
+
Persists only CarPlay / Android Auto notification settings without replacing beacon settings. Passing a plain `CarPlayNotificationConfig` is treated as `carPlay.events`.
|
|
1378
|
+
|
|
1330
1379
|
---
|
|
1331
1380
|
|
|
1332
1381
|
### `enableEventLogging()`
|
|
@@ -1591,9 +1640,13 @@ import type {
|
|
|
1591
1640
|
ExpoBeaconModuleEvents,
|
|
1592
1641
|
MonitoringOptions,
|
|
1593
1642
|
NotificationConfig,
|
|
1643
|
+
BeaconNotificationSettings,
|
|
1594
1644
|
BeaconNotificationConfig,
|
|
1645
|
+
CarPlayNotificationSettings,
|
|
1646
|
+
CarPlayNotificationConfig,
|
|
1595
1647
|
ForegroundServiceConfig,
|
|
1596
1648
|
NotificationChannelConfig,
|
|
1649
|
+
CarPlayChannelConfig,
|
|
1597
1650
|
EventLogQueryOptions,
|
|
1598
1651
|
EventLogEntry,
|
|
1599
1652
|
} from "expo-beacon";
|
|
@@ -1774,9 +1827,35 @@ Top-level notification configuration.
|
|
|
1774
1827
|
|
|
1775
1828
|
```ts
|
|
1776
1829
|
type NotificationConfig = {
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1830
|
+
beacons?: BeaconNotificationSettings;
|
|
1831
|
+
carPlay?: CarPlayNotificationSettings;
|
|
1832
|
+
|
|
1833
|
+
// Legacy aliases, still accepted:
|
|
1834
|
+
beaconEvents?: BeaconNotificationConfig;
|
|
1835
|
+
carPlayEvents?: CarPlayNotificationConfig;
|
|
1836
|
+
foregroundService?: ForegroundServiceConfig;
|
|
1837
|
+
channel?: NotificationChannelConfig;
|
|
1838
|
+
carPlayChannel?: CarPlayChannelConfig;
|
|
1839
|
+
};
|
|
1840
|
+
```
|
|
1841
|
+
|
|
1842
|
+
### `BeaconNotificationSettings`
|
|
1843
|
+
|
|
1844
|
+
```ts
|
|
1845
|
+
type BeaconNotificationSettings = {
|
|
1846
|
+
events?: BeaconNotificationConfig;
|
|
1847
|
+
foregroundService?: ForegroundServiceConfig; // Android only, title/text/icon only
|
|
1848
|
+
channel?: NotificationChannelConfig; // Android only, beacon alert channel
|
|
1849
|
+
};
|
|
1850
|
+
```
|
|
1851
|
+
|
|
1852
|
+
### `CarPlayNotificationSettings`
|
|
1853
|
+
|
|
1854
|
+
```ts
|
|
1855
|
+
type CarPlayNotificationSettings = {
|
|
1856
|
+
events?: CarPlayNotificationConfig;
|
|
1857
|
+
foregroundService?: ForegroundServiceConfig; // Android only, CarPlay-only title/text/icon
|
|
1858
|
+
channel?: CarPlayChannelConfig; // Android only, CarPlay alert channel
|
|
1780
1859
|
};
|
|
1781
1860
|
```
|
|
1782
1861
|
|
|
@@ -1805,6 +1884,8 @@ type ForegroundServiceConfig = {
|
|
|
1805
1884
|
};
|
|
1806
1885
|
```
|
|
1807
1886
|
|
|
1887
|
+
Foreground service notifications always use the dedicated Android channel `expo_beacon_foreground_channel`, created with low importance and no sound/vibration. This config only changes the notification content.
|
|
1888
|
+
|
|
1808
1889
|
### `NotificationChannelConfig`
|
|
1809
1890
|
|
|
1810
1891
|
```ts
|
|
@@ -1815,6 +1896,30 @@ type NotificationChannelConfig = {
|
|
|
1815
1896
|
};
|
|
1816
1897
|
```
|
|
1817
1898
|
|
|
1899
|
+
### `CarPlayNotificationConfig`
|
|
1900
|
+
|
|
1901
|
+
```ts
|
|
1902
|
+
type CarPlayNotificationConfig = {
|
|
1903
|
+
enabled?: boolean; // Default: true. Set false to suppress.
|
|
1904
|
+
connectedTitle?: string; // Default: "CarPlay Connected"
|
|
1905
|
+
disconnectedTitle?: string; // Default: "CarPlay Disconnected"
|
|
1906
|
+
body?: string; // Default: "CarPlay session {event}"
|
|
1907
|
+
// Supports {event} and {transport} placeholders.
|
|
1908
|
+
sound?: boolean; // iOS only. Default: true
|
|
1909
|
+
icon?: string; // Android only. Drawable resource name.
|
|
1910
|
+
};
|
|
1911
|
+
```
|
|
1912
|
+
|
|
1913
|
+
### `CarPlayChannelConfig`
|
|
1914
|
+
|
|
1915
|
+
```ts
|
|
1916
|
+
type CarPlayChannelConfig = {
|
|
1917
|
+
name?: string; // Default: "CarPlay / Android Auto"
|
|
1918
|
+
description?: string; // Default: "CarPlay and Android Auto connect/disconnect notifications"
|
|
1919
|
+
importance?: "low" | "default" | "high"; // Default: "default"
|
|
1920
|
+
};
|
|
1921
|
+
```
|
|
1922
|
+
|
|
1818
1923
|
### `BeaconTimeoutEvent`
|
|
1819
1924
|
|
|
1820
1925
|
Payload for `onBeaconTimeout`.
|
|
@@ -2101,7 +2206,7 @@ override fun onCreate() {
|
|
|
2101
2206
|
|
|
2102
2207
|
## Notifications
|
|
2103
2208
|
|
|
2104
|
-
|
|
2209
|
+
Local notifications are posted automatically for beacon enter/exit/timeout events and CarPlay / Android Auto connect/disconnect events. Beacon notifications and CarPlay notifications have separate configuration sections and separate Android channels.
|
|
2105
2210
|
|
|
2106
2211
|
### Default Values
|
|
2107
2212
|
|
|
@@ -2110,16 +2215,25 @@ A local notification is posted automatically for every beacon enter/exit event (
|
|
|
2110
2215
|
| Enter title | `"Beacon Entered"` |
|
|
2111
2216
|
| Exit title | `"Beacon Exited"` |
|
|
2112
2217
|
| Body | `"{identifier} region {event}ed"` |
|
|
2218
|
+
| CarPlay connected title | `"CarPlay Connected"` |
|
|
2219
|
+
| CarPlay disconnected title | `"CarPlay Disconnected"` |
|
|
2220
|
+
| CarPlay body | `"CarPlay session {event}"` |
|
|
2113
2221
|
| Sound (iOS) | `true` |
|
|
2114
2222
|
| Icon (Android) | System `ic_dialog_info` |
|
|
2115
2223
|
| Foreground service title | `"Beacon Monitoring Active"` |
|
|
2116
2224
|
| Foreground service text | `"Monitoring for iBeacons in the background"` |
|
|
2225
|
+
| CarPlay-only foreground title | `"Connected device monitoring active"` |
|
|
2226
|
+
| CarPlay-only foreground text | `"Monitoring connected vehicle (CarPlay/Android Auto)"` |
|
|
2227
|
+
| Foreground channel name (Android) | `"Beacon Foreground Service"` |
|
|
2228
|
+
| Foreground channel importance (Android) | `"low"` (no sound/vibration) |
|
|
2117
2229
|
| Channel name (Android) | `"Beacon Monitoring"` |
|
|
2118
2230
|
| Channel importance (Android) | `"low"` |
|
|
2231
|
+
| CarPlay channel name (Android) | `"CarPlay / Android Auto"` |
|
|
2232
|
+
| CarPlay channel importance (Android) | `"default"` |
|
|
2119
2233
|
|
|
2120
|
-
### Android
|
|
2234
|
+
### Android Channels
|
|
2121
2235
|
|
|
2122
|
-
|
|
2236
|
+
Foreground-service notifications use their own quiet channel ID, `expo_beacon_foreground_channel`, so the persistent status notification does not make sound or vibrate. Beacon event notifications use `expo_beacon_channel`; CarPlay / Android Auto event notifications use `expo_beacon_carplay_channel`. In CarPlay-only mode, the foreground-service notification still uses the quiet foreground channel but reads title/text/icon from `carPlay.foregroundService`.
|
|
2123
2237
|
|
|
2124
2238
|
> **Android channel importance note**: Android prevents decreasing channel importance after the first notification. Increasing works; decreasing has no effect until the user clears notification settings or reinstalls the app.
|
|
2125
2239
|
|
|
@@ -19,6 +19,7 @@ import org.altbeacon.beacon.*
|
|
|
19
19
|
import org.json.JSONArray
|
|
20
20
|
|
|
21
21
|
private const val CHANNEL_ID = "expo_beacon_channel"
|
|
22
|
+
private const val FOREGROUND_CHANNEL_ID = "expo_beacon_foreground_channel"
|
|
22
23
|
private const val CARPLAY_CHANNEL_ID = "expo_beacon_carplay_channel"
|
|
23
24
|
internal const val FOREGROUND_NOTIF_ID = 1001
|
|
24
25
|
/**
|
|
@@ -102,6 +103,7 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
102
103
|
override fun onCreate() {
|
|
103
104
|
super.onCreate()
|
|
104
105
|
activeService = this
|
|
106
|
+
ensureForegroundNotificationChannel(this)
|
|
105
107
|
ensureNotificationChannel(this)
|
|
106
108
|
ensureCarPlayNotificationChannel(this)
|
|
107
109
|
apiForwarder = BeaconApiForwarder(this)
|
|
@@ -947,7 +949,7 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
947
949
|
|
|
948
950
|
private fun showEnterExitNotification(region: Region, eventType: String) {
|
|
949
951
|
val config = readNotificationConfig()
|
|
950
|
-
val eventsConfig = config
|
|
952
|
+
val eventsConfig = notificationSection(config, "beacons", "events", "beaconEvents")
|
|
951
953
|
|
|
952
954
|
// Respect the enabled flag (defaults to true)
|
|
953
955
|
if (eventsConfig != null && !eventsConfig.optBoolean("enabled", true)) return
|
|
@@ -1162,7 +1164,7 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
1162
1164
|
|
|
1163
1165
|
private fun showCarPlayNotification(eventType: String, transport: String?) {
|
|
1164
1166
|
val config = readNotificationConfig()
|
|
1165
|
-
val eventsConfig = config
|
|
1167
|
+
val eventsConfig = notificationSection(config, "carPlay", "events", "carPlayEvents")
|
|
1166
1168
|
|
|
1167
1169
|
// Respect the enabled flag (defaults to true)
|
|
1168
1170
|
if (eventsConfig != null && !eventsConfig.optBoolean("enabled", true)) return
|
|
@@ -1239,6 +1241,7 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
1239
1241
|
.edit()
|
|
1240
1242
|
.putBoolean(MONITORING_ACTIVE_KEY, true)
|
|
1241
1243
|
.apply()
|
|
1244
|
+
ensureForegroundNotificationChannel(context)
|
|
1242
1245
|
ensureNotificationChannel(context)
|
|
1243
1246
|
ensureCarPlayNotificationChannel(context)
|
|
1244
1247
|
val intent = Intent(context, BeaconForegroundService::class.java)
|
|
@@ -1307,6 +1310,7 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
1307
1310
|
*/
|
|
1308
1311
|
fun enableCarPlay(context: Context) {
|
|
1309
1312
|
setCarPlayEnabled(context, true)
|
|
1313
|
+
ensureForegroundNotificationChannel(context)
|
|
1310
1314
|
ensureNotificationChannel(context)
|
|
1311
1315
|
ensureCarPlayNotificationChannel(context)
|
|
1312
1316
|
// Arm the WorkManager watchdog (15-min periodic safety net) and the
|
|
@@ -1468,6 +1472,15 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
1468
1472
|
}
|
|
1469
1473
|
}
|
|
1470
1474
|
|
|
1475
|
+
internal fun notificationSection(
|
|
1476
|
+
config: org.json.JSONObject,
|
|
1477
|
+
parentKey: String,
|
|
1478
|
+
childKey: String,
|
|
1479
|
+
legacyKey: String
|
|
1480
|
+
): org.json.JSONObject? =
|
|
1481
|
+
config.optJSONObject(parentKey)?.optJSONObject(childKey)
|
|
1482
|
+
?: config.optJSONObject(legacyKey)
|
|
1483
|
+
|
|
1471
1484
|
/**
|
|
1472
1485
|
* Resolve the configured small-icon drawable from [config], falling back to a stock icon.
|
|
1473
1486
|
*/
|
|
@@ -1488,13 +1501,21 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
1488
1501
|
private fun ensureChannel(
|
|
1489
1502
|
context: Context,
|
|
1490
1503
|
channelId: String,
|
|
1491
|
-
|
|
1504
|
+
parentKey: String,
|
|
1505
|
+
childKey: String,
|
|
1506
|
+
legacyKey: String,
|
|
1492
1507
|
defaultName: String,
|
|
1493
1508
|
defaultDescription: String,
|
|
1494
1509
|
fallbackImportance: Int
|
|
1495
1510
|
) {
|
|
1496
1511
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
|
|
1497
|
-
val channelConfig =
|
|
1512
|
+
val channelConfig =
|
|
1513
|
+
notificationSection(
|
|
1514
|
+
readNotificationConfig(context),
|
|
1515
|
+
parentKey,
|
|
1516
|
+
childKey,
|
|
1517
|
+
legacyKey
|
|
1518
|
+
)
|
|
1498
1519
|
|
|
1499
1520
|
val channelName =
|
|
1500
1521
|
channelConfig?.optString("name")?.takeIf { it.isNotEmpty() } ?: defaultName
|
|
@@ -1528,6 +1549,8 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
1528
1549
|
ensureChannel(
|
|
1529
1550
|
context,
|
|
1530
1551
|
CHANNEL_ID,
|
|
1552
|
+
"beacons",
|
|
1553
|
+
"channel",
|
|
1531
1554
|
"channel",
|
|
1532
1555
|
"Beacon Monitoring",
|
|
1533
1556
|
"Used for background iBeacon region monitoring",
|
|
@@ -1543,19 +1566,47 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
1543
1566
|
ensureChannel(
|
|
1544
1567
|
context,
|
|
1545
1568
|
CARPLAY_CHANNEL_ID,
|
|
1569
|
+
"carPlay",
|
|
1570
|
+
"channel",
|
|
1546
1571
|
"carPlayChannel",
|
|
1547
1572
|
"CarPlay / Android Auto",
|
|
1548
1573
|
"CarPlay and Android Auto connect/disconnect notifications",
|
|
1549
1574
|
NotificationManager.IMPORTANCE_DEFAULT
|
|
1550
1575
|
)
|
|
1551
1576
|
|
|
1577
|
+
/**
|
|
1578
|
+
* Ensure the persistent foreground-service notification has a quiet channel of its own.
|
|
1579
|
+
* Event channels can be default/high importance, but the always-on service status should
|
|
1580
|
+
* never make sound or vibrate.
|
|
1581
|
+
*/
|
|
1582
|
+
fun ensureForegroundNotificationChannel(context: Context) {
|
|
1583
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
|
|
1584
|
+
val notifMgr = context.getSystemService(NotificationManager::class.java)
|
|
1585
|
+
if (notifMgr?.getNotificationChannel(FOREGROUND_CHANNEL_ID) == null) {
|
|
1586
|
+
val channel =
|
|
1587
|
+
NotificationChannel(
|
|
1588
|
+
FOREGROUND_CHANNEL_ID,
|
|
1589
|
+
"Beacon Foreground Service",
|
|
1590
|
+
NotificationManager.IMPORTANCE_LOW
|
|
1591
|
+
)
|
|
1592
|
+
.apply {
|
|
1593
|
+
description =
|
|
1594
|
+
"Persistent status for beacon and CarPlay background monitoring"
|
|
1595
|
+
setSound(null, null)
|
|
1596
|
+
enableVibration(false)
|
|
1597
|
+
}
|
|
1598
|
+
notifMgr?.createNotificationChannel(channel)
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1552
1602
|
/**
|
|
1553
1603
|
* Build the persistent foreground-service notification from any Context. Static so
|
|
1554
1604
|
* cold-start paths that run before a service instance exists (e.g. [BootReceiver]) read the
|
|
1555
1605
|
* same persisted config.
|
|
1556
1606
|
*/
|
|
1557
1607
|
fun buildForegroundNotification(context: Context): Notification {
|
|
1558
|
-
|
|
1608
|
+
ensureForegroundNotificationChannel(context)
|
|
1609
|
+
val config = readNotificationConfig(context)
|
|
1559
1610
|
|
|
1560
1611
|
// If beacon monitoring is not active and the service is alive only
|
|
1561
1612
|
// for CarPlay observation, fall back to a generic notification so
|
|
@@ -1568,15 +1619,31 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
1568
1619
|
val defaultText =
|
|
1569
1620
|
if (carPlayOnly) "Monitoring connected vehicle (CarPlay/Android Auto)"
|
|
1570
1621
|
else "Monitoring for iBeacons in the background"
|
|
1571
|
-
|
|
1622
|
+
val fgConfig =
|
|
1623
|
+
if (carPlayOnly) {
|
|
1624
|
+
notificationSection(
|
|
1625
|
+
config,
|
|
1626
|
+
"carPlay",
|
|
1627
|
+
"foregroundService",
|
|
1628
|
+
"foregroundService"
|
|
1629
|
+
)
|
|
1630
|
+
} else {
|
|
1631
|
+
notificationSection(
|
|
1632
|
+
config,
|
|
1633
|
+
"beacons",
|
|
1634
|
+
"foregroundService",
|
|
1635
|
+
"foregroundService"
|
|
1636
|
+
)
|
|
1637
|
+
}
|
|
1572
1638
|
val title = fgConfig?.optString("title")?.takeIf { it.isNotEmpty() } ?: defaultTitle
|
|
1573
1639
|
val text = fgConfig?.optString("text")?.takeIf { it.isNotEmpty() } ?: defaultText
|
|
1574
1640
|
|
|
1575
|
-
return NotificationCompat.Builder(context,
|
|
1641
|
+
return NotificationCompat.Builder(context, FOREGROUND_CHANNEL_ID)
|
|
1576
1642
|
.setSmallIcon(resolveIconRes(context, fgConfig))
|
|
1577
1643
|
.setContentTitle(title)
|
|
1578
1644
|
.setContentText(text)
|
|
1579
1645
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
|
1646
|
+
.setSilent(true)
|
|
1580
1647
|
.setOngoing(true)
|
|
1581
1648
|
.build()
|
|
1582
1649
|
}
|