flutter_device_compass 2.1.0
flutter_device_compass: ^2.1.0 copied to clipboard
A Flutter compass plugin using device sensors. Heading is 0-360 degrees (0 = north).
flutter_device_compass #
A Flutter compass plugin using device sensors. Provides real-time device heading, orientation-compensated azimuth (0°–360°, where 0° is North), camera-mode heading for AR/camera overlays, and sensor accuracy.
Community-maintained fork of medyas/flutter_compass_v2 (lineage from hemanthrajv/flutter_compass), republished as flutter_device_compass on pub.dev for ongoing maintenance and modern Flutter (3.24+ / 3.44+) & Gradle/Kotlin compatibility.
Features #
- 🧭 Heading Calculation: 0° to 360°, where 0° is North.
- 📱 Orientation-Aware: Automatically compensates for device orientation changes (Portrait, Landscape Left, Landscape Right, Portrait Upside Down).
- 📷 Camera Mode Heading: Heading out the back of the device (
headingForCameraMode), ideal for Augmented Reality (AR) or camera overlays. - 🎯 Sensor Accuracy: Exposes calibration and accuracy deviation in degrees (
accuracy). - 🔍 Hardware Detection: Proactively check sensor availability via
FlutterCompass.hasSensorsbefore mounting compass views. - ⚡ Robust Sensor Fallbacks: Uses
Sensor.TYPE_ROTATION_VECTORon Android when available with low-pass filtered accelerometer + magnetometer fallback. - 🛡️ Crash-Resistant: Guarded against non-finite /
NaNsensor readings and negative true headings.
Getting Started #
Add flutter_device_compass to your pubspec.yaml:
dependencies:
flutter_device_compass: ^2.1.0
Platform Setup #
iOS #
iOS requires location permissions to deliver compass/heading updates via CoreLocation.
Add the following keys to your ios/Runner/Info.plist:
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to heading and compass data to orient the map.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs access to heading and compass data to orient the map.</string>
Note: Use a permission package like
permission_handlerto request location permissions at runtime before listening to compass events on iOS.
Android #
No additional permissions are strictly required for sensor access. However, if your app utilizes fine location for geomagnetic declination or maps alongside the compass, add the following to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Usage Examples #
1. Basic Stream Subscription #
import 'package:flutter_device_compass/flutter_device_compass.dart';
// Subscribe to compass updates
final subscription = FlutterCompass.events?.listen((CompassEvent event) {
print('Heading: ${event.heading}°');
print('Camera Mode Heading: ${event.headingForCameraMode}°');
print('Accuracy Deviation: ±${event.accuracy}°');
});
// Cancel when no longer needed
// subscription?.cancel();
2. Building a Rotating Compass UI (StreamBuilder) #
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter_device_compass/flutter_device_compass.dart';
class CompassWidget extends StatelessWidget {
const CompassWidget({super.key});
@override
Widget build(BuildContext context) {
return StreamBuilder<CompassEvent>(
stream: FlutterCompass.events,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
}
final heading = snapshot.data?.heading;
// On devices without compass sensors, heading will be null
if (heading == null) {
return const Center(
child: Text('Device does not have compass sensors'),
);
}
return Center(
child: Transform.rotate(
angle: (heading * (math.pi / 180) * -1),
child: Image.asset(
'assets/compass.png',
width: 250,
height: 250,
),
),
);
},
);
}
}
3. Check Sensor Availability #
Before initiating compass-dependent features, you can verify if the device hardware supports compass sensors:
final bool? isSupported = await FlutterCompass.hasSensors;
if (isSupported == true) {
print('Compass sensor is available on this device');
} else {
print('Device does not support compass/heading sensors');
}
4. Read Current Heading Once #
If you only need a single heading snapshot (e.g. when capturing a photo or logging location):
Future<void> logCurrentHeading() async {
final CompassEvent event = await FlutterCompass.events!.first;
print('Current heading is: ${event.heading}°');
}
CompassEvent Reference #
| Property | Type | Description |
|---|---|---|
heading |
double? |
The device heading in degrees around its Z-axis (pointing direction of the top of the phone). Range: 0.0 to 360.0, where 0.0 is North. null if sensor is unavailable. |
headingForCameraMode |
double? |
The heading in degrees around the device's X-axis (pointing out the back of the phone). Ideal for camera and AR alignment. |
accuracy |
double? |
Estimated deviation error in degrees (±). null if uncalibrated or unavailable. |
Maintainer #
Maintained with ❤️ by Nafis Kabbo.
Contributions, issues, and feature requests are welcome on GitHub!