Flutter地图导航插件flutter_mapbox_navigation的使用
Flutter地图导航插件flutter_mapbox_navigation的使用
简介
flutter_mapbox_navigation
是一个强大的 Flutter 插件,允许你在应用中添加专业的地图导航功能。通过 MapBox 提供的地图服务,你可以实现详细的路线导航、交通避让、实时语音提示等功能,而无需离开你的应用。
特性
- 完整的导航 UI:为 Flutter 应用提供了一个完整的转弯导航界面,可以轻松集成到你的应用中。
- 专业设计的地图样式:支持白天和夜晚驾驶的地图样式。
- 全球导航数据:提供全球范围内的驾驶、骑行和步行导航数据,基于开放数据和用户反馈。
- 交通避让和主动重新规划:根据当前路况在超过 55 个国家提供交通避让和主动重新规划功能。
- 自然语音提示:通过 Amazon Polly 提供自然的语音提示(无需额外配置)。
- 多语言支持:支持超过两打语言。
配置
iOS 配置
-
创建 MapBox 访问令牌:
- 前往 Mapbox 账户仪表板 并创建一个具有
DOWNLOADS:READ
权限范围的访问令牌。 - 创建一个名为
.netrc
的文件在你的主目录中,并添加以下内容:
其中machine api.mapbox.com login mapbox password PRIVATE_MAPBOX_API_TOKEN
PRIVATE_MAPBOX_API_TOKEN
是你的 MapBox API 令牌。
- 前往 Mapbox 账户仪表板 并创建一个具有
-
设置
MBXAccessToken
:- 在项目编辑器中选择应用目标,然后转到 Info 标签页。
- 在“Custom iOS Target Properties”部分,设置
MBXAccessToken
为你的访问令牌。
-
设置位置权限:
- 在 Info 标签页中,设置
NSLocationWhenInUseUsageDescription
为:Shows your location on the map and helps improve OpenStreetMap.
- 在 Info 标签页中,设置
-
启用后台模式:
- 转到 Capabilities 标签页,启用“Audio, AirPlay, and Picture in Picture”和“Location updates”。
- 或者在 Info 标签页中将
audio
和location
值添加到UIBackgroundModes
数组中。
Android 配置
-
设置
mapbox_access_token
:- 创建一个新的资源文件
mapbox_access_token.xml
,路径为<YOUR_FLUTTER_APP_ROOT>/android/app/src/main/res/values/mapbox_access_token.xml
。 - 添加一个字符串资源,名称为
mapbox_access_token
,值为你的令牌:<?xml version="1.0" encoding="utf-8"?> <resources xmlns:tools="http://schemas.android.com/tools"> <string name="mapbox_access_token" translatable="false" tools:ignore="UnusedResources">ADD_MAPBOX_ACCESS_TOKEN_HERE</string> </resources>
- 创建一个新的资源文件
-
添加权限:
- 在应用级别的 AndroidManifest.xml 中添加以下权限:
<manifest> ... <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> ... </manifest>
- 在应用级别的 AndroidManifest.xml 中添加以下权限:
-
设置
MAPBOX_DOWNLOADS_TOKEN
:- 将具有
downloads:read
权限范围的 MapBox 下载令牌添加到gradle.properties
文件中:MAPBOX_DOWNLOADS_TOKEN=sk.XXXXXXXXXXXXXXX
- 将具有
-
更新
MainActivity.kt
:- 将
MainActivity
继承自FlutterFragmentActivity
而不是FlutterActivity
:import io.flutter.embedding.android.FlutterFragmentActivity class MainActivity: FlutterFragmentActivity() { }
- 将
-
添加 Kotlin BOM:
- 在
android/app/build.gradle
中添加以下依赖:implementation platform("org.jetbrains.kotlin:kotlin-bom:1.8.0")
- 在
使用方法
设置默认路由选项(可选)
MapBoxNavigation.instance.setDefaultOptions(MapBoxOptions(
initialLatitude: 36.1175275,
initialLongitude: -115.1839524,
zoom: 13.0,
tilt: 0.0,
bearing: 0.0,
enableRefresh: false,
alternatives: true,
voiceInstructionsEnabled: true,
bannerInstructionsEnabled: true,
allowsUTurnAtWayPoints: true,
mode: MapBoxNavigationMode.drivingWithTraffic,
mapStyleUrlDay: "https://url_to_day_style",
mapStyleUrlNight: "https://url_to_night_style",
units: VoiceUnits.imperial,
simulateRoute: true,
language: "en"
));
监听事件
MapBoxNavigation.instance.registerRouteEventListener(_onRouteEvent);
Future<void> _onRouteEvent(e) async {
_distanceRemaining = await _directions.distanceRemaining;
_durationRemaining = await _directions.durationRemaining;
switch (e.eventType) {
case MapBoxEvent.progress_change:
var progressEvent = e.data as RouteProgressEvent;
_arrived = progressEvent.arrived;
if (progressEvent.currentStepInstruction != null)
_instruction = progressEvent.currentStepInstruction;
break;
case MapBoxEvent.route_building:
case MapBoxEvent.route_built:
_routeBuilt = true;
break;
case MapBoxEvent.route_build_failed:
_routeBuilt = false;
break;
case MapBoxEvent.navigation_running:
_isNavigating = true;
break;
case MapBoxEvent.on_arrival:
_arrived = true;
if (!_isMultipleStop) {
await Future.delayed(Duration(seconds: 3));
await _controller.finishNavigation();
} else {}
break;
case MapBoxEvent.navigation_finished:
case MapBoxEvent.navigation_cancelled:
_routeBuilt = false;
_isNavigating = false;
break;
default:
break;
}
// 刷新 UI
setState(() {});
}
开始导航
final cityhall = WayPoint(name: "City Hall", latitude: 42.886448, longitude: -78.878372);
final downtown = WayPoint(name: "Downtown Buffalo", latitude: 42.8866177, longitude: -78.8814924);
var wayPoints = List<WayPoint>();
wayPoints.add(cityhall);
wayPoints.add(downtown);
await MapBoxNavigation.instance.startNavigation(wayPoints: wayPoints);
嵌入导航视图
声明控制器
MapBoxNavigationViewController _controller;
将导航视图添加到小部件树
Container(
color: Colors.grey,
child: MapBoxNavigationView(
options: _options,
onRouteEvent: _onRouteEvent,
onCreated: (MapBoxNavigationViewController controller) async {
_controller = controller;
}),
),
构建路线
var wayPoints = List<WayPoint>();
wayPoints.add(_origin);
wayPoints.add(_stop1);
wayPoints.add(_stop2);
wayPoints.add(_stop3);
wayPoints.add(_stop4);
wayPoints.add(_origin);
_controller.buildRoute(wayPoints: wayPoints);
开始导航
_controller.startNavigation();
其他 iOS 配置
在 info.plist
文件中添加以下内容:
<dict>
...
<key>io.flutter.embedded_views_preview</key>
<true/>
...
</dict>
嵌入导航视图截图
iOS 视图 | Android 视图 |
---|---|
待办事项
- [已完成] Android 实现
- [已完成] 添加更多设置(如导航模式:驾驶、步行等)
- [已完成] 流式事件(如相关导航通知、指标、当前位置等)
- [已完成] 可嵌入的导航视图
- 离线路由
示例代码
import 'package:flutter/material.dart';
import 'package:flutter_mapbox_navigation/flutter_mapbox_navigation.dart';
void main() => runApp(const SampleNavigationApp());
class SampleNavigationApp extends StatelessWidget {
const SampleNavigationApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('MapBox Navigation Example')),
body: Center(
child: ElevatedButton(
onPressed: () async {
final cityhall = WayPoint(name: "City Hall", latitude: 42.886448, longitude: -78.878372);
final downtown = WayPoint(name: "Downtown Buffalo", latitude: 42.8866177, longitude: -78.8814924);
var wayPoints = List<WayPoint>();
wayPoints.add(cityhall);
wayPoints.add(downtown);
await MapBoxNavigation.instance.startNavigation(wayPoints: wayPoints);
},
child: const Text('Start Navigation'),
),
),
),
);
}
}
以上是一个简单的示例,展示了如何使用 flutter_mapbox_navigation
插件在 Flutter 应用中实现地图导航功能。希望对你有所帮助!
更多关于Flutter地图导航插件flutter_mapbox_navigation的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter地图导航插件flutter_mapbox_navigation的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何使用 flutter_mapbox_navigation
插件在 Flutter 应用中实现地图导航的示例代码。这个示例假定你已经设置好 Flutter 开发环境,并且已经添加了 flutter_mapbox_navigation
依赖到你的 pubspec.yaml
文件中。
首先,确保你的 pubspec.yaml
文件中包含以下依赖:
dependencies:
flutter:
sdk: flutter
flutter_mapbox_navigation: ^x.y.z # 请替换为最新版本号
然后运行 flutter pub get
来安装依赖。
接下来,你需要配置 Mapbox 的访问令牌。这通常在你的应用的 AndroidManifest.xml
和 Info.plist
文件中设置,但也可能在代码中设置。为了简单起见,这里假设你已经在这些文件中配置好了。
下面是一个完整的 Flutter 应用示例,展示如何使用 flutter_mapbox_navigation
进行地图导航:
import 'package:flutter/material.dart';
import 'package:flutter_mapbox_navigation/flutter_mapbox_navigation.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Mapbox Navigation Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MapboxNavigationScreen(),
);
}
}
class MapboxNavigationScreen extends StatefulWidget {
@override
_MapboxNavigationScreenState createState() => _MapboxNavigationScreenState();
}
class _MapboxNavigationScreenState extends State<MapboxNavigationScreen> {
late MapboxNavigationController _navigationController;
@override
void initState() {
super.initState();
// 初始化 MapboxNavigationController
_navigationController = MapboxNavigationController(
accessToken: 'YOUR_MAPBOX_ACCESS_TOKEN', // 请替换为你的 Mapbox 访问令牌
origin: MapboxPoint(latitude: 40.730610, longitude: -73.935242), // 起点坐标
destination: MapboxPoint(latitude: 37.774929, longitude: -122.419418), // 终点坐标
);
// 监听导航事件
_navigationController.navigationStateChanges.listen((state) {
print('Navigation state changed to: $state');
});
// 开始导航
_navigationController.startNavigation();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Mapbox Navigation Demo'),
),
body: Stack(
children: [
// MapboxNavigationView 用于显示地图和导航信息
MapboxNavigationView(
controller: _navigationController,
options: MapboxNavigationViewOptions(
// 你可以在这里配置导航视图的各种选项
// 例如:显示路线、交通信息等
),
),
// 自定义按钮用于停止导航(仅示例,实际应用中可能需要更复杂的逻辑)
Positioned(
bottom: 20,
right: 20,
child: ElevatedButton(
onPressed: () {
_navigationController.stopNavigation();
},
child: Text('Stop Navigation'),
),
),
],
),
);
}
@override
void dispose() {
// 释放资源
_navigationController.dispose();
super.dispose();
}
}
在这个示例中,我们创建了一个简单的 Flutter 应用,其中包含一个 MapboxNavigationView
用于显示地图和导航信息。我们还初始化了一个 MapboxNavigationController
并设置了起点和终点坐标。通过监听 navigationStateChanges
流,我们可以获取导航状态的变化。
请注意,你需要替换 'YOUR_MAPBOX_ACCESS_TOKEN'
为你的实际 Mapbox 访问令牌。
此外,这个示例仅展示了基本的导航功能。在实际应用中,你可能需要处理更多的导航事件、错误处理、用户交互等。你可以参考 flutter_mapbox_navigation
的官方文档以获取更多信息和高级功能。