Native compass heading plugin for Capacitor
npm install @capgo/capacitor-compass
Native compass heading plugin for Capacitor.
The official Capacitor Motion API relies on web APIs for compass/heading data, which provides a suboptimal developer experience:
- Inconsistent behavior across platforms
- Additional permissions handling through web APIs
- Limited accuracy compared to native implementations
- Poor performance on some devices
- No accuracy monitoring to ensure reliable compass readings
This plugin provides true native compass functionality using:
- iOS: CLLocationManager for accurate heading data via CoreLocation
- Android: Hardware sensors (accelerometer + magnetometer) for precise bearing calculation
- Accuracy monitoring: Monitor compass accuracy on Android and prompt users to calibrate when needed
- Event-based API: Modern addListener pattern for real-time heading updates
Essential for navigation apps, augmented reality, location-based games, and any app needing accurate compass heading.
| Plugin version | Capacitor compatibility | Maintained |
| -------------- | ----------------------- | ---------- |
| v8.\.\ | v8.\.\ | ✅ |
| v7.\.\ | v7.\.\ | On demand |
| v6.\.\ | v6.\.\ | ❌ |
| v5.\.\ | v5.\.\ | ❌ |
> Note: The major version of this plugin follows the major version of Capacitor. Use the version that matches your Capacitor installation (e.g., plugin v8 for Capacitor 8). Only the latest major version is actively maintained.
``bash`
npm install @capgo/capacitor-compass
npx cap sync
Add the following to your Info.plist:
`xml`
No additional setup required. The plugin uses the device's accelerometer and magnetometer sensors.
`typescript
import { CapgoCompass, CompassAccuracy } from '@capgo/capacitor-compass';
// Get current heading once
const { value } = await CapgoCompass.getCurrentHeading();
console.log('Current heading:', value, 'degrees');
// Listen for continuous heading updates
const handle = await CapgoCompass.addListener('headingChange', (event) => {
console.log('Heading:', event.value, 'degrees');
});
// Start the compass sensor
await CapgoCompass.startListening();
// Monitor compass accuracy (Android only)
const accuracyHandle = await CapgoCompass.addListener('accuracyChange', (event) => {
console.log('Compass accuracy:', event.accuracy);
if (event.accuracy < CompassAccuracy.MEDIUM) {
console.log('Compass needs calibration');
// Show your own custom UI to prompt user to calibrate
}
});
// Start accuracy monitoring
await CapgoCompass.watchAccuracy();
// Get current accuracy
const { accuracy } = await CapgoCompass.getAccuracy();
console.log('Current accuracy:', accuracy);
// Later: stop listening
await CapgoCompass.stopListening();
await CapgoCompass.unwatchAccuracy();
await handle.remove();
await accuracyHandle.remove();
`
* getCurrentHeading()
* getPluginVersion()
* startListening(...)
* stopListening()
* addListener('headingChange', ...)
* addListener('accuracyChange', ...)
* removeAllListeners()
* checkPermissions()
* requestPermissions()
* watchAccuracy()
* unwatchAccuracy()
* getAccuracy()
* Interfaces
* Type Aliases
* Enums
Capacitor Compass Plugin interface for reading device compass heading.
`typescript`
getCurrentHeading() => Promise
Get the current compass heading in degrees.
On iOS, the heading is updated in the background, and the latest value is returned.
On Android, the heading is calculated when the method is called using accelerometer and magnetometer sensors.
Not implemented on Web.
Returns: Promise<CompassHeading>
Since: 7.0.0
--------------------
`typescript`
getPluginVersion() => Promise<{ version: string; }>
Get the native Capacitor plugin version.
Returns: Promise<{ version: string; }>
Since: 7.0.0
--------------------
`typescript`
startListening(options?: ListeningOptions | undefined) => Promise
Start listening for compass heading changes via events.
This starts the compass sensors and emits 'headingChange' events.
| Param | Type | Description |
| ------------- | ------------------------------------------------------------- | ------------------------------------------------ |
| options | ListeningOptions | - Optional configuration for throttling behavior |
Since: 7.0.0
--------------------
`typescript`
stopListening() => Promise
Stop listening for compass heading changes.
This stops the compass sensors and stops emitting events.
Since: 7.0.0
--------------------
`typescript`
addListener(eventName: 'headingChange', listenerFunc: (event: HeadingChangeEvent) => void) => Promise<{ remove: () => Promise
Add a listener for compass heading change events.
| Param | Type | Description |
| ------------------ | ------------------------------------------------------------------------------------- | ------------------------------------------------ |
| eventName | 'headingChange' | - The event to listen for ('headingChange') |
| listenerFunc | (event: HeadingChangeEvent) => void | - The function to call when the event is emitted |
Returns: Promise<{ remove: () => Promise<void>; }>
Since: 7.0.0
--------------------
`typescript`
addListener(eventName: 'accuracyChange', listenerFunc: (event: AccuracyChangeEvent) => void) => Promise<{ remove: () => Promise
Add a listener for compass accuracy change events.
Only supported on Android. On iOS and Web, this will never emit events.
| Param | Type | Description |
| ------------------ | --------------------------------------------------------------------------------------- | ------------------------------------------------ |
| eventName | 'accuracyChange' | - The event to listen for ('accuracyChange') |
| listenerFunc | (event: AccuracyChangeEvent) => void | - The function to call when the event is emitted |
Returns: Promise<{ remove: () => Promise<void>; }>
Since: 8.2.0
--------------------
`typescript`
removeAllListeners() => Promise
Remove all listeners for this plugin.
Since: 7.0.0
--------------------
`typescript`
checkPermissions() => Promise
Check the current permission status for accessing compass data.
On iOS, this checks location permission status.
On Android, this always returns 'granted' as no permissions are required.
Returns: Promise<PermissionStatus>
Since: 7.0.0
--------------------
`typescript`
requestPermissions() => Promise
Request permission to access compass data.
On iOS, this requests location permission (required for heading data).
On Android, this resolves immediately as no permissions are required.
Returns: Promise<PermissionStatus>
Since: 7.0.0
--------------------
`typescript`
watchAccuracy() => Promise
Start monitoring compass accuracy.
On Android, this monitors the magnetometer accuracy and emits accuracyChange events.
Developers can listen to these events and implement their own UI for calibration prompts.
On iOS and Web, this method does nothing as compass accuracy monitoring is not available.
Since: 8.2.0
--------------------
`typescript`
unwatchAccuracy() => Promise
Stop monitoring compass accuracy.
This stops the accuracy monitoring.
Since: 8.2.0
--------------------
`typescript`
getAccuracy() => Promise<{ accuracy: CompassAccuracy; }>
Get the current compass accuracy level.
On Android, returns the current magnetometer sensor accuracy.
On iOS and Web, always returns CompassAccuracy.UNKNOWN as accuracy monitoring is not available.
Returns: Promise<{ accuracy: CompassAccuracy; }>
Since: 8.2.0
--------------------
#### CompassHeading
Result containing the compass heading value.
| Prop | Type | Description |
| ----------- | ------------------- | ---------------------------------- |
| value | number | Compass heading in degrees (0-360) |
#### ListeningOptions
Options for configuring compass listening behavior.
| Prop | Type | Description | Default | Since |
| ---------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | ----- |
| minInterval | number | Minimum interval between heading change events in milliseconds. Lower values = more frequent updates but higher CPU/battery usage. | 100 | 8.1.4 |
| minHeadingChange | number | Minimum heading change in degrees required to trigger an event. Lower values = more sensitive but more events. Handles wraparound (e.g., 359° to 1° = 2° change). | 2.0 | 8.1.4 |
#### HeadingChangeEvent
Event data for heading change events.
| Prop | Type | Description |
| ----------- | ------------------- | ---------------------------------- |
| value | number | Compass heading in degrees (0-360) |
#### AccuracyChangeEvent
Event data for accuracy change events.
| Prop | Type | Description |
| -------------- | ----------------------------------------------------------- | ------------------------------------- |
| accuracy | CompassAccuracy | Current accuracy level of the compass |
#### PermissionStatus
Permission status for compass plugin.
| Prop | Type | Description | Since |
| ------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
| compass | PermissionState | Permission state for accessing compass/location data. On iOS, this requires location permission to access heading. On Android, no special permissions are required for compass sensors. | 7.0.0 |
#### PermissionState
'prompt' | 'prompt-with-rationale' | 'granted' | 'denied'
#### CompassAccuracy
| Members | Value | Description |
| ---------------- | --------------- | ------------------------------------------------------------------- |
| HIGH | 3 | High accuracy - approximates to less than 5 degrees of error |
| MEDIUM | 2 | Medium accuracy - approximates to less than 10 degrees of error |
| LOW | 1 | Low accuracy - approximates to less than 15 degrees of error |
| UNRELIABLE | 0 | Unreliable accuracy - approximates to more than 15 degrees of error |
| UNKNOWN` | -1 | Unknown accuracy value |
This plugin is inspired by capacitor-native-compass by HeyItsBATMAN.