SSukha 地图开发者文档

Sukha地图 Android SDK 开发文档

文档核对:2026-10-08 · 本次源码编译 API · Java 接口。

本文面向接入地图、定位、搜索、路线与导航的 Android 开发者,按“入门、开发指南、接口参考、常见问题”的方式组织。方法与包名以本次Sukha SDK 为准;熟悉高德的开发者可以沿用相似的接入思路,但不能直接替换二进制或照搬全部高德参数。

1. 概述

1.1 产品能力

类别 本版本提供的能力 使用入口
基础地图 地图显示、生命周期、相机、手势、主题、截图 MapView、SukhaMap
覆盖物 点、线、面、圆、三点弧线、信息窗 Marker、Polyline、Polygon、Circle、Arc
数据可视化 热力图、点聚合、瓦片覆盖物 HeatmapTileProvider、ClusterOverlay、TileOverlay
图形工具 点选绘制、线面顶点及中点编辑、距离和面积 MouseTool、PolylineEditor、PolygonEditor、MapUtils
定位 单次、连续、定位质量控制、地址补充 SukhaLocationClient
搜索 关键词、周边、ID、输入联想、正逆地理编码 PoiSearch、Inputtips、GeocodeSearch
路线 驾车、步行、距离/时间/几何及步骤 RouteSearch
导航 驾车控制器、模拟导航、步行控制器、完整服务多语言录音 NavigationClient、WalkingNavi
完整界面 自带地图、搜索、路线与导航 UI SukhaMapFragment
可选业务组件 配送定位及配送导航界面 maps-delivery;基础地图无需依赖

地图与路线的覆盖范围取决于授权数据集及已发布数据。存在方法不代表任意地点都有对应数据。骑行、完整省市区门牌地址、行政区划边界不在本次范围;公交、货车、实时交通等也不作为已支持能力交付。

1.2 SDK 模块与版本

Maven 坐标前缀 cn.sukha.maps: 固定版本 内容
maps-core 0.1.0-alpha.23 基础地图、覆盖物与工具
maps-services 0.1.0-alpha.19 授权会话、搜索、地理编码、路线
maps-location 0.1.0-alpha.21 定位
maps-navigation 0.1.0-alpha.32 导航模型、引擎、录音资源
maps-navigation-services 0.1.0-alpha.36 在线导航服务及控制器
maps-ui 0.1.0-alpha.79 完整地图界面
maps-delivery 0.1.0-alpha.30 可选配送组件

SDK 安装包由平台提供,需与本次文档的 API 基线匹配。解压保留 Maven 仓库、POM 和 AAR,通过本地 Maven 解析依赖,不要只取单个 AAR。历史包即使 Maven 版本号相同,也可能缺少后续接口,详见版本与交付。

2. 入门指南

2.1 环境准备与获取 Key

工程基线为 JDK 17、Gradle 8.7、Android Gradle Plugin 8.5.2、compileSdk 34、minSdk 23;源码使用 Java 11,开启 desugaring。客户工程可使用经自行验证的其他兼容版本。

申请Sukha Android Key 时提供:应用 applicationId、实际 APK 签名证书 SHA1、授权数据集及地图/搜索/路线/导航能力。调试证书和正式证书分别登记。高德 Key 不可用于Sukha服务。

2.2 配置工程

将解压出的 maven 放到客户工程根目录的 vendor/sukha/maven。

// settings.gradle
dependencyResolutionManagement {
    repositories {
        maven { url = uri("$rootDir/vendor/sukha/maven") }
        google()
        mavenCentral()
    }
}
// app/build.gradle
android {
    compileSdk 34
    defaultConfig { minSdk 23 }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
        coreLibraryDesugaringEnabled true
    }
}
dependencies {
    implementation 'cn.sukha.maps:maps-core:0.1.0-alpha.23'
    implementation 'cn.sukha.maps:maps-services:0.1.0-alpha.19'
    implementation 'cn.sukha.maps:maps-location:0.1.0-alpha.21'
    // 自定义导航时引入
    implementation 'cn.sukha.maps:maps-navigation-services:0.1.0-alpha.36'
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
}

若采用完整地图界面,选择 maps-ui:0.1.0-alpha.79,由 POM 引入其依赖。不要混用不同批次模块。第三方 AndroidX、MapLibre 等依赖仍由 Google/Maven Central 获取。

2.3 配置 Manifest

<!-- manifest 节点下 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 使用定位才需要以下权限;还需宿主进行运行时申请 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<!-- application 节点内,替换成自己的授权信息 -->
<meta-data android:name="cn.sukha.maps.API_KEY" android:value="YOUR_ANDROID_KEY" />
<meta-data android:name="cn.sukha.maps.SERVICE_URL" android:value="https://map.sukha.cn" />
<meta-data android:name="cn.sukha.maps.DATASET_ID" android:value="YOUR_DATASET_ID" />

示例经纬度位于演示数据范围;YOUR_DATASET_ID 由提供方分配,不能用示例坐标推断覆盖全国或全球。

2.4 显示第一张地图

下面是 Activity 的最小结构,在宿主完成所需的授权流程后进入此页。它不主动申请或启动定位。

package example;

import android.app.Activity;
import android.os.Bundle;
import cn.sukha.mapsdk.maps.MapView;
import cn.sukha.mapsdk.maps.CameraUpdateFactory;
import cn.sukha.mapsdk.maps.model.LatLng;
import cn.sukha.mapsdk.services.core.MapsInitializer;

public class QuickStartActivity extends Activity {
    private MapView mapView;
    @Override public void onCreate(Bundle state) {
        super.onCreate(state);
        MapsInitializer.initialize(this);
        mapView = new MapView(this);
        setContentView(mapView);
        mapView.onCreate(state);
        mapView.getMapAsync(map -> map.moveCamera(
            CameraUpdateFactory.newLatLngZoom(
                new LatLng(21.67623, 100.02228), 16)));
    }
    @Override protected void onStart() { super.onStart(); mapView.onStart(); }
    @Override protected void onResume() { super.onResume(); mapView.onResume(); }
    @Override protected void onPause() { mapView.onPause(); super.onPause(); }
    @Override protected void onStop() { mapView.onStop(); super.onStop(); }
    @Override protected void onSaveInstanceState(Bundle out) {
        super.onSaveInstanceState(out); mapView.onSaveInstanceState(out);
    }
    @Override public void onLowMemory() { super.onLowMemory(); mapView.onLowMemory(); }
    @Override protected void onDestroy() { mapView.onDestroy(); super.onDestroy(); }
}

宿主还需在 Manifest 声明此 Activity。getMapAsync 表示地图控制对象可用,不保证所有网络数据已加载。通过 MapView.setOnMapLoadListener 的 onMapLoadError(SdkException) 接收数据加载失败。

2.5 示例约定

后续示例为方法体片段,context 为 Activity/Context,map 是 getMapAsync 得到的 SukhaMap,report(value) 表示宿主更新界面或记录日志。示例并非全部顺序执行。常用 imports:

import cn.sukha.mapsdk.maps.*;
import cn.sukha.mapsdk.maps.model.*;
import cn.sukha.mapsdk.services.core.*;
import cn.sukha.mapsdk.services.poisearch.*;
import cn.sukha.mapsdk.services.inputtips.*;
import cn.sukha.mapsdk.services.geocoder.*;
import cn.sukha.mapsdk.services.route.*;
import cn.sukha.mapsdk.location.SukhaLocationClient;
import cn.sukha.mapsdk.location.SukhaLocationClientOption;

3. 基础概念与坐标

数据 顺序 / 单位 约定
LatLng / LatLonPoint / SukhaLatLng 纬度、经度;度 默认 WGS84
Android Location 原始 WGS84 即便地图使用 GCJ02,也不预先偏移传感器位置
路线距离 / 定位 accuracy 米 accuracy 越小,水平不确定性通常越小
路线 time / duration 秒 不要当毫秒
定位时间戳、间隔、超时、动画时长 毫秒 时间戳使用实际采样时间
屏幕坐标、控件边距 物理像素 dp 由宿主换算
Android 颜色 ARGB int 例如 0xff1268e5

默认使用 WGS84,缅甸数据建议保留此模式。迁移 GCJ02 业务可在创建任何地图/服务前选择模式:

MapsInitializer.initialize(context, "https://map.sukha.cn", "YOUR_DATASET_ID",
    "zh-CN", CoordinateMode.System.GCJ02);

此时地图、搜索及路线公开坐标使用 GCJ02;后台仍使用 WGS84。不要再次手动偏移返回值。模式不允许在已创建地图上切换,保存状态也不能跨模式恢复。独立实例使用 AndroidSdkClient.create(context, base, dataset, language, coordinateSystem),在 MapView.onCreate 前 setServiceClient(client),搜索服务共享同一 client。

转换支持算法区间为经度 73.66–135.05、纬度 3.86–53.55,区间外报错;它不是行政边界数据。手工 GeoJSON、覆盖物、聚合点应已属于选定公开坐标系。第三方栅格瓦片不会自动重投影。原始定位回调保持 WGS84;NavigationClient.toNavigationPosition(fix) 可转换为导航公开坐标。

4. 创建地图与主题

接口 用途 注意事项
MapView(context) 基础地图容器 宿主负责生命周期
getMapAsync(callback) 获取 SukhaMap 获取后再操作地图
getCameraPosition() 相机状态 target、zoom、tilt、bearing
getBounds() 当前可视包围范围 不是精确可视四边形
getProjection().toScreenLocation(point) 经纬度转屏幕像素 相对地图控件
getProjection().fromScreenLocation(pixel) 屏幕转经纬度 整数像素有舍入误差
setTheme(MapTheme.DAY/NIGHT/AUTO) 白天、夜间、跟随宿主 AUTO 根据宿主实际 Android 主题,不读取时间或地理位置;固定浅色宿主保持白天

完整 UI 是另一种入口,需要 AndroidX Fragment 宿主:

cn.sukha.mapsdk.api.SukhaMapConfig config =
    new cn.sukha.mapsdk.api.SukhaMapConfig.Builder(context)
        .serverBaseUrl("https://map.sukha.cn")
        .language("en-US").voiceLanguage("zh-CN")
        .build();
// 使用 SukhaMapFragment.newInstance(config) 后提交到宿主 Fragment 容器。

基础 MapView 用于自定义页面;完整 Fragment 自带地图交互和导航界面,不需要再叠加另一套 SDK 地图容器。

5. 与地图交互

5.1 相机、缩放与范围适配

map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(21.67623, 100.02228), 17));
map.animateCamera(CameraUpdateFactory.zoomTo(18), 300, null);
LatLngBounds bounds = LatLngBounds.builder()
    .include(new LatLng(21.67623, 100.02228))
    .include(new LatLng(21.68, 100.03)).build();
map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 24, 80, 24, 220));

四边距顺序为左、上、右、下。适配范围前确保控件已布局且可用宽高大于边距总和。动画时长 1–60000 毫秒,回调为 SukhaMap.CancelableCallback 或 null;stopAnimation() 取消动画。

5.2 控件与手势

UiSettings ui = map.getUiSettings();
ui.setCompassEnabled(true);
ui.setZoomControlsEnabled(true);
ui.setScaleControlsEnabled(true);
ui.setMyLocationButtonEnabled(true);
ui.setRotateGesturesEnabled(true);
ui.setTiltGesturesEnabled(false);

setAllGesturesEnabled 控制全部手势,setScrollGesturesEnabled、setZoomGesturesEnabled 可分别控制。显示定位按钮不等于已获得定位权限或真实位置。

5.3 地图与覆盖物事件

map.setOnMapClickListener(point -> report(point));
map.setOnMarkerClickListener(marker -> { report(marker.getId()); return true; });
map.setOnInfoWindowClickListener(marker -> report(marker.getId()));
map.setOnCameraChangeListener(new SukhaMap.OnCameraChangeListener() {
    public void onCameraChange(CameraPosition p) { report(p.target); }
    public void onCameraChangeFinish(CameraPosition p) { report(p.zoom); }
});
map.setOnMapTouchListener(event -> report(event.getActionMasked()));

同种 setter 会替换旧监听,传 null 解绑。Marker 点击返回 true 表示业务已处理。MotionEvent 仅在回调内使用,回调后回收。触摸监听是观察接口,不用于拦截手势。另有地图长按、Marker 拖拽与截图等接口,详见接口索引。

6. 在地图上绘制

6.1 点标记与信息窗

Marker marker = map.addMarker(new MarkerOptions()
    .position(new LatLng(21.67623, 100.02228)).title("门店").rotateAngle(0));
marker.setPosition(new LatLng(21.677, 100.023));
marker.setRotateAngle(90);
marker.showInfoWindow();
// marker.setVisible(false); marker.remove();

position 必填;旋转角按顺时针屏幕角度归一化至 0–360。setInfoWindowAdapter 支持自定义信息窗 View。图片通过 BitmapDescriptorFactory.fromBitmap(bitmap) 或 fromResource(context, resourceId) 转成图标后交给 MarkerOptions.icon / Marker.setIcon。矢量资源先绘制为 Bitmap;避免每次定位都重新构建图标。

6.2 折线、面与圆

LatLng a = new LatLng(21.67623, 100.02228);
LatLng b = new LatLng(21.678, 100.024);
LatLng c = new LatLng(21.680, 100.022);
Polyline line = map.addPolyline(new PolylineOptions().add(a, b, c)
    .color(0xff1268e5).width(5));
Polygon polygon = map.addPolygon(new PolygonOptions().add(a, b, c)
    .fillColor(0x221268e5).strokeColor(0xff1268e5));
Circle circle = map.addCircle(new CircleOptions().center(a).radius(100)
    .fillColor(0x221268e5).strokeColor(0xff1268e5));

折线至少 2 点,面至少 3 点;圆半径单位米。更新图形使用对应 setPoints、setCenter、setRadius,删除用 remove()。已删除对象不再复用。

6.3 三点弧线

Arc arc = map.addArc(new ArcOptions()
    .point(new LatLng(21.676, 100.020), new LatLng(21.679, 100.022),
           new LatLng(21.676, 100.024))
    .strokeColor(0xff1268e5).strokeWidth(5));
// arc.remove();

三点依次为起点、经过点、终点;三点应能定义有效弧线。底层通过几何采样显示,不承诺与其他厂商的曲线插值完全一致。

6.4 热力图

HeatmapTileProvider heat = new HeatmapTileProvider.Builder()
    .data(java.util.Arrays.asList(new LatLng(21.676, 100.022),
                                 new LatLng(21.677, 100.023)))
    .radius(20).opacity(0.6).build();
TileOverlay heatLayer = map.addTileOverlay(new TileOverlayOptions().tileProvider(heat));
// 更新 heat.setData(newPoints) 后调用 heatLayer.clearTileCache()。
// heatLayer.remove();
参数 默认 / 范围 说明
data / weightedData 必填其中之一 点集合 / WeightedLatLng 权重点集合
radius 20;10–50 像素 热力核显示半径
opacity 0.6;0–1 透明度
gradient SDK 默认渐变 Gradient 颜色及分段位置

6.5 点聚合

java.util.List<ClusterItem> items = new java.util.ArrayList<>();
items.add(() -> new LatLng(21.676, 100.022));
items.add(() -> new LatLng(21.6761, 100.0221));
ClusterOverlay clusters = new ClusterOverlay(map, items, 60, context);
clusters.setMaxZoom(20);
clusters.setOnClusterClickListener((marker, members) -> report(members.size()));
// clusters.setData(updatedItems); clusters.onDestroy();

clusterRadius 是屏幕网格边长,1–1024 物理像素,不是点间严格距离半径。输入最多 20000 项;setMaxZoom 范围 0–24,默认 20,达到后逐点显示。setClusterRenderer 返回自定义 Drawable。大规模数据仍需目标机性能测试,不保证任意机型固定帧率。

6.6 绘制与编辑

MouseTool tool = new MouseTool(map);
tool.setOnDrawListener(overlay -> report(overlay));
tool.polyline(new PolylineOptions().color(0xff1268e5).width(5));
// 用户逐点点击;宿主的完成按钮调用 tool.finish(),撤销调用 tool.undo()。

PolylineEditor editor = new PolylineEditor(map, line);
editor.open();
// editor.addMidpoint(0); editor.close(); editor.destroy();

MouseTool 支持 marker、polyline、polygon、circle、rectangle。Android 线/面显式 finish();圆与矩形两次点选完成。线面编辑支持顶点拖动和边中点插入;面包含闭合边。close(false) 保留已完成图形,close(true) 同时删除工具创建的图形;工具 destroy 不等于删除目标图形。map.clear() 会释放地图上的工具。

7. 定位

7.1 单次定位

调用前由宿主完成实际的定位权限与隐私授权。userHasConsented 是宿主保存的真实结果。

SukhaLocationClient location = new SukhaLocationClient(context);
location.setPrivacyConsent(userHasConsented);
location.setLocationOption(new SukhaLocationClientOption()
    .setOnceLocation(true).setLocationTimeout(15000));
location.setLocationListener(fix -> {
    if (fix.getErrorCode() != 0) { report(fix.getError()); return; }
    report(fix.getLatitude()); report(fix.getLongitude());
});
location.startLocation();

单次结果后自动停止采集,实例仍应在结束使用后 onDestroy()。成功错误码是 0;它不同于搜索服务的成功码 1000。不要使用失败对象中的无效坐标。

7.2 连续定位与参数

location.stopLocation();
location.setLocationOption(new SukhaLocationClientOption()
    .setOnceLocation(false).setInterval(2000)
    .setLocationMode(SukhaLocationClientOption.SukhaLocationMode.Hight_Accuracy)
    .setNeedAddress(false));
location.startLocation();
配置方法 默认 有效值与含义
setOnceLocation false true 单次,false 连续
setInterval 2000 1000–3600000 毫秒,期望间隔
setLocationTimeout / setHttpTimeOut 15000 1000–120000 毫秒
setLocationMode Hight_Accuracy Hight_Accuracy、Battery_Saving、Device_Sensors;拼写按真实枚举
setMaximumAccuracy 正无穷 大于 0 的米数;默认保留基础质量过滤
setOnceLocationLatest false 有限观察窗口内选择较优位置
setBestLocationTimeout 3000 1000–10000 毫秒
setLocationCacheEnable false 是否复用有效缓存
setLastLocationLifeCycle 10000 缓存寿命 0–60000 毫秒
setNeedAddress false 异步补充地址,独立地址监听接收
setSensorAssistEnabled false 可选方向辅助

setAddressListener 接收后续地址结果;首次坐标不应等待地址。地址字段缺失时显示业务占位语,不拼接假省市区。方向或速度必须检查 hasBearing() / hasSpeed();缺失方向不是朝北。

7.3 显示定位蓝点

map.setMyLocationStyle(new MyLocationStyle()
    .myLocationType(MyLocationStyle.LOCATION_TYPE_SHOW)
    .dotColor(0xff1268e5).radiusFillColor(0x221268e5));
map.setMyLocationEnabled(true);
// 成功定位回调内:fix 为真实 SukhaLocation
android.location.Location raw = new android.location.Location("sdk");
raw.setLatitude(fix.getLatitude()); raw.setLongitude(fix.getLongitude());
raw.setAccuracy(fix.getAccuracy()); raw.setTime(fix.getTime());
map.updateMyLocation(raw);

SHOW 仅显示,LOCATE 首次回中,FOLLOW 持续跟随。输入是原始 WGS84;GCJ02 模式由地图内部转换显示。

7.4 前台服务与释放

SukhaLocationClient 自身不是前台服务,也没有可照搬的高德 enableBackgroundLocation 方法。后台持续场景由宿主合法启动并维持 location 类型前台服务,或选用 SDK 的导航/配送前台组件;权限、通知和启动时机需按目标 Android 版本处理。系统停止进程后不能保证持续定位。

停止采集调用 stopLocation();最终释放调用 onDestroy()。页面关闭是否结束持续定位由业务会话拥有者决定,不应销毁仍在服务中使用的对象。

8. 搜索与地址

8.1 POI 关键词、周边与详情

PoiSearch.Query query = new PoiSearch.Query("酒店", "", "");
query.setPageNum(1); query.setPageSize(20);
PoiSearch search = new PoiSearch(context, query);
search.setOnPoiSearchListener(new PoiSearch.OnPoiSearchListener() {
    public void onPoiSearched(PoiResult result, int code) {
        if (code == SdkException.SUCCESS) report(result.getPois());
        else report(search.getLastError());
    }
    public void onPoiItemSearched(PoiItem item, int code) { report(item); }
});
search.searchPOIAsyn();
// 周边查询:先 setBound,再发起查询。
// search.setBound(new PoiSearch.SearchBound(new LatLonPoint(21.67623,100.02228),1000));
// 已获取Sukha POI ID 后:search.searchPOIIdAsyn(id);
参数 约束 说明
keyword 字符串 关键词
type 字符串,可空 Sukha数据类别,不保证与高德分类码一致
city 空字符串或 null 当前不提供行政城市筛选
pageNum 1–5,默认 1 页号
pageSize 1–50,默认 20 页大小
SearchBound.range 0–5000 米 周边范围
ID Sukha ID 不接受高德 POI ID

同一服务实例的新请求会取消旧请求。需要并行独立查询时分别创建服务对象,共享 SdkClient 即可。

8.2 输入联想

Inputtips tips = new Inputtips(context, new InputtipsQuery("酒店", "").setLimit(10));
tips.setInputtipsListener((items, code) -> {
    if (code == SdkException.SUCCESS) report(items); else report(tips.getLastError());
});
tips.requestInputtipsAsyn();

关键词去空白后不能为空,最多 200 字符;limit 为 1–50。下拉 UI 由宿主绘制。监听回调后不要持有已退出 Activity;退出时 destroy。

8.3 正地理编码与逆地理编码

GeocodeSearch geocoder = new GeocodeSearch(context);
geocoder.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() {
    public void onRegeocodeSearched(RegeocodeResult result, int code) {
        if (code == SdkException.SUCCESS) report(result.getRegeocodeAddress());
        else report(geocoder.getLastError());
    }
    public void onGeocodeSearched(GeocodeResult result, int code) {
        if (code == SdkException.SUCCESS) report(result.getGeocodeAddressList());
    }
});
geocoder.getFromLocationNameAsyn(new GeocodeQuery("门店名称", ""));
// 独立执行下面逆查询;不要与上面的正查询同时在同一个对象上执行。
RegeocodeQuery rq = new RegeocodeQuery(new LatLonPoint(21.67623,100.02228),
    1000, GeocodeSearch.GPS);
rq.setExtensions("all");
// geocoder.getFromLocationAsyn(rq);

正查询匹配已发布地点/建筑名称,不是完整国内地址解析。逆查询 radius 为 0–3000 米;extensions 为 base/all,默认 base。latLonType 当前只接受 GPS,不能传 AMAP 常量;坐标模式仍由 client 配置。逆查询包含 formattedAddress、匹配信息、POI 和道路,完整省市区门牌不作保证。

同步 getFromLocationName / getFromLocation 只能在工作线程调用。界面优先使用异步接口。

9. 出行路线规划

9.1 驾车与步行

RouteSearch routes = new RouteSearch(context);
routes.setRouteSearchListener(new RouteSearch.OnRouteSearchListener() {
    public void onDriveRouteSearched(DriveRouteResult result, int code) {
        if (code == SdkException.SUCCESS) report(result.getPaths());
        else report(routes.getLastError());
    }
    public void onWalkRouteSearched(WalkRouteResult result, int code) {
        if (code == SdkException.SUCCESS) report(result.getPaths());
        else report(routes.getLastError());
    }
});
RouteSearch.FromAndTo endpoints = new RouteSearch.FromAndTo(
    new LatLonPoint(21.67623,100.02228), new LatLonPoint(21.68,100.03));
routes.calculateDriveRouteAsyn(new RouteSearch.DriveRouteQuery(
    endpoints, RouteSearch.DRIVING_TIME));
// 步行另行调用:routes.calculateWalkRouteAsyn(new RouteSearch.WalkRouteQuery(endpoints));
查询参数 值 说明
驾车策略 DRIVING_TIME=0、DRIVING_DISTANCE=1 时间优先、距离优先;不能透传其他高德枚举
passedByPoints 最多 16 点 驾车途经点
avoidpolygons 最多 32 个,每个 3–16 点 驾车避让区域
avoidRoad 最多 200 字符 避让道路名称;指定时优先于区域
步行策略 WALK_DEFAULT=0 当前步行默认策略

高级驾车参数使用五参数 DriveRouteQuery(endpoints, mode, passedByPoints, avoidpolygons, avoidRoad)。服务端必须支持相应规划能力;本次 SDK 发布没有自动升级所有客户后台。若服务返回不支持,不能静默退化为忽略约束。

9.2 结果模型

DriveRouteResult.getPaths() / WalkRouteResult.getPaths() 返回路径;路径提供距离、耗时、polyline、steps。步骤包含道路名称、分段几何、距离及服务返回的指令/动作/耗时等。缺少可选字段时不得拼造导航指令。路线预览不能直接视为真实导航会话;导航应使用下一章控制器。

10. 导航

内置导航页与 Sukha 自有地图共用导航布局、转向图标和版权组件。通过当前 Activity 调用 SukhaNaviPage.createIntent(...) 或 showRouteActivity(...),页面跟随宿主实际主题:未适配夜间的宿主保持浅色,适配 DayNight 的宿主按其当前设置显示;不按时间或 GPS 切换。已移除内置导航参数中的独立 theme(...) 设置。嵌入式地图仍支持 DAY / NIGHT / AUTO。

导航地图左下角保留版权并避让底部卡片:中文 © 苏哈出行、英文 © Sukha Go、缅文 © သုခ,跟随界面语言,在横竖屏及深浅主题下均显示。

10.1 驾车控制器调用顺序

类:cn.sukha.mapsdk.navi.services.NavigationClient。

  1. 创建客户端,设置 NavigationClient.Listener,调用 initialize()。
  2. 收到 onReady(datasetVersion) 后,调用 startLocation(),等待有效位置。
  3. 调用 calculateDriveRoute(destination),或显式传起终点;等待 onCalculateRouteSuccess。
  4. 宿主开始按钮调用 startNavi();onNaviInfoUpdate 更新自定义导航界面。
  5. 结束时 stopNavi(),会话销毁时 close() / onDestroy()。
方法 / 回调 参数或结果 说明
calculateDriveRoute(start, destination, heading) SukhaLatLng、可空 Float 公开坐标模式;heading 为方向角
calculateDriveRoute(destination) SukhaLatLng 使用最近有效定位
startNavi() 无 真导航需要 10 秒内、accuracy ≤50 米的位置
startNavi(mode) GPSNaviMode / EmulatorNaviMode 模拟仅用于开发验证
setEmulatorNaviSpeed(kph) 1–120 停止导航后配置
setVoiceEnabled(enabled) boolean 控制导航录音播放
onCalculateRouteFailure(message) String 算路失败
onError(code, message) String、String 初始化/定位等错误
onArriveDestination(side) 目的地侧向信息 到达事件

不要在开始导航时用常量坐标、过期位置或虚构精度绕过质量检查。NavigationClient 管理连续定位和导航,不自动等同于一个可长期后台运行的 Activity;后台使用前台导航服务或完整导航页的对应接入方式。

10.2 步行导航

类:cn.sukha.mapsdk.navi.services.WalkingNavi,构造 WalkingNavi(context, client)。设置 Listener 后依次 calculateWalkRoute(start,end) → 成功回调 → startNavi()。宿主在有效定位回调里调用 updateLocation(android.location.Location),传原始 WGS84。结束 stopNavi(),最终 close()。步行不提供骑行行为替代。

10.3 多语言与语音

Android 服务初始化可传 zh-CN、en-US、my-MM;完整 SukhaMapConfig.Builder.language 控制显示语言,voiceLanguage 控制完整导航流程的语音语言。宿主应显式匹配系统或用户选择,不假设所有入口都自动读取系统语言。

当前 Android 完整导航流程已具备中文、英文和缅文预录音资源及对应语言入口。NavigationForegroundService 可设置显示与语音语言;低层 NavigationClient 没有同名语言配置方法,不能混用入口。资源随对应构建交付,不将旧 AAR 的版本号视为语音更新证明。动态地名是否有译名取决于后台数据。原始 instruction 可能为中文,完整 SDK UI 使用显示翻译;自定义 UI 可用 cn.sukha.mapsdk.i18n.SdkLanguage.instruction(language, raw)。

11. 地图计算与工具

double meters = MapUtils.calculateLineDistance(
    new LatLng(21.67623,100.02228), new LatLng(21.68,100.03));

结果为球面直线距离,单位米,不是沿路距离。面积和坐标转换使用 SDK 工具,勿将这些近似计算用于测绘级承诺。经纬度转像素用 Projection;WGS84/GCJ02 转换使用 CoordinateConverter 或初始化坐标模式,二者不要重复执行。

12. 错误码、线程与资源管理

12.1 服务错误码

数字码 名称 处理建议
1000 SUCCESS 服务调用成功;仍检查是否有结果
2001 NETWORK_ERROR 检查网络;有界重试
2002 AUTH_ERROR 核对 Key、包名、签名、数据集、能力
2003 INVALID_ARGUMENT 修正参数,勿无限重试
2004 NO_ROUTE 换起终点或提示暂无路线
2005 SERVER_ERROR 记录 requestId 联系服务方
2006 CANCELLED 已取消;通常不提示故障

getLastError() 提供 SdkException,可读取 getCode()、getRequestId()、getHttpStatus()、getRetryAfterMillis()。httpStatus=0 表示无 HTTP 响应,retryAfterMillis=-1 表示未取得有效 Retry-After。参数校验也可能同步抛 IllegalArgumentException,不能只依赖异步回调。

SdkLogger.setErrorLogger((source, code, requestId) ->
    android.util.Log.w("MapSDK", source + " / " + code + " / " + requestId));
// 宿主日志代理不再需要时:SdkLogger.setErrorLogger(null);

12.2 定位错误码

原始码 统一代码 含义
0 成功 可使用位置
1 PERMISSION_DENIED 缺定位权限
2 PROVIDER_DISABLED 系统定位关闭
3 TIMEOUT 定位超时
4 SOURCE_FAILURE 位置源失败
5 STOPPED 定位已停止
6 PRIVACY_DENIED 未同意或已撤销授权
7 ACCURACY_INSUFFICIENT 无位置达到设定精度

定位错误通过 SukhaLocation.getError() 取得结构化信息,与搜索的 1000/200x 码分开处理。

12.3 线程与生命周期

地图、覆盖物、定位及导航控制器在主线程操作;异步服务回调也不要执行阻塞工作。同步网络方法只能在工作线程调用。共享 client 的销毁顺序:先停止定位/导航 → 销毁工具及服务 → MapView.onDestroy → 最后由拥有者 client.close。使用 MapsInitializer 的进程级默认会话时,只有全部使用者退出后才调用 MapsInitializer.destroy。

搜索对象可 cancel() 取消请求并继续复用;destroy() 后不可再调用。map.clear() 只清理地图相关对象,不能代替停止独立定位和搜索。Activity 重建后要重新绑定监听器。

13. API 分类索引

分类 包路径 主要类
地图与交互 cn.sukha.mapsdk.maps MapView、SukhaMap、CameraUpdateFactory、UiSettings、Projection
覆盖物 cn.sukha.mapsdk.maps Marker、Polyline、Polygon、Circle、Arc、TileOverlay
参数与几何 cn.sukha.mapsdk.maps.model LatLng、LatLngBounds、CameraPosition、各 Options、BitmapDescriptorFactory
热力与聚合 maps.model / maps HeatmapTileProvider、WeightedLatLng、Gradient、ClusterOverlay、ClusterItem
编辑 cn.sukha.mapsdk.maps MouseTool、PathEditor、PolylineEditor、PolygonEditor
定位 cn.sukha.mapsdk.location SukhaLocationClient、SukhaLocationClientOption、SukhaLocation、LocationError
授权与诊断 cn.sukha.mapsdk.services.core MapsInitializer、AndroidSdkClient、SdkClient、SdkException、SdkLogger
搜索联想 services.poisearch / services.inputtips PoiSearch、PoiResult、PoiItem、Inputtips、InputtipsQuery、Tip
地理编码 cn.sukha.mapsdk.services.geocoder GeocodeSearch、GeocodeQuery、RegeocodeQuery、结果与地址模型
路线 cn.sukha.mapsdk.services.route RouteSearch、DriveRouteResult、WalkRouteResult、Path/Step 模型
导航服务 cn.sukha.mapsdk.navi.services NavigationClient、WalkingNavi、NavigationForegroundService
完整地图配置 cn.sukha.mapsdk.api SukhaMapConfig
完整地图 Fragment cn.sukha.mapsdk SukhaMapFragment

详细公开声明见随本文交付的 Android API 声明索引,最终签名以固定版本 AAR 的公开接口为准。索引按公开声明提取,不交付 internal、测试实现或 SDK 核心源码。

14. 从高德迁移与常见问题

常见迁移点 本 SDK 对应规则
AMap 控制对象 使用 SukhaMap,包名 cn.sukha.mapsdk.*
Key 使用Sukha Android Key,不能复用高德 Key
默认坐标 WGS84;GCJ02 必须明确配置
高德策略整数 只映射本文支持的策略,不直接透传
国内城市/区划码 不作为搜索过滤和完整地址能力提供
位置成功码 定位 0;搜索/路线 1000
高德示例点聚合 使用 ClusterOverlay;分组结果不承诺相同
导航与预览 RouteSearch 预览与 NavigationClient 会话分开

地图白屏:检查 Key/签名、数据集、网络、加载错误回调、控件尺寸和生命周期。地图点偏移:先查经纬度顺序及是否重复坐标转换。定位精度不足:检查真实 accuracy、系统精确定位权限、环境及业务阈值;不要把低质量结果改写为高精度。路线无结果:确认覆盖范围及后台规划能力。连续搜索丢旧结果:同实例主动取消旧请求是既定行为。

15. 版本说明与参考来源

本次以 2026-10-08 当前源码重新编译的 SDK 核对 API 和 Java 示例。后台地图与路由数据分别发布。取得历史包时请先核对接口,不能仅凭 Maven 版本号判断内容相同。详见版本与交付。

栏目结构参考高德 Android SDK 指南,本文接口与示例根据本项目编写。