@capgo/capacitor-ibeacon 8.1.2 → 8.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 CHANGED
@@ -194,6 +194,34 @@ Enable ARMA filtering for distance calculations (Android only).
194
194
  await CapacitorIbeacon.enableARMAFilter({ enabled: true });
195
195
  ```
196
196
 
197
+ ### Android background scanning
198
+
199
+ Android 8+ requires a foreground service to keep Bluetooth scanning alive in the background. You can opt in once and the plugin will automatically
200
+ toggle background scanning when the app moves between foreground and background.
201
+
202
+ ```typescript
203
+ // Enable background scanning globally (Android only)
204
+ await CapacitorIbeacon.enableBackgroundMode({ enabled: true });
205
+
206
+ // Or opt in per call
207
+ await CapacitorIbeacon.startMonitoringForRegion({
208
+ identifier: 'MyBeaconRegion',
209
+ uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D',
210
+ enableBackgroundMode: true,
211
+ });
212
+ ```
213
+
214
+ You can also enable it via Capacitor config:
215
+
216
+ ```typescript
217
+ // capacitor.config.ts
218
+ plugins: {
219
+ CapacitorIbeacon: {
220
+ enableBackgroundMode: true,
221
+ },
222
+ }
223
+ ```
224
+
197
225
  ## Events
198
226
 
199
227
  Listen to beacon events using Capacitor's event system:
@@ -43,11 +43,16 @@ import org.altbeacon.beacon.Region;
43
43
  )
44
44
  public class CapacitorIbeaconPlugin extends Plugin implements BeaconConsumer {
45
45
 
46
- private final String pluginVersion = "8.1.2";
46
+ private final String pluginVersion = "8.1.3";
47
+ private static final String FOREGROUND_CHANNEL_ID = "beacon_service_channel";
48
+ private static final int FOREGROUND_NOTIFICATION_ID = 456;
47
49
  private BeaconManager beaconManager;
48
50
  private Map<String, Region> monitoredRegions = new HashMap<>();
49
51
  private Map<String, Region> rangedRegions = new HashMap<>();
50
52
  private boolean beaconManagerBound = false;
53
+ private boolean backgroundModeEnabled = false;
54
+ private boolean foregroundServiceEnabled = false;
55
+ private boolean isInBackground = false;
51
56
 
52
57
  @Override
53
58
  public void load() {
@@ -102,10 +107,16 @@ public class CapacitorIbeaconPlugin extends Plugin implements BeaconConsumer {
102
107
  }
103
108
  }
104
109
  );
110
+
111
+ Boolean configBackgroundMode = getConfig().getBoolean("enableBackgroundMode", false);
112
+ if (configBackgroundMode != null && configBackgroundMode) {
113
+ backgroundModeEnabled = true;
114
+ }
105
115
  }
106
116
 
107
117
  @Override
108
118
  protected void handleOnDestroy() {
119
+ applyBackgroundMode(false);
109
120
  if (beaconManager != null && beaconManagerBound) {
110
121
  beaconManager.unbind(this);
111
122
  beaconManagerBound = false;
@@ -113,6 +124,20 @@ public class CapacitorIbeaconPlugin extends Plugin implements BeaconConsumer {
113
124
  super.handleOnDestroy();
114
125
  }
115
126
 
127
+ @Override
128
+ protected void handleOnPause() {
129
+ super.handleOnPause();
130
+ isInBackground = true;
131
+ applyBackgroundMode(backgroundModeEnabled);
132
+ }
133
+
134
+ @Override
135
+ protected void handleOnResume() {
136
+ super.handleOnResume();
137
+ isInBackground = false;
138
+ applyBackgroundMode(backgroundModeEnabled);
139
+ }
140
+
116
141
  @Override
117
142
  public void onBeaconServiceConnect() {
118
143
  beaconManagerBound = true;
@@ -139,6 +164,7 @@ public class CapacitorIbeaconPlugin extends Plugin implements BeaconConsumer {
139
164
  String uuid = call.getString("uuid");
140
165
  Integer major = call.getInt("major");
141
166
  Integer minor = call.getInt("minor");
167
+ Boolean enableBackgroundMode = call.getBoolean("enableBackgroundMode");
142
168
 
143
169
  if (identifier == null || uuid == null) {
144
170
  call.reject("Missing required parameters");
@@ -146,6 +172,9 @@ public class CapacitorIbeaconPlugin extends Plugin implements BeaconConsumer {
146
172
  }
147
173
 
148
174
  try {
175
+ if (enableBackgroundMode != null) {
176
+ setBackgroundModeEnabled(enableBackgroundMode);
177
+ }
149
178
  Region region = createRegion(identifier, uuid, major, minor);
150
179
  monitoredRegions.put(identifier, region);
151
180
  beaconManager.startMonitoring(region);
@@ -183,6 +212,7 @@ public class CapacitorIbeaconPlugin extends Plugin implements BeaconConsumer {
183
212
  String uuid = call.getString("uuid");
184
213
  Integer major = call.getInt("major");
185
214
  Integer minor = call.getInt("minor");
215
+ Boolean enableBackgroundMode = call.getBoolean("enableBackgroundMode");
186
216
 
187
217
  if (identifier == null || uuid == null) {
188
218
  call.reject("Missing required parameters");
@@ -190,6 +220,9 @@ public class CapacitorIbeaconPlugin extends Plugin implements BeaconConsumer {
190
220
  }
191
221
 
192
222
  try {
223
+ if (enableBackgroundMode != null) {
224
+ setBackgroundModeEnabled(enableBackgroundMode);
225
+ }
193
226
  Region region = createRegion(identifier, uuid, major, minor);
194
227
  rangedRegions.put(identifier, region);
195
228
  beaconManager.startRangingBeacons(region);
@@ -525,44 +558,7 @@ public class CapacitorIbeaconPlugin extends Plugin implements BeaconConsumer {
525
558
  public void enableBackgroundMode(PluginCall call) {
526
559
  Boolean enabled = call.getBoolean("enabled", true);
527
560
  try {
528
- if (enabled != null && enabled) {
529
- // Enable foreground service for background beacon scanning
530
- // This is required on Android 8+ for reliable background operation
531
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
532
- // Create notification channel for foreground service
533
- android.app.NotificationChannel channel = new android.app.NotificationChannel(
534
- "beacon_service_channel",
535
- "Beacon Service",
536
- android.app.NotificationManager.IMPORTANCE_LOW
537
- );
538
- channel.setDescription("Background beacon monitoring service");
539
-
540
- android.app.NotificationManager notificationManager = getContext().getSystemService(
541
- android.app.NotificationManager.class
542
- );
543
- if (notificationManager != null) {
544
- notificationManager.createNotificationChannel(channel);
545
- }
546
-
547
- // Build notification for foreground service
548
- android.app.Notification.Builder builder = new android.app.Notification.Builder(getContext(), "beacon_service_channel");
549
- builder.setSmallIcon(android.R.drawable.ic_dialog_info);
550
- builder.setContentTitle("Beacon Monitoring");
551
- builder.setContentText("Scanning for nearby beacons");
552
-
553
- // Enable foreground service mode in AltBeacon
554
- beaconManager.enableForegroundServiceScanning(builder.build(), 456);
555
- }
556
-
557
- // Set background mode
558
- beaconManager.setBackgroundMode(true);
559
- } else {
560
- // Disable background mode
561
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
562
- beaconManager.disableForegroundServiceScanning();
563
- }
564
- beaconManager.setBackgroundMode(false);
565
- }
561
+ setBackgroundModeEnabled(enabled != null && enabled);
566
562
  call.resolve();
567
563
  } catch (Exception e) {
568
564
  call.reject("Failed to enable background mode", e);
@@ -690,4 +686,63 @@ public class CapacitorIbeaconPlugin extends Plugin implements BeaconConsumer {
690
686
  return "far";
691
687
  }
692
688
  }
689
+
690
+ private void setBackgroundModeEnabled(boolean enabled) {
691
+ backgroundModeEnabled = enabled;
692
+ applyBackgroundMode(enabled);
693
+ }
694
+
695
+ private void applyBackgroundMode(boolean enabled) {
696
+ if (beaconManager == null) {
697
+ return;
698
+ }
699
+
700
+ boolean shouldEnableBackgroundMode = enabled && isInBackground;
701
+
702
+ if (shouldEnableBackgroundMode) {
703
+ enableForegroundServiceIfNeeded();
704
+ beaconManager.setBackgroundMode(true);
705
+ } else {
706
+ disableForegroundServiceIfNeeded();
707
+ beaconManager.setBackgroundMode(false);
708
+ }
709
+ }
710
+
711
+ private void enableForegroundServiceIfNeeded() {
712
+ if (foregroundServiceEnabled || Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
713
+ return;
714
+ }
715
+
716
+ // Create notification channel for foreground service
717
+ android.app.NotificationChannel channel = new android.app.NotificationChannel(
718
+ FOREGROUND_CHANNEL_ID,
719
+ "Beacon Service",
720
+ android.app.NotificationManager.IMPORTANCE_LOW
721
+ );
722
+ channel.setDescription("Background beacon monitoring service");
723
+
724
+ android.app.NotificationManager notificationManager = getContext().getSystemService(android.app.NotificationManager.class);
725
+ if (notificationManager != null) {
726
+ notificationManager.createNotificationChannel(channel);
727
+ }
728
+
729
+ // Build notification for foreground service
730
+ android.app.Notification.Builder builder = new android.app.Notification.Builder(getContext(), FOREGROUND_CHANNEL_ID);
731
+ builder.setSmallIcon(android.R.drawable.ic_dialog_info);
732
+ builder.setContentTitle("Beacon Monitoring");
733
+ builder.setContentText("Scanning for nearby beacons");
734
+
735
+ // Enable foreground service mode in AltBeacon
736
+ beaconManager.enableForegroundServiceScanning(builder.build(), FOREGROUND_NOTIFICATION_ID);
737
+ foregroundServiceEnabled = true;
738
+ }
739
+
740
+ private void disableForegroundServiceIfNeeded() {
741
+ if (!foregroundServiceEnabled || Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
742
+ return;
743
+ }
744
+
745
+ beaconManager.disableForegroundServiceScanning();
746
+ foregroundServiceEnabled = false;
747
+ }
693
748
  }
package/dist/docs.json CHANGED
@@ -820,6 +820,13 @@
820
820
  "docs": "Notify when device enters region (iOS only).",
821
821
  "complexTypes": [],
822
822
  "type": "boolean | undefined"
823
+ },
824
+ {
825
+ "name": "enableBackgroundMode",
826
+ "tags": [],
827
+ "docs": "Enable Android background mode for this monitoring/ranging call.\nWhen true, the plugin will keep scanning in background using a foreground service.",
828
+ "complexTypes": [],
829
+ "type": "boolean | undefined"
823
830
  }
824
831
  ]
825
832
  },
@@ -374,6 +374,11 @@ export interface BeaconRegion {
374
374
  * Notify when device enters region (iOS only).
375
375
  */
376
376
  notifyEntryStateOnDisplay?: boolean;
377
+ /**
378
+ * Enable Android background mode for this monitoring/ranging call.
379
+ * When true, the plugin will keep scanning in background using a foreground service.
380
+ */
381
+ enableBackgroundMode?: boolean;
377
382
  }
378
383
  /**
379
384
  * Background scan period configuration options (Android only).
@@ -4,7 +4,7 @@ import CoreLocation
4
4
 
5
5
  @objc(CapacitorIbeaconPlugin)
6
6
  public class CapacitorIbeaconPlugin: CAPPlugin, CAPBridgedPlugin {
7
- private let pluginVersion: String = "8.1.2"
7
+ private let pluginVersion: String = "8.1.3"
8
8
  public let identifier = "CapacitorIbeaconPlugin"
9
9
  public let jsName = "CapacitorIbeacon"
10
10
  public let pluginMethods: [CAPPluginMethod] = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-ibeacon",
3
- "version": "8.1.2",
3
+ "version": "8.1.3",
4
4
  "description": "iBeacon plugin for Capacitor - proximity detection and beacon region monitoring",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",