Android 高德地图的使用, 狠详细! 手把手!(地图 + 定位 + 逆地理编码 + 输入提示 + Poi 搜索)

8,127 阅读7分钟

最近项目用到高德地图,因此来写一篇文章理一下高德的使用步骤方法,希望对大家有用!

1.注册+配置

废话不多说,要使用高德地图首先要去高德开放平台注册成为开发者(lbs.amap.com/), 注册成为高德开发者需要分三步:第一步,注册高德开发者;第二步,去控制台创建应用;第三步,获取Key(见下图,注意看命名规范,SHA1值得获取网上有!很简单)。


获取key


ok之后,到官网下载高德SDK(lbs.amap.com/api/android…), 我这边全部都下载了,解压后,得到一个 AMap3DMap_xxxxx(版本号).jar 文件和一个 armeabi 文件夹,之后,(一)将jar包拷贝到你项目的libs目录下.(二)在 main 目录下创建文件夹 jniLibs (如果有就不需要创建了),将armeabi 文件夹复制到这个目录下,如果已经有这个目录,将下载的 so 库复制到这个目录即可.见图(也可以参考高德官网的第二种配置方式):


Studio 配置工程

别忘了添加File依赖:


FileDependencies

好了,前期准备弄好,终于可以上代码了.

2.地图

1.在清单文件中配置key:

1  

2.配置权限(把下面这堆配置进去,再也不用担心bug出在权限问题上了):




















3.在布局文件中加载地图控件:


4.你只要在onCreate()中添加如下几行代码,高德地图就显示出来了!

MapView mapView = (MapView) findViewById(R.id.map);//找到地图控件
mapView.onCreate(savedInstanceState);// 此方法必须重写
AMap aMap = mapView.getMap();//得到一个map对象

是不是很简单!再此我还是想说下,高德地图的软实力和百度地图是有差距的,但是高德的开发文档要比百度很人性化!
接下来我们来使用定位功能在地图上添加点标记玩玩.

3.定位+添加标记

第一种方式(基础,可参考官网,链接在此:lbs.amap.com/api/android…):

//初始化定位
mLocationClient = new AMapLocationClient(getApplicationContext());
//初始化AMapLocationClientOption对象
mLocationOption = new AMapLocationClientOption();
//设置定位模式为高精度模式。
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
//设置定位回调监听
mLocationClient.setLocationListener(this);
//获取一次定位结果
mLocationOption.setOnceLocation(true);
//设置是否返回地址信息(默认返回地址信息)
mLocationOption.setNeedAddress(true);
//给定位客户端对象设置定位参数
mLocationClient.setLocationOption(mLocationOption);
//启动定位
mLocationClient.startLocation();

之后在监听器的回调方法内解析AMapLocation对象,里面包含地址,省市县街道,地区编码,城市编码等等等,可以在此添加标记,定位当前位置,你问我如何把标记固定在屏幕中央?也在这里面:

//----------------------这是位置改变监听------------------------------------    
@Override    
public void onLocationChanged(AMapLocation aMapLocation) {        
      if (aMapLocation != null) {            
          if (aMapLocation.getErrorCode() == 0) {                
              //可在其中解析amapLocation获取相应内容。                         
              LatLng latLng = new LatLng(aMapLocation.getLatitude(),       
              aMapLocation.getLongitude());//取出经纬度               
             //添加Marker显示定位位置                
            if (locationMarker == null) {                    
            //如果是空的添加一个新的,icon方法就是设置定位图标,可以自定义                    
            locationMarker = aMap.addMarker(new MarkerOptions()                           
            .position(latLng).snippet("最快1分钟到达").draggable(true).setFlat(true));                    
            locationMarker.showInfoWindow();//主动显示indowindow                    
            aMap.addText(new TextOptions().position(latLng).text(aMapLocation.getAddress()));                    
            //固定标签在屏幕中央                    
            locationMarker.setPositionByPixels(mMapView.getWidth() / 2,mMapView.getHeight() / 2);                 
        } else {                   
           //已经添加过了,修改位置即可                    
          locationMarker.setPosition(latLng);                
        }                
       //然后可以移动到定位点,使用animateCamera就有动画效果                
       aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15));//参数提示:1.经纬度 2.缩放级别                        
       }else {                          
        //定位失败时,可通过ErrCode(错误码)信息来确定失败的原因,errInfo是错误信息,详见错误码表。                
        Log.e("AmapError","location Error, ErrCode:" +aMapLocation.getErrorCode() + ", errInfo:"+ aMapLocation.getErrorInfo());            
          }       
     }    
}

第二种方式,实现OnMapLoadedListener,在回调方法中首先添加一个标记在地图中央,之后封装一个方法,开启单次定位即可:

aMap.setOnMapLoadedListener(this);
//----------------------OnMapLoaded 当地图加载完成时回调此方法------------------------------------------    
    @Override
    public void onMapLoaded() {
        MarkerOptions markerOptions = new MarkerOptions();        
        markerOptions.setFlat(true);
        markerOptions.anchor(0.5f, 0.5f);            
        markerOptions.position(new LatLng(0, 0));        
        markerOptions.snippet("最快1分钟到达").draggable(true).setFlat(true);        
        markerOptions.icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(),                                R.drawable.icon_loaction_start)));
        mPositionMark = aMap.addMarker(markerOptions);
        mPositionMark.showInfoWindow();//主动显示indowindow
        mPositionMark.setPositionByPixels(mMapView.getWidth() / 2,mMapView.getHeight() / 2);
        mLocationTask.startSingleLocate();    }


封装的单次定位方法在此,很简单:

//开启单次定位
public void startSingleLocate() {
    AMapLocationClientOption option=new AMapLocationClientOption();
    option.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
    option.setOnceLocation(true);
    mLocationClient.setLocationOption(option);
    mLocationClient.startLocation();
}

是时候贴张效果图图了:


是的,很丑


关于怎么让按钮悬浮在地图上?也很简单啊



    
        
        
        
        
            
            
            
        
        
    

4.地理编码+逆地理编码

下面来说一下地理编码(地址转坐标)/逆地理编码(坐标转地址)功能,依然很简单,再次提一下高德人性化的文档!
地址转坐标实现步骤:

//构造 GeocodeSearch 对象,并设置监听。
geocodeSearch = new GeocodeSearch(this);
geocodeSearch.setOnGeocodeSearchListener(this);
//通过GeocodeQuery设置查询参数,调用getFromLocationNameAsyn(GeocodeQuery geocodeQuery) 方法发起请求。
//address表示地址,第二个参数表示查询城市,中文或者中文全拼,citycode、adcode都ok 
GeocodeQuery query = newGeocodeQuery(address, "010"); 
geocoderSearch.getFromLocationNameAsyn(query);

坐标转地址实现步骤:

oderSearch = new GeocodeSearch(this);
geocoderSearch.setOnGeocodeSearchListener(this);//和上面一样
// 第一个参数表示一个Latlng(经纬度),第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系
RegeocodeQuery query = newRegeocodeQuery(latLonPoint, 200,GeocodeSearch.AMAP); 
geocoderSearch.getFromLocationAsyn(query);

之后再回调方法中解析即可:

//------------------------坐标转地址/坐标转地址的监听回调-------------------------
//result里面有你想要的结果.
    @Override
    public void onRegeocodeSearched(RegeocodeResult result, int rCode) {
       result.getGeocodeAddressList().get(0).getLatLonPoint();
    }
    @Override
    public void onGeocodeSearched(GeocodeResult result, int rCode) {
       result.getRegeocodeAddress().getFormatAddress();
    }

5.输入提示+Poi搜索

最后是搜索提示+Poi搜索功能:先上效果图:


Poi搜索

实现步骤:

这边已经提供了两个封装好的类,一个是输入提示 一个是Poi搜索

import android.content.Context;import android.util.Log;
import com.amap.api.services.core.AMapException;
import com.amap.api.services.help.Inputtips;
import com.amap.api.services.help.Inputtips.InputtipsListener;
import com.amap.api.services.help.Tip;
import java.util.ArrayList;import java.util.List;
/**
   * ClassName:InputTipTask 
* Function: 简单封装了Inputtips的搜索服务,将其余提示的adapter进行数据绑定 * @author yiyi.qi * @version * @since JDK 1.6 * @see */ public class InputTipTask implements InputtipsListener { private static InputTipTask mInputTipTask; private Inputtips mInputTips; private RecomandAdapter mAdapter; Context mContext; public static InputTipTask getInstance(Context context, RecomandAdapter adapter){ if(mInputTipTask==null){ mInputTipTask=new InputTipTask(context); } //单例情况,多次进入DestinationActivity传进来的RecomandAdapter对象会不是同一个 mInputTipTask.setRecommandAdapter(adapter); return mInputTipTask; } public void setRecommandAdapter(RecomandAdapter adapter){ mAdapter=adapter; } private InputTipTask(Context context ){ mInputTips=new Inputtips(context, this); } public void searchTips(String keyWord, String city){ try { mInputTips.requestInputtips(keyWord, city); } catch (AMapException e) { e.printStackTrace(); } } @Override public void onGetInputtips(List tips, int resultCode) { //v3.2.1及以上版本SDK 返回码1000是正常 千万注意 if(resultCode==1000&&tips!=null){ ArrayList positions=new ArrayList(); for(Tip tip:tips){ //经纬度 address city(adcode) positions.add(new PositionEntity(0, 0, tip.getName(),tip.getAdcode())); } mAdapter.setPositionEntities(positions); mAdapter.notifyDataSetChanged(); PoiSearchTask poiSearchTask=new PoiSearchTask(mContext.getApplicationContext(), mAdapter); for(int i = 0;i
import android.content.Context;
import com.amap.api.services.core.PoiItem;
import com.amap.api.services.poisearch.PoiResult;
import com.amap.api.services.poisearch.PoiSearch;
import com.amap.api.services.poisearch.PoiSearch.OnPoiSearchListener;
import com.amap.api.services.poisearch.PoiSearch.Query;
import java.util.ArrayList;import java.util.List;
/** 
 * ClassName:PoiSearchTask 
* Function: 简单封装了poi搜索的功能,搜索结果配合RecommendAdapter进行使用显示
* @author yiyi.qi * @version * @since JDK 1.6 * @see */ public class PoiSearchTask implements OnPoiSearchListener { private Context mContext; private RecomandAdapter mRecommandAdapter; public PoiSearchTask(Context context, RecomandAdapter recomandAdapter) { mContext = context; mRecommandAdapter = recomandAdapter; } public void search(String keyWord, String city) { Query query = new PoiSearch.Query(keyWord, "", city); query.setPageSize(10); query.setPageNum(0); PoiSearch poiSearch = new PoiSearch(mContext, query); poiSearch.setOnPoiSearchListener(this); poiSearch.searchPOIAsyn(); } @Override public void onPoiSearched(PoiResult poiResult, int resultCode) { if (resultCode == 1000 && poiResult != null) { ArrayList pois=poiResult.getPois(); if(pois==null){ return; } List entities=new ArrayList(); for(PoiItem poiItem:pois){ PositionEntity entity=new PositionEntity(poiItem.getLatLonPoint().getLatitude(), poiItem.getLatLonPoint().getLongitude(), poiItem.getTitle(),poiItem.getCityName()); entities.add(entity); } mRecommandAdapter.setPositionEntities(entities); mRecommandAdapter.notifyDataSetChanged(); } //TODO 可以根据app自身需求对查询错误情况进行相应的提示或者逻辑处理 } @Override public void onPoiItemSearched(PoiItem poiItem, int i) {}}

你要做的 只是拷贝这连个类到工程中,然后在搜索的Activity中实现TextWatcher接口后,进行如下调用:

//在onTextChanged方法中调用InputTipTask 的getInstance方法
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
       if (RouteTask.getInstance(getApplicationContext()).getStartPoint() == null) {
       Toast.makeText(getApplicationContext(), "检查网络,Key等问题", Toast.LENGTH_SHORT).show();
       return;
}
InputTipTask.getInstance(getApplicationContext(), mRecomandAdapter).searchTips(s.toString(),
        RouteTask.getInstance(getApplicationContext()).getStartPoint().city);
}

输入提示完成.如果你希望点选后进行更详细的Poi搜索,也只需在相应位置调用:

//生成poiSearchTask对象
PoiSearchTask poiSearchTask=new PoiSearchTask(getApplicationContext(),mRecomandAdapter);
//开始进行POI搜索
poiSearchTask.search(mDestinaionText.getText().toString(),RouteTask.getInstance(getApplicationContext()).getStartPoint().city);

以上需要一个位置的实体Bean:

/** 
* ClassName:PositionEntity 
* Function: 封装的关于位置的实体
* @author yiyi.qi * @version * @since JDK 1.6 * @see */ public class PositionEntity { @Override public String toString() { return "PositionEntity{" + "latitue=" + latitue + ", longitude=" + longitude + ", address='" + address + '\'' + ", city='" + city + '\'' + '}'; } public double latitue; public double longitude; public String address; public String city; public PositionEntity() {} public PositionEntity(double latitude, double longtitude, String address, String city) { this.latitue = latitude; this.longitude = longtitude; this.address = address; this.city = city; } }

之后会带来导航相关文章,如果哪里不懂或者写的不对的地方可以联系我!有不足之处还请多多包涵!谢谢最后贴一个地址,如果有用到聚合Marker的可以传送到此,很详细:

lbsbbs.amap.com/forum.php?m…