expo-beacon 0.6.7 → 0.6.8
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.
|
@@ -76,29 +76,31 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
76
76
|
// Increase AltBeacon's region exit period so didExitRegion doesn't fire
|
|
77
77
|
// prematurely during brief BLE scan gaps.
|
|
78
78
|
BeaconManager.setRegionExitPeriod(REGION_EXIT_PERIOD_MS)
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
buildForegroundNotification(), FOREGROUND_NOTIF_ID
|
|
86
|
-
)
|
|
87
|
-
} catch (e: IllegalStateException) {
|
|
88
|
-
// Already bound by another consumer (e.g. a scan in progress) — non-fatal.
|
|
89
|
-
Log.w(TAG, "enableForegroundServiceScanning skipped (already bound)", e)
|
|
90
|
-
}
|
|
79
|
+
// NOTE: We intentionally do NOT call enableForegroundServiceScanning().
|
|
80
|
+
// Our BeaconForegroundService is already a foreground service (startForeground
|
|
81
|
+
// in onStartCommand). AltBeacon's internal BeaconService runs in the same
|
|
82
|
+
// process and inherits the elevated priority. Calling enable/disable on the
|
|
83
|
+
// shared singleton causes crashes when the ExpoBeaconModule has an active
|
|
84
|
+
// scan bound to the same BeaconManager.
|
|
91
85
|
}
|
|
92
86
|
|
|
93
87
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
88
|
+
try {
|
|
89
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
90
|
+
startForeground(
|
|
91
|
+
FOREGROUND_NOTIF_ID,
|
|
92
|
+
buildForegroundNotification(),
|
|
93
|
+
ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE
|
|
94
|
+
)
|
|
95
|
+
} else {
|
|
96
|
+
startForeground(FOREGROUND_NOTIF_ID, buildForegroundNotification())
|
|
97
|
+
}
|
|
98
|
+
} catch (e: Exception) {
|
|
99
|
+
// SecurityException on Android 14+ if BT permissions missing,
|
|
100
|
+
// or other platform-specific issues. Stop gracefully instead of crashing.
|
|
101
|
+
Log.e(TAG, "startForeground failed — stopping service", e)
|
|
102
|
+
stopSelf()
|
|
103
|
+
return START_NOT_STICKY
|
|
102
104
|
}
|
|
103
105
|
if (serviceConnected) {
|
|
104
106
|
// Already bound from a prior onStartCommand — reload regions directly
|
|
@@ -590,6 +592,7 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
590
592
|
fun start(context: Context) {
|
|
591
593
|
context.getSharedPreferences(PREF_IS_MONITORING, Context.MODE_PRIVATE)
|
|
592
594
|
.edit().putBoolean("active", true).apply()
|
|
595
|
+
ensureNotificationChannel(context)
|
|
593
596
|
val intent = Intent(context, BeaconForegroundService::class.java)
|
|
594
597
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
595
598
|
context.startForegroundService(intent)
|
|
@@ -700,7 +703,6 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
700
703
|
monitoredRegions.forEach {
|
|
701
704
|
try { beaconManager.stopMonitoringBeaconsInRegion(it) } catch (_: RemoteException) {}
|
|
702
705
|
}
|
|
703
|
-
try { beaconManager.disableForegroundServiceScanning() } catch (_: Exception) {}
|
|
704
706
|
beaconManager.unbind(this)
|
|
705
707
|
super.onDestroy()
|
|
706
708
|
}
|
|
@@ -327,9 +327,25 @@ class ExpoBeaconModule : Module(), BeaconConsumer {
|
|
|
327
327
|
promise.reject("PERMISSION_DENIED", "Location permissions required for background monitoring. Call requestPermissionsAsync() first.", null)
|
|
328
328
|
return@AsyncFunction
|
|
329
329
|
}
|
|
330
|
+
// Android 12+ requires BLUETOOTH_SCAN for BLE operations;
|
|
331
|
+
// Android 14+ additionally requires it for connectedDevice foreground services.
|
|
332
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
333
|
+
val hasBtScan = ContextCompat.checkSelfPermission(ctx, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED
|
|
334
|
+
val hasBtConnect = ContextCompat.checkSelfPermission(ctx, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED
|
|
335
|
+
if (!hasBtScan || !hasBtConnect) {
|
|
336
|
+
promise.reject("PERMISSION_DENIED", "Bluetooth permissions required for beacon monitoring. Call requestPermissionsAsync() first.", null)
|
|
337
|
+
return@AsyncFunction
|
|
338
|
+
}
|
|
339
|
+
}
|
|
330
340
|
|
|
331
341
|
registerEventReceiver()
|
|
332
|
-
|
|
342
|
+
try {
|
|
343
|
+
BeaconForegroundService.start(ctx)
|
|
344
|
+
} catch (e: Exception) {
|
|
345
|
+
unregisterEventReceiver()
|
|
346
|
+
promise.reject("SERVICE_START_FAILED", "Failed to start monitoring service: ${e.message}", e)
|
|
347
|
+
return@AsyncFunction
|
|
348
|
+
}
|
|
333
349
|
promise.resolve(null)
|
|
334
350
|
}
|
|
335
351
|
|
|
@@ -345,7 +361,6 @@ class ExpoBeaconModule : Module(), BeaconConsumer {
|
|
|
345
361
|
return@AsyncFunction
|
|
346
362
|
}
|
|
347
363
|
BeaconForegroundService.stop(ctx)
|
|
348
|
-
try { beaconManager.disableForegroundServiceScanning() } catch (_: Exception) {}
|
|
349
364
|
unregisterEventReceiver()
|
|
350
365
|
promise.resolve(null)
|
|
351
366
|
}
|