pinpoint_sdk 12.2.0+21
pinpoint_sdk: ^12.2.0+21 copied to clipboard
The Pinpoint SDK is a cross-platform (Android/iOS) Flutter plugin for positioning with Pinpoint's technology.
example/lib/main.dart
import 'dart:async';
import 'package:example/widgets.dart';
import 'package:flutter/material.dart';
import 'package:pinpoint_sdk/pinpoint_sdk.dart';
void main() {
// initialize Geolocator
// Note: the API key will become mandatory in a future release, at the moment it is still optional.
initGeolocator(apiKey: 'myApiKey');
runApp(MaterialApp(home: Example()));
}
class Example extends StatefulWidget {
const Example({super.key});
@override
State<Example> createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
/// Position stream that tracks the current location updates.
Stream<Position>? _positioningStream;
/// [Wgs84Reference] for the indoor position.
/// This includes the latitude, longitude and azimuth.
Wgs84Reference? _wgs84Reference;
/// Determines if the [_positioningStream] is null.
bool get _isPositioning => _positioningStream != null;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('assets/Pin-Round-Orange@128px.png', height: 32),
const SizedBox(width: 10),
const Text("Pinpoint Flutter SDK Demo"),
],
),
),
backgroundColor: const Color(0xFFF7F7F7),
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: StreamBuilder(
stream: _positioningStream,
builder: (context, snapshot) {
bool hasPosition = snapshot.hasData;
bool isIndoorPosition = snapshot.data is IndoorPosition;
// Received position when the position stream is running. Can be a outdoor or indoor position.
Position? position = snapshot.data;
return Column(
spacing: 15,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
spacing: 10,
children: [
const Text(
"WGS84 Coordinates",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
),
),
if (_isPositioning)
Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color:
isIndoorPosition
? Colors.green
: Colors.red,
shape: BoxShape.circle,
),
),
],
),
if (_isPositioning && !hasPosition)
const CircularProgressIndicator(
color: Color.fromRGBO(255, 153, 26, 1),
),
IconButton(
onPressed: () => _setWGS84Ref(),
icon: Icon(Icons.settings),
),
],
),
if (_isPositioning)
Text(
isIndoorPosition ? "indoor position" : "outdoor position",
style: TextStyle(color: Colors.grey, fontSize: 16),
),
ValueBox(
label: "Latitude",
value:
_isPositioning && hasPosition
? position!.latitude.toString()
: "",
color: Colors.red.shade300,
),
ValueBox(
label: "Longitude",
value:
_isPositioning && hasPosition
? position!.longitude.toString()
: "",
color: Colors.green.shade300,
),
ValueBox(
label: "Accuracy",
value:
_isPositioning && hasPosition
? "${position!.accuracy.toStringAsFixed(2)} m"
: "",
color: Colors.blue.shade300,
),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed:
_isPositioning ? _stopPositioning : _startPositioning,
style: ElevatedButton.styleFrom(
backgroundColor:
_isPositioning ? Colors.red : Colors.green,
padding: const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: Text(
_isPositioning
? "Stop Positioning"
: "Start Positioning",
style: const TextStyle(
color: Colors.white,
fontSize: 18,
),
),
),
),
Text(
"For indoor positioning please hold your TRACElet close to the device.",
),
],
);
},
),
),
),
);
}
///Requests Permission and checks if the permission was granted.
Future<bool> _checkPermissions() async {
var permission = await Geolocator.checkPermission();
// If permissions are deniedForever, permission dialog will not be shown until
// the user updates the permission in the App settings
if (permission == LocationPermission.deniedForever) {
await Geolocator.openAppSettings();
}
if (permission != LocationPermission.always &&
permission != LocationPermission.whileInUse) {
permission = await Geolocator.requestPermission();
}
if (permission != LocationPermission.always &&
permission != LocationPermission.whileInUse) {
return false;
}
return true;
}
/// Cancels the positioning stream.
void _stopPositioning() async {
setState(() {
_positioningStream = null;
});
}
/// Starts the positioning stream with a distance filter of 2 m,
/// if the [_refLatitude], [_refLongitude], [_refAzimuth] are set and [_checkPermissions] is true.
Future<void> _startPositioning() async {
if (_wgs84Reference == null) {
_setWGS84Ref();
return;
}
if (!await _checkPermissions()) return;
setState(() {
_positioningStream = Geolocator.getPositionStream(
locationSettings: const LocationSettings(
distanceFilter: 2,
timeLimit: Duration(minutes: 1),
),
);
});
}
/// Opens the [WGS84ReferenceDialog] and updates the Georeference for indoor positioning, if the result != null.
Future<void> _setWGS84Ref() async {
final result = await showDialog(
context: context,
builder: (context) {
return WGS84ReferenceDialog(wgs84Result: _wgs84Reference);
},
);
if (result != null) {
setState(() {
_wgs84Reference = result;
});
// Needs to be set for indoor positioning
Geolocator.updateGeoreference(
latitude: _wgs84Reference!.latitude,
longitude: _wgs84Reference!.longitude,
azimuth: _wgs84Reference!.azimuth,
);
}
}
}
/// Wgs84Reference with [latitude], [longitude] and [azimuth].
class Wgs84Reference {
double latitude;
double longitude;
double azimuth;
Wgs84Reference({
required this.latitude,
required this.longitude,
required this.azimuth,
});
}