- Ranging
- Monitoring
- Region Monitoring (or geo fencing), works in all app states.
- Advertising device as an iBeacon
- ARMA filter for distance calculations
- Disable request for bluetooth permissions
cordova plugin add https://github.com/petermetz/cordova-plugin-ibeacon.git
The plugin's API closely mimics the one exposed through the CLLocationManager introduced in iOS 7.
Since version 2, the main IBeacon
facade of the DOM is called LocationManager
and it's API is based on promises instead of callbacks.
Another important change of version 2 is that it no longer pollutes the global namespace, instead all the model classes and utilities are accessible
through the cordova.plugins.locationManager
reference chain.
Since version 3.2 the Klass dependency has been removed and therefore means creation of the delegate has changed.
On iOS 8, you have to request permissions from the user of your app explicitly. You can do this through the plugin's API.
See the LocationManager's
related methods: requestWhenInUseAuthorization
and requestAlwaysAuthorization
for further details.
In order to use Advertising (e.g startAdvertising
), the iOS-Capability "Location updates" is required. (set in Xcode -> [your Target] -> Capabilities -> Background Modes -> Location updates)
Standard CLLocationManager functions
/**
* Function that creates a BeaconRegion data transfer object.
*
* @throws Error if the BeaconRegion parameters are not valid.
*/
function createBeacon() {
var uuid = '00000000-0000-0000-0000-000000000000'; // mandatory
var identifier = 'beaconAtTheMacBooks'; // mandatory
var minor = 1000; // optional, defaults to wildcard if left empty
var major = 5; // optional, defaults to wildcard if left empty
// throws an error if the parameters are not valid
var beaconRegion = new cordova.plugins.locationManager.BeaconRegion(identifier, uuid, major, minor);
return beaconRegion;
}
var logToDom = function (message) {
var e = document.createElement('label');
e.innerText = message;
var br = document.createElement('br');
var br2 = document.createElement('br');
document.body.appendChild(e);
document.body.appendChild(br);
document.body.appendChild(br2);
window.scrollTo(0, window.document.height);
};
var delegate = new cordova.plugins.locationManager.Delegate();
delegate.didDetermineStateForRegion = function (pluginResult) {
logToDom('[DOM] didDetermineStateForRegion: ' + JSON.stringify(pluginResult));
cordova.plugins.locationManager.appendToDeviceLog('[DOM] didDetermineStateForRegion: '
+ JSON.stringify(pluginResult));
};
delegate.didStartMonitoringForRegion = function (pluginResult) {
console.log('didStartMonitoringForRegion:', pluginResult);
logToDom('didStartMonitoringForRegion:' + JSON.stringify(pluginResult));
};
delegate.didRangeBeaconsInRegion = function (pluginResult) {
logToDom('[DOM] didRangeBeaconsInRegion: ' + JSON.stringify(pluginResult));
};
var uuid = '00000000-0000-0000-0000-000000000000';
var identifier = 'beaconOnTheMacBooksShelf';
var minor = 1000;
var major = 5;
var beaconRegion = new cordova.plugins.locationManager.BeaconRegion(identifier, uuid, major, minor);
cordova.plugins.locationManager.setDelegate(delegate);
// required in iOS 8+
cordova.plugins.locationManager.requestWhenInUseAuthorization();
// or cordova.plugins.locationManager.requestAlwaysAuthorization()
cordova.plugins.locationManager.startMonitoringForRegion(beaconRegion)
.fail(function(e) { console.error(e); })
.done();
var uuid = '00000000-0000-0000-0000-000000000000';
var identifier = 'beaconOnTheMacBooksShelf';
var minor = 1000;
var major = 5;
var beaconRegion = new cordova.plugins.locationManager.BeaconRegion(identifier, uuid, major, minor);
cordova.plugins.locationManager.stopMonitoringForRegion(beaconRegion)
.fail(function(e) { console.error(e); })
.done();
var logToDom = function (message) {
var e = document.createElement('label');
e.innerText = message;
var br = document.createElement('br');
var br2 = document.createElement('br');
document.body.appendChild(e);
document.body.appendChild(br);
document.body.appendChild(br2);
window.scrollTo(0, window.document.height);
};
var delegate = new cordova.plugins.locationManager.Delegate();
delegate.didDetermineStateForRegion = function (pluginResult) {
logToDom('[DOM] didDetermineStateForRegion: ' + JSON.stringify(pluginResult));
cordova.plugins.locationManager.appendToDeviceLog('[DOM] didDetermineStateForRegion: '
+ JSON.stringify(pluginResult));
};
delegate.didStartMonitoringForRegion = function (pluginResult) {
console.log('didStartMonitoringForRegion:', pluginResult);
logToDom('didStartMonitoringForRegion:' + JSON.stringify(pluginResult));
};
delegate.didRangeBeaconsInRegion = function (pluginResult) {
logToDom('[DOM] didRangeBeaconsInRegion: ' + JSON.stringify(pluginResult));
};
var uuid = '00000000-0000-0000-0000-000000000000';
var identifier = 'beaconOnTheMacBooksShelf';
var minor = 1000;
var major = 5;
var beaconRegion = new cordova.plugins.locationManager.BeaconRegion(identifier, uuid, major, minor);
cordova.plugins.locationManager.setDelegate(delegate);
// required in iOS 8+
cordova.plugins.locationManager.requestWhenInUseAuthorization();
// or cordova.plugins.locationManager.requestAlwaysAuthorization()
cordova.plugins.locationManager.startRangingBeaconsInRegion(beaconRegion)
.fail(function(e) { console.error(e); })
.done();
var uuid = '00000000-0000-0000-0000-000000000000';
var identifier = 'beaconOnTheMacBooksShelf';
var minor = 1000;
var major = 5;
var beaconRegion = new cordova.plugins.locationManager.BeaconRegion(identifier, uuid, major, minor);
cordova.plugins.locationManager.stopRangingBeaconsInRegion(beaconRegion)
.fail(function(e) { console.error(e); })
.done();
cordova.plugins.locationManager.isAdvertisingAvailable()
.then(function(isSupported){
console.log("isSupported: " + isSupported);
})
.fail(function(e) { console.error(e); })
.done();
cordova.plugins.locationManager.isAdvertising()
.then(function(isAdvertising){
console.log("isAdvertising: " + isAdvertising);
})
.fail(function(e) { console.error(e); })
.done();
var uuid = '00000000-0000-0000-0000-000000000000';
var identifier = 'advertisedBeacon';
var minor = 2000;
var major = 5;
var beaconRegion = new cordova.plugins.locationManager.BeaconRegion(identifier, uuid, major, minor);
// The Delegate is optional
var delegate = new cordova.plugins.locationManager.Delegate();
// Event when advertising starts (there may be a short delay after the request)
// The property 'region' provides details of the broadcasting Beacon
delegate.peripheralManagerDidStartAdvertising = function(pluginResult) {
console.log('peripheralManagerDidStartAdvertising: '+ JSON.stringify(pluginResult.region));
};
// Event when bluetooth transmission state changes
// If 'state' is not set to BluetoothManagerStatePoweredOn when advertising cannot start
delegate.peripheralManagerDidUpdateState = function(pluginResult) {
console.log('peripheralManagerDidUpdateState: '+ pluginResult.state);
};
cordova.plugins.locationManager.setDelegate(delegate);
// Verify the platform supports transmitting as a beacon
cordova.plugins.locationManager.isAdvertisingAvailable()
.then(function(isSupported){
if (isSupported) {
cordova.plugins.locationManager.startAdvertising(beaconRegion)
.fail(console.error)
.done();
} else {
console.log("Advertising not supported");
}
})
.fail(function(e) { console.error(e); })
.done();
cordova.plugins.locationManager.stopAdvertising()
.fail(function(e) { console.error(e); })
.done();
cordova.plugins.locationManager.isBluetoothEnabled()
.then(function(isEnabled){
console.log("isEnabled: " + isEnabled);
if (isEnabled) {
cordova.plugins.locationManager.disableBluetooth();
} else {
cordova.plugins.locationManager.enableBluetooth();
}
})
.fail(function(e) { console.error(e); })
.done();
var uuid = cordova.plugins.locationManager.BeaconRegion.WILDCARD_UUID; //wildcard
var identifier = 'SomeIdentifier';
var major = undefined;
var minor = undefined;
var beaconRegion = new cordova.plugins.locationManager.BeaconRegion(identifier, uuid, major, minor);
var logToDom = function (message) {
console.warn(message);
};
var delegate = new cordova.plugins.locationManager.Delegate();
delegate.didDetermineStateForRegion = function (pluginResult) {
logToDom('[DOM] didDetermineStateForRegion: ' + JSON.stringify(pluginResult));
cordova.plugins.locationManager.appendToDeviceLog('[DOM] didDetermineStateForRegion: '
+ JSON.stringify(pluginResult));
};
delegate.didStartMonitoringForRegion = function (pluginResult) {
console.log('didStartMonitoringForRegion:', pluginResult);
logToDom('didStartMonitoringForRegion:' + JSON.stringify(pluginResult));
};
delegate.didRangeBeaconsInRegion = function (pluginResult) {
logToDom('[DOM] didRangeBeaconsInRegion: ' + JSON.stringify(pluginResult));
};
cordova.plugins.locationManager.setDelegate(delegate);
cordova.plugins.locationManager.startMonitoringForRegion(beaconRegion)
.fail(function(e) { console.error(e); })
.done();
The underlying library uses the moving average to calculate distance by default, but an ARMA filter can be enabled which will weigh more recent measurements higher than older measurements. It can be enabled by adding the following preference to your config.xml
file:
<preference name="com.unarin.cordova.beacon.android.altbeacon.EnableArmaFilter" value="true" />
By default, this library requests the user for bluetooth permissions when the app starts. If you would like to request permission in a different way or at a different time, set the following preference in your config.xml
file.
<preference name="com.unarin.cordova.beacon.android.altbeacon.RequestBtPermission" value="false" />
If scheduled scan jobs are enabled, uses a ScanJob
run with the JobScheduler
to perform scans rather than using a long-running BeaconService
to do so. Calling with true on devices older than Android L 5.0 will not apply the change as the JobScheduler is not available. This value defaults to true on Android O+ and false on devices with older OS versions. Accepting the default value of false is recommended on Android N and earlier because otherwise beacon scans may be run only once every 15 minutes in the background, and no low power scans may be performed between scanning cycles. Setting this value to false will disable ScanJobs when the app is run on Android 8+, which can prohibit delivery of callbacks when the app is in the background unless the scanning process is running in a foreground service. To override the defaults, set the following preference in your config.xml
file.
See (AltBeacon docs)[https://altbeacon.github.io/android-beacon-library/javadoc/org/altbeacon/beacon/BeaconManager.html] for more info.
<preference name="com.unarin.cordova.beacon.android.altbeacon.EnableScheduledScanJobs" value="false" />
Contributions are welcome at all times, please make sure that the tests are running without errors before submitting a pull request. The current development branch that you should submit your pull requests against is "v3.x" branch.
This project uses commitlint, please ensure all commit messages pass commitlint before submitting a pull request.
CHANGELOG.md
list meaningful changes since last release, use the format ofgit log --pretty=oneline --abbrev-commit
package.json
bump the versionplugin.xml
bump the version- Publish to both npm packages (due to historical reasons)
$ npm publish
(this publishes undercom.unarin.cordova.beacon
in npm)- Edit
name
property in thepackage.json
file fromcom.unarin.cordova.beacon
tocordova-plugin-ibeacon
(do not commit the change) $ npm publish
again to publish under the legacy package name as well- revert the change you just did in
package.json
- Dart SDK installed on the path (Tested with: 1.2, 1.3, 1.3.3)
- NodeJS
- NPM
- Cordova NPM package (Tested with: 3.4.0-0.1.3)
- XCode (Tested with 5.0.2 and 6.0)
dart test/run_tests.dart
Executing the test runner will do the following:
- Generates a Cordova project
- Add the iOS platform
- Installs the iBeacon plugin from the local file-system.
- Launches XCode by opening the project.
- Open an app which has Cordova iBeacon plugin installed in XCode
- Install it onto a device or simulator
- Open Safari
- Go to the dev tools window
- Paste the code from the examples into the javascript console, it should run without any errors.