@capgo/capacitor-ibeacon 7.0.0
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/CapgoCapacitorIbeacon.podspec +17 -0
- package/LICENSE +21 -0
- package/Package.swift +28 -0
- package/README.md +379 -0
- package/android/build.gradle +59 -0
- package/android/src/main/java/ee/forgr/plugin/capacitor_ibeacon/CapacitorIbeaconPlugin.java +171 -0
- package/dist/docs.json +542 -0
- package/dist/esm/definitions.d.ts +352 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +31 -0
- package/dist/esm/web.js +49 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +63 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +66 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/CapacitorIbeaconPlugin/CapacitorIbeacon.swift +234 -0
- package/ios/Sources/CapacitorIbeaconPlugin/CapacitorIbeaconPlugin.swift +159 -0
- package/package.json +92 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'CapgoCapacitorIbeacon'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.license = package['license']
|
|
10
|
+
s.homepage = package['repository']['url']
|
|
11
|
+
s.author = package['author']
|
|
12
|
+
s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
|
|
13
|
+
s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
14
|
+
s.ios.deployment_target = '14.0'
|
|
15
|
+
s.dependency 'Capacitor'
|
|
16
|
+
s.swift_version = '5.1'
|
|
17
|
+
end
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Martin Donadieu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/Package.swift
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// swift-tools-version: 5.9
|
|
2
|
+
import PackageDescription
|
|
3
|
+
|
|
4
|
+
let package = Package(
|
|
5
|
+
name: "CapgoCapacitorIbeacon",
|
|
6
|
+
platforms: [.iOS(.v14)],
|
|
7
|
+
products: [
|
|
8
|
+
.library(
|
|
9
|
+
name: "CapgoCapacitorIbeacon",
|
|
10
|
+
targets: ["CapacitorIbeaconPlugin"])
|
|
11
|
+
],
|
|
12
|
+
dependencies: [
|
|
13
|
+
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.0.0")
|
|
14
|
+
],
|
|
15
|
+
targets: [
|
|
16
|
+
.target(
|
|
17
|
+
name: "CapacitorIbeaconPlugin",
|
|
18
|
+
dependencies: [
|
|
19
|
+
.product(name: "Capacitor", package: "capacitor-swift-pm"),
|
|
20
|
+
.product(name: "Cordova", package: "capacitor-swift-pm")
|
|
21
|
+
],
|
|
22
|
+
path: "ios/Sources/CapacitorIbeaconPlugin"),
|
|
23
|
+
.testTarget(
|
|
24
|
+
name: "CapacitorIbeaconPluginTests",
|
|
25
|
+
dependencies: ["CapacitorIbeaconPlugin"],
|
|
26
|
+
path: "ios/Tests/CapacitorIbeaconPluginTests")
|
|
27
|
+
]
|
|
28
|
+
)
|
package/README.md
ADDED
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
# capacitor-ibeacon
|
|
2
|
+
<a href="https://capgo.app/"><img src='https://raw.githubusercontent.com/Cap-go/capgo/main/assets/capgo_banner.png' alt='Capgo - Instant updates for capacitor'/></a>
|
|
3
|
+
|
|
4
|
+
<div align="center">
|
|
5
|
+
<h2><a href="https://capgo.app/?ref=plugin"> ➡️ Get Instant updates for your App with Capgo</a></h2>
|
|
6
|
+
<h2><a href="https://capgo.app/consulting/?ref=plugin"> Missing a feature? We'll build the plugin for you 💪</a></h2>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
iBeacon plugin for Capacitor - proximity detection and beacon region monitoring.
|
|
10
|
+
|
|
11
|
+
## Documentation
|
|
12
|
+
|
|
13
|
+
The most complete doc is available here: https://capgo.app/docs/plugins/ibeacon/
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @capgo/capacitor-ibeacon
|
|
19
|
+
npx cap sync
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Configuration
|
|
23
|
+
|
|
24
|
+
### iOS
|
|
25
|
+
|
|
26
|
+
Add the following to your `Info.plist`:
|
|
27
|
+
|
|
28
|
+
```xml
|
|
29
|
+
<key>NSLocationWhenInUseUsageDescription</key>
|
|
30
|
+
<string>This app needs location access to detect nearby beacons</string>
|
|
31
|
+
|
|
32
|
+
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
|
33
|
+
<string>This app needs location access to monitor beacons in the background</string>
|
|
34
|
+
|
|
35
|
+
<key>NSBluetoothAlwaysUsageDescription</key>
|
|
36
|
+
<string>This app uses Bluetooth to detect nearby beacons</string>
|
|
37
|
+
|
|
38
|
+
<key>UIBackgroundModes</key>
|
|
39
|
+
<array>
|
|
40
|
+
<string>location</string>
|
|
41
|
+
</array>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Android
|
|
45
|
+
|
|
46
|
+
Add the following to your `AndroidManifest.xml`:
|
|
47
|
+
|
|
48
|
+
```xml
|
|
49
|
+
<manifest>
|
|
50
|
+
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
51
|
+
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
|
52
|
+
<uses-permission android:name="android.permission.BLUETOOTH" />
|
|
53
|
+
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
|
54
|
+
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
|
55
|
+
</manifest>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Important**: For Android, you need to integrate the [AltBeacon](https://altbeacon.github.io/android-beacon-library/) library into your project for beacon detection to work.
|
|
59
|
+
|
|
60
|
+
Add to your app's `build.gradle`:
|
|
61
|
+
|
|
62
|
+
```gradle
|
|
63
|
+
dependencies {
|
|
64
|
+
implementation 'org.altbeacon:android-beacon-library:2.20+'
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## API
|
|
69
|
+
|
|
70
|
+
All methods are available through the `CapacitorIbeacon` object:
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import { CapacitorIbeacon } from '@capgo/capacitor-ibeacon';
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### startMonitoringForRegion(options: BeaconRegion)
|
|
77
|
+
|
|
78
|
+
Start monitoring for a beacon region. Triggers events when entering/exiting the region.
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
await CapacitorIbeacon.startMonitoringForRegion({
|
|
82
|
+
identifier: 'MyBeaconRegion',
|
|
83
|
+
uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D',
|
|
84
|
+
major: 1,
|
|
85
|
+
minor: 2
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### stopMonitoringForRegion(options: BeaconRegion)
|
|
90
|
+
|
|
91
|
+
Stop monitoring for a beacon region.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
await CapacitorIbeacon.stopMonitoringForRegion({
|
|
95
|
+
identifier: 'MyBeaconRegion',
|
|
96
|
+
uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D'
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### startRangingBeaconsInRegion(options: BeaconRegion)
|
|
101
|
+
|
|
102
|
+
Start ranging beacons in a region. Provides continuous distance updates.
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
await CapacitorIbeacon.startRangingBeaconsInRegion({
|
|
106
|
+
identifier: 'MyBeaconRegion',
|
|
107
|
+
uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D'
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### stopRangingBeaconsInRegion(options: BeaconRegion)
|
|
112
|
+
|
|
113
|
+
Stop ranging beacons in a region.
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
await CapacitorIbeacon.stopRangingBeaconsInRegion({
|
|
117
|
+
identifier: 'MyBeaconRegion',
|
|
118
|
+
uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D'
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### startAdvertising(options: BeaconAdvertisingOptions)
|
|
123
|
+
|
|
124
|
+
Start advertising the device as an iBeacon (iOS only).
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
await CapacitorIbeacon.startAdvertising({
|
|
128
|
+
uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D',
|
|
129
|
+
major: 1,
|
|
130
|
+
minor: 2,
|
|
131
|
+
identifier: 'MyBeacon'
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### stopAdvertising()
|
|
136
|
+
|
|
137
|
+
Stop advertising the device as an iBeacon (iOS only).
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
await CapacitorIbeacon.stopAdvertising();
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### requestWhenInUseAuthorization()
|
|
144
|
+
|
|
145
|
+
Request "When In Use" location authorization.
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
const { status } = await CapacitorIbeacon.requestWhenInUseAuthorization();
|
|
149
|
+
console.log('Authorization status:', status);
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### requestAlwaysAuthorization()
|
|
153
|
+
|
|
154
|
+
Request "Always" location authorization (required for background monitoring).
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
const { status } = await CapacitorIbeacon.requestAlwaysAuthorization();
|
|
158
|
+
console.log('Authorization status:', status);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### getAuthorizationStatus()
|
|
162
|
+
|
|
163
|
+
Get current location authorization status.
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
const { status } = await CapacitorIbeacon.getAuthorizationStatus();
|
|
167
|
+
// status: 'not_determined' | 'restricted' | 'denied' | 'authorized_always' | 'authorized_when_in_use'
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### isBluetoothEnabled()
|
|
171
|
+
|
|
172
|
+
Check if Bluetooth is enabled on the device.
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
const { enabled } = await CapacitorIbeacon.isBluetoothEnabled();
|
|
176
|
+
if (!enabled) {
|
|
177
|
+
console.log('Please enable Bluetooth');
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### isRangingAvailable()
|
|
182
|
+
|
|
183
|
+
Check if ranging is available on the device.
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
const { available } = await CapacitorIbeacon.isRangingAvailable();
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### enableARMAFilter(options: { enabled: boolean })
|
|
190
|
+
|
|
191
|
+
Enable ARMA filtering for distance calculations (Android only).
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
await CapacitorIbeacon.enableARMAFilter({ enabled: true });
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Events
|
|
198
|
+
|
|
199
|
+
Listen to beacon events using Capacitor's event system:
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
import { CapacitorIbeacon } from '@capgo/capacitor-ibeacon';
|
|
203
|
+
import { PluginListenerHandle } from '@capacitor/core';
|
|
204
|
+
|
|
205
|
+
// Listen for ranging events
|
|
206
|
+
const rangingListener: PluginListenerHandle = await CapacitorIbeacon.addListener(
|
|
207
|
+
'didRangeBeacons',
|
|
208
|
+
(data) => {
|
|
209
|
+
console.log('Beacons detected:', data.beacons);
|
|
210
|
+
data.beacons.forEach(beacon => {
|
|
211
|
+
console.log(`Beacon: ${beacon.uuid}, Distance: ${beacon.accuracy}m, Proximity: ${beacon.proximity}`);
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
// Listen for region enter events
|
|
217
|
+
const enterListener: PluginListenerHandle = await CapacitorIbeacon.addListener(
|
|
218
|
+
'didEnterRegion',
|
|
219
|
+
(data) => {
|
|
220
|
+
console.log('Entered region:', data.region.identifier);
|
|
221
|
+
}
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
// Listen for region exit events
|
|
225
|
+
const exitListener: PluginListenerHandle = await CapacitorIbeacon.addListener(
|
|
226
|
+
'didExitRegion',
|
|
227
|
+
(data) => {
|
|
228
|
+
console.log('Exited region:', data.region.identifier);
|
|
229
|
+
}
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
// Listen for region state changes
|
|
233
|
+
const stateListener: PluginListenerHandle = await CapacitorIbeacon.addListener(
|
|
234
|
+
'didDetermineStateForRegion',
|
|
235
|
+
(data) => {
|
|
236
|
+
console.log(`Region ${data.region.identifier}: ${data.state}`);
|
|
237
|
+
}
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
// Clean up listeners when done
|
|
241
|
+
rangingListener.remove();
|
|
242
|
+
enterListener.remove();
|
|
243
|
+
exitListener.remove();
|
|
244
|
+
stateListener.remove();
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Complete Example
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
import { CapacitorIbeacon } from '@capgo/capacitor-ibeacon';
|
|
251
|
+
|
|
252
|
+
// Define your beacon region
|
|
253
|
+
const beaconRegion = {
|
|
254
|
+
identifier: 'MyStore',
|
|
255
|
+
uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D',
|
|
256
|
+
major: 1
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
async function setupBeaconMonitoring() {
|
|
260
|
+
try {
|
|
261
|
+
// Request permission
|
|
262
|
+
const { status } = await CapacitorIbeacon.requestWhenInUseAuthorization();
|
|
263
|
+
|
|
264
|
+
if (status !== 'authorized_when_in_use' && status !== 'authorized_always') {
|
|
265
|
+
console.error('Location permission denied');
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Check if Bluetooth is enabled
|
|
270
|
+
const { enabled } = await CapacitorIbeacon.isBluetoothEnabled();
|
|
271
|
+
if (!enabled) {
|
|
272
|
+
console.error('Bluetooth is not enabled');
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Set up event listeners
|
|
277
|
+
await CapacitorIbeacon.addListener('didEnterRegion', (data) => {
|
|
278
|
+
console.log('Welcome! You entered:', data.region.identifier);
|
|
279
|
+
// Show welcome notification or trigger action
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
await CapacitorIbeacon.addListener('didExitRegion', (data) => {
|
|
283
|
+
console.log('Goodbye! You left:', data.region.identifier);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
await CapacitorIbeacon.addListener('didRangeBeacons', (data) => {
|
|
287
|
+
data.beacons.forEach(beacon => {
|
|
288
|
+
console.log(`Beacon ${beacon.minor}: ${beacon.proximity} (${beacon.accuracy.toFixed(2)}m)`);
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
// Start monitoring
|
|
293
|
+
await CapacitorIbeacon.startMonitoringForRegion(beaconRegion);
|
|
294
|
+
console.log('Started monitoring for beacons');
|
|
295
|
+
|
|
296
|
+
// Start ranging for distance updates
|
|
297
|
+
await CapacitorIbeacon.startRangingBeaconsInRegion(beaconRegion);
|
|
298
|
+
console.log('Started ranging beacons');
|
|
299
|
+
|
|
300
|
+
} catch (error) {
|
|
301
|
+
console.error('Error setting up beacon monitoring:', error);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Call the setup function
|
|
306
|
+
setupBeaconMonitoring();
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## TypeScript Types
|
|
310
|
+
|
|
311
|
+
### BeaconRegion
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
interface BeaconRegion {
|
|
315
|
+
identifier: string;
|
|
316
|
+
uuid: string;
|
|
317
|
+
major?: number;
|
|
318
|
+
minor?: number;
|
|
319
|
+
notifyEntryStateOnDisplay?: boolean;
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Beacon
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
interface Beacon {
|
|
327
|
+
uuid: string;
|
|
328
|
+
major: number;
|
|
329
|
+
minor: number;
|
|
330
|
+
rssi: number;
|
|
331
|
+
proximity: 'immediate' | 'near' | 'far' | 'unknown';
|
|
332
|
+
accuracy: number;
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### BeaconAdvertisingOptions
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
interface BeaconAdvertisingOptions {
|
|
340
|
+
uuid: string;
|
|
341
|
+
major: number;
|
|
342
|
+
minor: number;
|
|
343
|
+
identifier: string;
|
|
344
|
+
measuredPower?: number;
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
## Proximity Values
|
|
349
|
+
|
|
350
|
+
- **immediate**: Very close to the beacon (within a few centimeters)
|
|
351
|
+
- **near**: Relatively close to the beacon (within a couple of meters)
|
|
352
|
+
- **far**: Further away from the beacon (10+ meters)
|
|
353
|
+
- **unknown**: Distance cannot be determined
|
|
354
|
+
|
|
355
|
+
## Important Notes
|
|
356
|
+
|
|
357
|
+
1. **iOS Background Monitoring**: To monitor beacons in the background, you need "Always" location permission and the `location` background mode in Info.plist.
|
|
358
|
+
|
|
359
|
+
2. **Android Library**: Android implementation requires the AltBeacon library to be integrated into your project.
|
|
360
|
+
|
|
361
|
+
3. **Battery Usage**: Continuous beacon ranging can consume significant battery. Consider using monitoring (which is more battery-efficient) and only start ranging when needed.
|
|
362
|
+
|
|
363
|
+
4. **UUID Format**: UUIDs must be in the standard format: `XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX`
|
|
364
|
+
|
|
365
|
+
5. **Major/Minor Values**: These are optional 16-bit unsigned integers (0-65535) used to identify specific beacons within a UUID.
|
|
366
|
+
|
|
367
|
+
6. **Permissions**: Always request and check permissions before starting beacon operations.
|
|
368
|
+
|
|
369
|
+
## Credits
|
|
370
|
+
|
|
371
|
+
This plugin was inspired by [cordova-plugin-ibeacon](https://github.com/petermetz/cordova-plugin-ibeacon) and adapted for Capacitor.
|
|
372
|
+
|
|
373
|
+
## License
|
|
374
|
+
|
|
375
|
+
MIT
|
|
376
|
+
|
|
377
|
+
## Contributing
|
|
378
|
+
|
|
379
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to this plugin.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
ext {
|
|
2
|
+
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
|
|
3
|
+
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1'
|
|
4
|
+
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1'
|
|
5
|
+
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0'
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
buildscript {
|
|
9
|
+
repositories {
|
|
10
|
+
mavenCentral()
|
|
11
|
+
google()
|
|
12
|
+
}
|
|
13
|
+
dependencies {
|
|
14
|
+
classpath 'com.android.tools.build:gradle:8.7.2'
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
apply plugin: 'com.android.library'
|
|
19
|
+
|
|
20
|
+
android {
|
|
21
|
+
namespace "ee.forgr.plugin.capacitor_ibeacon"
|
|
22
|
+
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 35
|
|
23
|
+
defaultConfig {
|
|
24
|
+
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
|
|
25
|
+
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 35
|
|
26
|
+
versionCode 1
|
|
27
|
+
versionName "1.0"
|
|
28
|
+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
29
|
+
}
|
|
30
|
+
buildTypes {
|
|
31
|
+
release {
|
|
32
|
+
minifyEnabled false
|
|
33
|
+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
lintOptions {
|
|
37
|
+
abortOnError false
|
|
38
|
+
}
|
|
39
|
+
compileOptions {
|
|
40
|
+
sourceCompatibility JavaVersion.VERSION_21
|
|
41
|
+
targetCompatibility JavaVersion.VERSION_21
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
repositories {
|
|
46
|
+
google()
|
|
47
|
+
jcenter()
|
|
48
|
+
mavenCentral()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
dependencies {
|
|
53
|
+
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
54
|
+
implementation project(':capacitor-android')
|
|
55
|
+
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
|
56
|
+
testImplementation "junit:junit:$junitVersion"
|
|
57
|
+
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
|
58
|
+
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
|
59
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
package ee.forgr.plugin.capacitor_ibeacon;
|
|
2
|
+
|
|
3
|
+
import android.Manifest;
|
|
4
|
+
import android.bluetooth.BluetoothAdapter;
|
|
5
|
+
import android.content.pm.PackageManager;
|
|
6
|
+
import androidx.core.app.ActivityCompat;
|
|
7
|
+
import com.getcapacitor.JSArray;
|
|
8
|
+
import com.getcapacitor.JSObject;
|
|
9
|
+
import com.getcapacitor.Plugin;
|
|
10
|
+
import com.getcapacitor.PluginCall;
|
|
11
|
+
import com.getcapacitor.PluginMethod;
|
|
12
|
+
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
13
|
+
import com.getcapacitor.annotation.Permission;
|
|
14
|
+
|
|
15
|
+
@CapacitorPlugin(
|
|
16
|
+
name = "CapacitorIbeacon",
|
|
17
|
+
permissions = {
|
|
18
|
+
@Permission(alias = "location", strings = {
|
|
19
|
+
Manifest.permission.ACCESS_FINE_LOCATION,
|
|
20
|
+
Manifest.permission.ACCESS_COARSE_LOCATION
|
|
21
|
+
}),
|
|
22
|
+
@Permission(alias = "bluetooth", strings = {
|
|
23
|
+
Manifest.permission.BLUETOOTH,
|
|
24
|
+
Manifest.permission.BLUETOOTH_ADMIN
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
)
|
|
28
|
+
public class CapacitorIbeaconPlugin extends Plugin {
|
|
29
|
+
|
|
30
|
+
private final String PLUGIN_VERSION = "0.0.1";
|
|
31
|
+
|
|
32
|
+
@Override
|
|
33
|
+
public void load() {
|
|
34
|
+
// Initialize beacon library if needed
|
|
35
|
+
// This requires adding a beacon library like AltBeacon
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@PluginMethod
|
|
39
|
+
public void startMonitoringForRegion(PluginCall call) {
|
|
40
|
+
String identifier = call.getString("identifier");
|
|
41
|
+
String uuid = call.getString("uuid");
|
|
42
|
+
Integer major = call.getInt("major");
|
|
43
|
+
Integer minor = call.getInt("minor");
|
|
44
|
+
|
|
45
|
+
if (identifier == null || uuid == null) {
|
|
46
|
+
call.reject("Missing required parameters");
|
|
47
|
+
return
|
|
48
|
+
;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// TODO: Implement beacon monitoring using AltBeacon or similar library
|
|
52
|
+
call.reject("Beacon monitoring requires AltBeacon library integration");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@PluginMethod
|
|
56
|
+
public void stopMonitoringForRegion(PluginCall call) {
|
|
57
|
+
String identifier = call.getString("identifier");
|
|
58
|
+
String uuid = call.getString("uuid");
|
|
59
|
+
|
|
60
|
+
if (identifier == null || uuid == null) {
|
|
61
|
+
call.reject("Missing required parameters");
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// TODO: Stop monitoring
|
|
66
|
+
call.resolve();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@PluginMethod
|
|
70
|
+
public void startRangingBeaconsInRegion(PluginCall call) {
|
|
71
|
+
String identifier = call.getString("identifier");
|
|
72
|
+
String uuid = call.getString("uuid");
|
|
73
|
+
Integer major = call.getInt("major");
|
|
74
|
+
Integer minor = call.getInt("minor");
|
|
75
|
+
|
|
76
|
+
if (identifier == null || uuid == null) {
|
|
77
|
+
call.reject("Missing required parameters");
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// TODO: Implement beacon ranging
|
|
82
|
+
call.reject("Beacon ranging requires AltBeacon library integration");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@PluginMethod
|
|
86
|
+
public void stopRangingBeaconsInRegion(PluginCall call) {
|
|
87
|
+
String identifier = call.getString("identifier");
|
|
88
|
+
String uuid = call.getString("uuid");
|
|
89
|
+
|
|
90
|
+
if (identifier == null || uuid == null) {
|
|
91
|
+
call.reject("Missing required parameters");
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// TODO: Stop ranging
|
|
96
|
+
call.resolve();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@PluginMethod
|
|
100
|
+
public void startAdvertising(PluginCall call) {
|
|
101
|
+
call.reject("Advertising is not supported on Android through this API");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@PluginMethod
|
|
105
|
+
public void stopAdvertising(PluginCall call) {
|
|
106
|
+
call.reject("Advertising is not supported on Android through this API");
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@PluginMethod
|
|
110
|
+
public void requestWhenInUseAuthorization(PluginCall call) {
|
|
111
|
+
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION)
|
|
112
|
+
!= PackageManager.PERMISSION_GRANTED) {
|
|
113
|
+
requestPermissionForAlias("location", call, "locationPermissionCallback");
|
|
114
|
+
} else {
|
|
115
|
+
JSObject ret = new JSObject();
|
|
116
|
+
ret.put("status", "authorized_when_in_use");
|
|
117
|
+
call.resolve(ret);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@PluginMethod
|
|
122
|
+
public void requestAlwaysAuthorization(PluginCall call) {
|
|
123
|
+
requestWhenInUseAuthorization(call);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@PluginMethod
|
|
127
|
+
public void getAuthorizationStatus(PluginCall call) {
|
|
128
|
+
JSObject ret = new JSObject();
|
|
129
|
+
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION)
|
|
130
|
+
== PackageManager.PERMISSION_GRANTED) {
|
|
131
|
+
ret.put("status", "authorized_when_in_use");
|
|
132
|
+
} else {
|
|
133
|
+
ret.put("status", "denied");
|
|
134
|
+
}
|
|
135
|
+
call.resolve(ret);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@PluginMethod
|
|
139
|
+
public void isBluetoothEnabled(PluginCall call) {
|
|
140
|
+
JSObject ret = new JSObject();
|
|
141
|
+
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
|
142
|
+
ret.put("enabled", bluetoothAdapter != null && bluetoothAdapter.isEnabled());
|
|
143
|
+
call.resolve(ret);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@PluginMethod
|
|
147
|
+
public void isRangingAvailable(PluginCall call) {
|
|
148
|
+
JSObject ret = new JSObject();
|
|
149
|
+
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
|
150
|
+
ret.put("available", bluetoothAdapter != null);
|
|
151
|
+
call.resolve(ret);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
@PluginMethod
|
|
155
|
+
public void enableARMAFilter(PluginCall call) {
|
|
156
|
+
Boolean enabled = call.getBoolean("enabled", false);
|
|
157
|
+
// TODO: Configure ARMA filter if using AltBeacon
|
|
158
|
+
call.resolve();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
@PluginMethod
|
|
162
|
+
public void getPluginVersion(final PluginCall call) {
|
|
163
|
+
try {
|
|
164
|
+
final JSObject ret = new JSObject();
|
|
165
|
+
ret.put("version", this.PLUGIN_VERSION);
|
|
166
|
+
call.resolve(ret);
|
|
167
|
+
} catch (final Exception e) {
|
|
168
|
+
call.reject("Could not get plugin version", e);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|