下载地址 https://github.com/mapeifan/GaodeMap
(注意:此项目仅适合初学者入门学习使用)
附目录:
部分打印日志如下:
2020-03-27 11:01:39.929 20391-20391/com.test.map:secondProcess E/DEBUG_FAN: amap onMyLocationChange 定位成功, lat: 22.764450 lon: 114.087204
2020-03-27 11:01:42.979 20391-20391/com.test.map:secondProcess E/DEBUG_FAN: amap onMyLocationChange 定位成功, lat: 22.764450 lon: 114.087204
2020-03-27 11:01:44.231 20391-20391/com.test.map:secondProcess E/DEBUG_FAN: poiid B02F37V1PJ name:龙岗区 coordinate:lat/lng: (22.72093202969028,114.24691200256349)
2020-03-27 11:01:44.582 20391-20407/com.test.map:secondProcess I/p:secondProces: NativeAlloc concurrent copying GC freed 30576(1467KB) AllocSpace objects, 6(176KB) LOS objects, 80% free, 2MB/14MB, paused 6.208ms total 145.082ms
2020-03-27 11:01:44.679 20391-20391/com.test.map:secondProcess W/Looper: Slow Looper: doFrame is 307ms late because of 1 msg, msg 1 took 318ms (late=4ms h=android.os.Handler c=android.app.FragmentManagerImpl$1)
2020-03-27 11:01:44.692 20391-20391/com.test.map:secondProcess E/DEBUG_FAN: 广东省深圳市龙岗区龙城街道中共深圳市龙岗区委政法委员会深圳市龙岗区人民政府距离:19.61
2020-03-27 11:01:47.360 20391-20391/com.test.map:secondProcess E/DEBUG_FAN: amap onMyLocationChange 定位成功, lat: 22.764450 lon: 114.087218
2020-03-27 11:01:51.056 20391-20391/com.test.map:secondProcess E/DEBUG_FAN: amap onMyLocationChange 定位成功, lat: 22.764450 lon: 114.087218
2020-03-27 11:02:09.351 20391-20391/com.test.map:secondProcess E/DEBUG_FAN: poiid B02F002I0B name:博罗县 coordinate:lat/lng: (23.17287321385666,114.28948402404787)
2020-03-27 11:02:09.623 20391-20391/com.test.map:secondProcess E/DEBUG_FAN: 广东省惠州市博罗县罗阳镇博惠路82号距离:64.44
需要注意的是:
第一种情况:如果能在你的手机上运行,但是没有功能,
这个需要你填写自己的APIkey。在官方https://lbs.amap.com/ 开发者网站中,建立你的项目,创建你的key,需要SHA1码。
SHA1码获取方式:https://lbs.amap.com/faq/android/map-sdk/create-project/46723
然后在清单文件AndroidManifest.xml中,
value值改为你自己的。
需要注意的是,定位失败的,请检查定位权限是否打开
第二种情况:
在androidStudio中导入,运行时出现问题的,请查看自己的以下文件是否与我的设置相同
build.gradle文件
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.test.map"
minSdkVersion 17
targetSdkVersion 22
versionCode 1
versionName "1.1"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk {
//设置支持的SO库架构
abiFilters 'armeabi' //, 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.2.0'
// compile 'com.android.support.constraint:constraint-layout:1.0.0-beta1'
testCompile 'junit:junit:4.12'
compile 'org.greenrobot:eventbus:3.0.0'
}
gradle-wrapper.properties 目前,我androidstudio已更新到最新版本3.6.1
#Fri Mar 27 09:41:03 GMT+08:00 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
外部build.gradle .
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
google()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
20180906 补充:
有需要实现地图/导航什么功能的,可以下面留言,我看到会一一回复大家。我这里只会告诉你如何去实现,代码封装优化什么的,这个自己去想。
下面是 服务区部分案例:
@Override
public void onServiceAreaUpdate(AMapServiceAreaInfo[] aMapServiceAreaInfos) {
// 服务区信息回调函数 0代表服务区,1代表收费站
for (int i = 0; i < aMapServiceAreaInfos.length; i++) {
int a = aMapServiceAreaInfos.length;
AMapServiceAreaInfo info = aMapServiceAreaInfos[i];
String name = info.getName();
int aa = info.getRemainDist();
int bb = info.getType();
ServiceAreaDataBean areaDataBean = new ServiceAreaDataBean();
areaDataBean.setAreaNum(a);
areaDataBean.setAreaInstance(i);
areaDataBean.setAreaType(bb);
areaDataBean.setAreaName(name);
areaDataBean.setAreaDistance(aa);
Message msg = new Message();
msg.what = TEST_SERVER;
msg.obj = areaDataBean;
handler.sendMessage(msg);
}
}
以下为 hander 中消息处理内容:
private void doSolveServerData(ServiceAreaDataBean areaDataBean) {
int areaNum = areaDataBean.getAreaNum();
int instance = areaDataBean.getAreaInstance();
int areaTypeb = areaDataBean.getAreaType();
String areaName = areaDataBean.getAreaName();
int distance = areaDataBean.getAreaDistance();
if (areaNum == 1) {
if (instance == 0) {
showServerArea1();
if (areaTypeb == 0) {
tv_server_1.setText(areaName.replace(getString(R.string.nav_server_server), ""));
tv_server_1_1.setText(GdMapUtil.getFriendlyDistance(distance));
server_show_data1.setBackground(getResources().getDrawable(R.drawable.nav_sever_0));
} else if (areaTypeb == 1) {
tv_server_1.setText(areaName.replace(getString(R.string.nav_server_pay), ""));
tv_server_1_1.setText(GdMapUtil.getFriendlyDistance(distance));
server_show_data1.setBackground(getResources().getDrawable(R.drawable.nav_sever_1));
}
if (distance < 10) { //小于10米 则隐藏服务区提示
hideServerArea1();
}
}
} else if (areaNum == 2) {
showServerArea2();
if (instance == 0) {
if (areaTypeb == 0) {
tv_server_1.setText(areaName.replace(getString(R.string.nav_server_server), ""));
tv_server_1_1.setText(GdMapUtil.getFriendlyDistance(distance));
server_show_data1.setBackground(getResources().getDrawable(R.drawable.nav_sever_0));
} else if (areaTypeb == 1) {
tv_server_1.setText(areaName.replace(getString(R.string.nav_server_pay), ""));
tv_server_1_1.setText(GdMapUtil.getFriendlyDistance(distance));
server_show_data1.setBackground(getResources().getDrawable(R.drawable.nav_sever_1));
}
if (distance < 10) { //小于10米 则隐藏服务区提示
hideServerArea1();
}
} else if (instance == 1) {
if (areaTypeb == 0) {
tv_server_2.setText(areaName.replace(getString(R.string.nav_server_server), ""));
tv_server_2_2.setText(GdMapUtil.getFriendlyDistance(distance));
server_show_data2.setBackground(getResources().getDrawable(R.drawable.nav_sever_0));
} else if (areaTypeb == 1) {
tv_server_2.setText(areaName.replace(getString(R.string.nav_server_pay), ""));
tv_server_2_2.setText(GdMapUtil.getFriendlyDistance(distance));
server_show_data2.setBackground(getResources().getDrawable(R.drawable.nav_sever_1));
}
if (distance < 10) { //小于10米 则隐藏服务区提示
hideServerArea2();
}
}
}
}
ServiceAreaDataBean.java
package com.itas.klong.nav.Bean;
/**
* Created by Administrator on 2018/1/25.
*/
public class ServiceAreaDataBean {
/**
* 回调数据个数
*/
private int areaNum;
/**
* 回调数据单号 0 1
*/
private int areaInstance;
/**
* 服务区类型
* 0 服务区
* 1 收费站
*/
private int areaType;
/**
* 服务区名称
*/
private String areaName;
/**
* 服务区距离
*/
private int areaDistance;
public int getAreaNum() {
return areaNum;
}
public void setAreaNum(int areaNum) {
this.areaNum = areaNum;
}
public int getAreaInstance() {
return areaInstance;
}
public void setAreaInstance(int areaInstance) {
this.areaInstance = areaInstance;
}
public int getAreaType() {
return areaType;
}
public void setAreaType(int areaType) {
this.areaType = areaType;
}
public String getAreaName() {
return areaName;
}
public void setAreaName(String areaName) {
this.areaName = areaName;
}
public int getAreaDistance() {
return areaDistance;
}
public void setAreaDistance(int areaDistance) {
this.areaDistance = areaDistance;
}
}
导航界面代码如下:
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import com.amap.api.navi.AMapNavi;
import com.amap.api.navi.AMapNaviListener;
import com.amap.api.navi.AMapNaviView;
import com.amap.api.navi.AMapNaviViewListener;
import com.amap.api.navi.AMapNaviViewOptions;
import com.amap.api.navi.model.AMapLaneInfo;
import com.amap.api.navi.model.AMapNaviCross;
import com.amap.api.navi.model.AMapNaviInfo;
import com.amap.api.navi.model.AMapNaviLocation;
import com.amap.api.navi.model.AMapNaviPath;
import com.amap.api.navi.model.AMapNaviTrafficFacilityInfo;
import com.amap.api.navi.model.AimLessModeCongestionInfo;
import com.amap.api.navi.model.AimLessModeStat;
import com.amap.api.navi.model.NaviInfo;
import com.amap.api.navi.model.NaviLatLng;
import com.autonavi.tbt.NaviStaticInfo;
import com.autonavi.tbt.TrafficFacilityInfo;
import java.util.ArrayList;
import java.util.List;
public class NavActivity extends Activity implements AMapNaviListener,AMapNaviViewListener {
AMapNaviView mAMapNaviView;
AMapNavi mAMapNavi;
NaviLatLng mEndLatlng = new NaviLatLng(xxxx, xxxx);
NaviLatLng mStartLatlng= new NaviLatLng(xxxx, xxxxc);;
List mStartList = new ArrayList();
List mEndList = new ArrayList();
List mWayPointList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_basic_navi);
mAMapNavi = AMapNavi.getInstance(getApplicationContext());
mAMapNavi.addAMapNaviListener(this);
mAMapNavi.setEmulatorNaviSpeed(60);
mAMapNavi.startNavi(AMapNavi.EmulatorNaviMode); //模拟导航模式
mAMapNaviView = (AMapNaviView) findViewById(R.id.navi_view);
mAMapNaviView.onCreate(savedInstanceState);
mAMapNaviView.setAMapNaviViewListener(this);
setAmapNaviViewOptions();
}
private void setAmapNaviViewOptions() {
if (mAMapNaviView == null) {
return;
}
AMapNaviViewOptions viewOptions = new AMapNaviViewOptions();
viewOptions.setSettingMenuEnabled(false);//设置菜单按钮是否在导航界面显示
viewOptions.setNaviNight(false);//设置导航界面是否显示黑夜模式
viewOptions.setReCalculateRouteForYaw(true);//设置偏航时是否重新计算路径
viewOptions.setReCalculateRouteForTrafficJam(true);//前方拥堵时是否重新计算路径
viewOptions.setTrafficInfoUpdateEnabled(true);//设置交通播报是否打开
viewOptions.setCameraInfoUpdateEnabled(true);//设置摄像头播报是否打开
viewOptions.setScreenAlwaysBright(true);//设置导航状态下屏幕是否一直开启。
viewOptions.setCrossDisplayEnabled(false); //设置导航时 路口放大功能是否显示
viewOptions.setTrafficBarEnabled(false); //设置 返回路况光柱条是否显示(只适用于驾车导航,需要联网)
viewOptions.setMonitorCameraEnabled(true); //设置摄像头图标是否显示 是
// viewOptions.setLayoutVisible(false); //设置导航界面UI是否显示
//viewOptions.setNaviViewTopic(mThemeStle);//设置导航界面的主题
//viewOptions.setZoom(16);
viewOptions.setTilt(0); //2D显示
mAMapNaviView.setViewOptions(viewOptions);
}
@Override
protected void onResume() {
super.onResume();
mAMapNaviView.onResume();
mStartList.add(mStartLatlng);
mEndList.add(mEndLatlng);
}
@Override
protected void onPause() {
super.onPause();
// mAMapNavi.stopNavi();
}
@Override
protected void onDestroy() {
super.onDestroy();
mAMapNaviView.onDestroy();
//since 1.6.0
//不再在naviview destroy的时候自动执行AMapNavi.stopNavi();
//请自行执行
mAMapNavi.stopNavi();
mAMapNavi.destroy();
}
/**
* 导航创建失败时的回调函数
*/
@Override
public void onInitNaviFailure() {
Log.e("nav", "导航创建失败" );
}
/**
* 导航创建成功时的回调函数
*/
@Override
public void onInitNaviSuccess() {
/**
* 方法:
* int strategy=mAMapNavi.strategyConvert(congestion, avoidhightspeed, cost, hightspeed, multipleroute);
* 参数:
* @congestion 躲避拥堵
* @avoidhightspeed 不走高速
* @cost 避免收费
* @hightspeed 高速优先
* @multipleroute 多路径
*
* 说明:
* 以上参数都是boolean类型,其中multipleroute参数表示是否多条路线,如果为true则此策略会算出多条路线。
* 注意:
* 不走高速与高速优先不能同时为true
* 高速优先与避免收费不能同时为true
*/
int strategy=0;
try {
strategy = mAMapNavi.strategyConvert(true,false,false,false, false); //自己设置。。
} catch (Exception e) {
e.printStackTrace();
}
mAMapNavi.calculateDriveRoute(mStartList, mEndList, mWayPointList, strategy);
Log.e("nav", "导航创建成功" );
}
/**
* type - 导航类型,1 : 实时导航,2 :模拟导航
* @param type
*/
@Override
public void onStartNavi(int type) {
Log.e("nav", "启动导航后回调函数"+type );
}
/**
* 当前方路况光柱信息有更新时回调函数。
*/
@Override
public void onTrafficStatusUpdate() {
}
/**
* 当GPS位置有更新时的回调函数
* @param location
*/
@Override
public void onLocationChange(AMapNaviLocation location) {
}
/**
* 导航播报信息回调函数
* type - 播报类型,包含导航播报、前方路况播报和整体路况播报,类型请见NaviTTSType
* text - 播报文字
* @param type
* @param text
*/
@Override
public void onGetNavigationText(int type, String text) {
String NavInformationText = text; //测试---fan
}
/**
* 模拟导航停止后回调函数
*/
@Override
public void onEndEmulatorNavi() {
Log.e("nav","模拟导航停止");
}
/**
* 到达目的地后回调函数
*/
@Override
public void onArriveDestination() {
Log.e("nav", "到达目的地");
}
/**
* 到达目的地后回调函数(包含统计信息)
* @param naviStaticInfo
*/
@Override
public void onArriveDestination(NaviStaticInfo naviStaticInfo) {
}
/**
* 步行或者驾车路径规划成功后的回调函数
*/
@Override
public void onCalculateRouteSuccess() {
AMapNaviPath naviPath = mAMapNavi.getNaviPath();
if (naviPath == null) {
return;
}
mAMapNavi.startNavi(AMapNavi.EmulatorNaviMode);
Log.e("nav", "驾车路径规划成功" );
}
/**
* 步行或者驾车路径规划失败后的回调函数
* @param errorInfo
*/
@Override
public void onCalculateRouteFailure(int errorInfo) {
Log.e("nav", "驾车路径规划失败" +errorInfo);
}
/**
* 步行或驾车导航时,出现偏航后需要重新计算路径的回调函数
*/
@Override
public void onReCalculateRouteForYaw() {
}
/**
* 驾车导航时,如果前方遇到拥堵时需要重新计算路径的回调
*/
@Override
public void onReCalculateRouteForTrafficJam() {
}
/**
* 驾车路径导航到达某个途经点的回调函数
* wayID - 到达途径点的编号,标号从1开始,依次累加。 模拟导航下不工作
* @param wayID
*/
@Override
public void onArrivedWayPoint(int wayID) {
}
/**
* 用户手机GPS设置是否开启的回调函数
* enabled - true,开启;false,未开启
* @param enabled
*/
@Override
public void onGpsOpenStatus(boolean enabled) {
}
@Override
public void onNaviInfoUpdated(AMapNaviInfo naviInfo) {
}
/**
* 导航数据回调 ********重点
* 导航引导信息回调 naviinfo 是导航信息类
* naviinfo - 导航信息对象。
* @param naveinfo
*/
@Override
public void onNaviInfoUpdate(NaviInfo naveinfo) {
if (naveinfo == null) {
return;
}
// 很多的数据 ,在这里得到
// 算是重点区域吧
}
@Override
public void OnUpdateTrafficFacility(TrafficFacilityInfo trafficFacilityInfo) {
}
@Override
public void OnUpdateTrafficFacility(AMapNaviTrafficFacilityInfo aMapNaviTrafficFacilityInfo) {
}
/**
* 显示路口放大图回调
* aMapNaviCross - 路口放大图类,可以获得此路口放大图bitmap
* @param aMapNaviCross
*/
@Override
public void showCross(AMapNaviCross aMapNaviCross) {
}
/**
* 关闭路口放大图回调
*/
@Override
public void hideCross() {
}
/**
* 显示道路信息回调
* laneInfos - 道路信息数组,可获得各条道路分别是什么类型,可用于用户使用自己的素材完全自定义显示。
* laneBackgroundInfo - 道路背景数据数组,可用于装载官方的DriveWayView,并显示。
* laneRecommendedInfo - 道路推荐数据数组,可用于装载官方的DriveWayView,并显示。
* @param laneInfos
* @param laneBackgroundInfo
* @param laneRecommendedInfo
*/
@Override
public void showLaneInfo(AMapLaneInfo[] laneInfos, byte[] laneBackgroundInfo, byte[] laneRecommendedInfo) {
}
/**
* 关闭道路信息回调
*/
@Override
public void hideLaneInfo() {
}
/**
* 多路线算路成功回调
* */
@Override
public void onCalculateMultipleRoutesSuccess(int[] ints) {
Log.e("nav","多路线算路成功回调");
}
/**
* 通知当前是否显示平行路切换
* parallelRoadType - 0表示隐藏 1 表示显示主路 2 表示显示辅路
* @param i
*/
@Override
public void notifyParallelRoad(int i) {
}
/**
* 巡航模式(无路线规划)下,道路设施信息更新回调
* infos - 道路设施信息
* @param aMapNaviTrafficFacilityInfos
*/
@Override
public void OnUpdateTrafficFacility(AMapNaviTrafficFacilityInfo[] aMapNaviTrafficFacilityInfos) {
}
/**
* 巡航模式(无路线规划)下,统计信息更新回调 连续5个点大于15km/h后开始回调
* aimLessModeStat - 巡航模式(无路线规划)下统计信息
* @param aimLessModeStat
*/
@Override
public void updateAimlessModeStatistics(AimLessModeStat aimLessModeStat) {
}
/**
* 巡航模式(无路线规划)下,统计信息更新回调 当拥堵长度大于500米且拥堵时间大于5分钟时回调
* @param aimLessModeCongestionInfo
*/
@Override
public void updateAimlessModeCongestionInfo(AimLessModeCongestionInfo aimLessModeCongestionInfo) {
}
/**==================================================以下为AMapNaviViewListener监听回调======================================*/
/**
* 界面右下角功能设置按钮的回调接口
*/
@Override
public void onNaviSetting() {
}
/**
* 导航页面左下角返回按钮点击后弹出的『退出导航对话框』中选择『确定』后的回调接口
*/
@Override
public void onNaviCancel() {
finish();
}
/**
* 导航页面左下角返回按钮的回调接口 false-由SDK主动弹出『退出导航』对话框,true-SDK不主动弹出『退出导航对话框』,由用户自定义
* @return
*/
@Override
public boolean onNaviBackClick() {
return false;
}
/**
* 导航界面地图状态的回调
* isLock - 地图状态,0:车头朝上状态;1:非锁车状态,即车标可以任意显示在地图区域内。
* @param isLock
*/
@Override
public void onNaviMapMode(int isLock) {
}
/**
* 界面左上角转向操作的点击回调
*/
@Override
public void onNaviTurnClick() {
}
/**
* 界面下一道路名称的点击回调
*/
@Override
public void onNextRoadClick() {
}
/**
* 界面全览按钮的点击回调
*/
@Override
public void onScanViewButtonClick() {
}
/**
* 是否锁定地图的回调
* @param b
*/
@Override
public void onLockMap(boolean b) {
}
/**
* 导航view加载完成回调
*/
@Override
public void onNaviViewLoaded() {
}
@Override
protected void onStop() {
super.onStop();
}
}
效果图如下: