上周学习了高德地图和极光推送的SDK,需要在项目中用到,不过学习起来还是费了一番功夫去看文档和Demo代码的。(不得不吐槽部分文档真的无厘头,只有简单的实例程序注释都没有,上下文还不对接,真是醉了),所以打算把最直白的步骤写在博客中,也希望能帮到还不会用这两种SDK的小伙伴们,少走弯路,提高工作效率。
本文主要介绍高德地图SDK的使用步骤:
包括从获取Key,到导包,到布局文件,以及编码实现。
还有两个最常用的功能:
实现定位自身。
根据地名或者坐标实现搜索定位并显示小蓝点。
一、获取高德Key:
点击这里进入高德控制台,点击创建应用,输入应用名称和应用类型。
应用创建完成后,点击添加key开始添加新key:
SHA1码的获取方式有两种:
1、Eclipse可以直接从Preferances -> Android -> Build查看当前应用的SHA1值。
2、AndroidStudio用户有两种方式,第一种通过命令行语句获得,不过这样子还要签名要费一番周折,第二种方式最简单直接用一个方法输出当前应用的SHA1值,复制下来就可以了,方法如下(高德文档提供):
public static String sHA1(Context context) {
try {
PackageInfo info = context.getPackageManager().getPackageInfo(
context.getPackageName(), PackageManager.GET_SIGNATURES);
byte[] cert = info.signatures[0].toByteArray();
MessageDigest md = MessageDigest.getInstance("SHA1");
byte[] publicKey = md.digest(cert);
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < publicKey.length; i++) {
String appendString = Integer.toHexString(0xFF & publicKey[i])
.toUpperCase(Locale.US);
if (appendString.length() == 1)
hexString.append("0");
hexString.append(appendString);
hexString.append(":");
}
String result = hexString.toString();
Log.d("xiaojingyu", result);
return result.substring(0, result.length() - 1);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
之后提交,就会得到一串类似于38bcab8bxxxxxx5bed57ba835e1的字符,这就是我们开发所需要的key了。
二、导包:
eclipse就不说了,直接把包放到libs里就可以了。
AndroidStudio复杂一点,但也就是放到libs里再add 到library就行了。
如下几个是需要用到的包:
以及包下载地址
三、获取权限:
需要的权限都要添加进AndroidMainfest.xml文件中:
首先是布局文件:
设置高德sdk指定的MapView:
MapView mMapView = null;
那这个MapView的作用是什么呢?读完代码(文档并不会告诉你)我们可以发现它是地图的View,需要实现地图的生命周期管理:
mMapView = (MapView) v.findViewById(R.id.map);
//在activity执行onCreate时执行mMapView.onCreate(savedInstanceState),实现地图生命周期管理
mMapView.onCreate(savedInstanceState);
当然起到控制作用的还有一个关键类AMap,起到对地图的一些基本管理以及控制接口作用,我们可以在初始化的时候进行如下操作来初始化amap实例:
if (aMap == null) {
aMap = mMapView.getMap();
aMap.moveCamera(CameraUpdateFactory.zoomTo(0)); //设置缩放为0,则一进来就显示整个中国大陆
aMap.setLocationSource(this);// 设置定位监听
aMap.getUiSettings().setMyLocationButtonEnabled(true);// 设置默认定位按钮是否显示
aMap.setMyLocationEnabled(true);// 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false
// 设置定位的类型为定位模式 ,可以由定位、跟随或地图根据面向方向旋转几种
aMap.setMyLocationType(AMap.LOCATION_TYPE_LOCATE);
}
实现当前位置系统小蓝点:
我们可以用当前Activity实现AMap定位监听AMapLocationListener,并重写它的定位方法:
@Override
public void onLocationChanged(AMapLocation amapLocation) {
if (mListener != null && amapLocation != null) {
if (amapLocation != null
&& amapLocation.getErrorCode() == 0) {
mListener.onLocationChanged(amapLocation);// 显示系统小蓝点
} else {
String errText = "定位失败," + amapLocation.getErrorCode() + ": " + amapLocation.getErrorInfo();
Log.e("AmapErr", errText);
}
}
}
这里还要用到一个位置改变监听:OnLocationChangedListener,通过它的方法onLocationChanged(amaplocation)来实现地图上位置的改变!
可以看到在Amap的初始化的代码中需要设置定位监听,所以需要当前Activity实现LocationSource接口,并重写激活定位以及停止定位两个接口方法:
/**
* 激活定位
*/
@Override
public void activate(OnLocationChangedListener listener) {
Log.d("xiaojingyu", "activate");
mListener = listener;
if (mLocationClient == null) {
mLocationClient = new AMapLocationClient(getActivity());
mLocationOption = new AMapLocationClientOption();
//设置定位监听
mLocationClient.setLocationListener(this);
//设置为高精度定位模式
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
//设置定位参数
mLocationClient.setLocationOption(mLocationOption);
// 此方法为每隔固定时间会发起一次定位请求,为了减少电量消耗或网络流量消耗,
// 注意设置合适的定位时间的间隔(最小间隔支持为2000ms),并且在合适时间调用stopLocation()方法来取消定位请求
// 在定位结束后,在合适的生命周期调用onDestroy()方法
// 在单次定位情况下,定位无论成功与否,都无需调用stopLocation()方法移除请求,定位sdk内部会移除
mLocationClient.startLocation();
}
}
/**
* 停止定位
*/
@Override
public void deactivate() {
Log.d("xiaojingyu", "deactivate");
mListener = null;
if (mLocationClient != null) {
mLocationClient.stopLocation();
mLocationClient.onDestroy();
}
mLocationClient = null;
}
这里需要用到一个定位的Client对象,以及一个Option位置对象
记得申明:
public AMapLocationClient mLocationClient = null;
public AMapLocationClientOption mLocationOption = null;
//搜索组件 private GeocodeSearch geocoderSearch; private Marker geoMarker;
geocoderSearch = new GeocodeSearch(getActivity());
geocoderSearch.setOnGeocodeSearchListener(this);
geoMarker = aMap.addMarker(new MarkerOptions().anchor(0.5f, 0.5f)
.icon(BitmapDescriptorFactory
.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)));
其中geoMarker是用来显示定位成功之后的小蓝点。
/**
* 响应地理编码
*/
public void getLatlon(final String name) {
//showDialog();
GeocodeQuery query = new GeocodeQuery(name, "0086");// 第一个参数表示地址,第二个参数表示查询城市,中文或者中文全拼,citycode、adcode,
geocoderSearch.getFromLocationNameAsyn(query);// 设置同步地理编码请求
}
其中第二个参数我设置成0086是中国的区号,这样可以实现全国范围内查找。比如我只设置成长沙的区号0731,那么我只能输入长沙的地名进行查找,再查比如岳阳是查不到的。
之后会回调geocoderSearch的监听方法实现定位:
@Override
public void onGeocodeSearched(GeocodeResult result, int rCode) {
//dismissDialog();
if (rCode == 1000) {
if (result != null && result.getGeocodeAddressList() != null
&& result.getGeocodeAddressList().size() > 0) {
GeocodeAddress address = result.getGeocodeAddressList().get(0);
aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
AMapUtil.convertToLatLng(address.getLatLonPoint()), 15));
geoMarker.setPosition(AMapUtil.convertToLatLng(address
.getLatLonPoint()));
addressName = "经纬度值:" + address.getLatLonPoint() + "\n位置描述:"
+ address.getFormatAddress();
// ToastUtil.show(getActivity(), addressName);
} else {
ToastUtil.show(getActivity(), "没有查询到结果~!");
}
} else {
ToastUtil.showerror(getActivity(), rCode);
}
}
用到的功能大概就是这些,如果还需要其他的功能可以参考高德SDK官方文档:
http://lbs.amap.com/api/android-location-sdk/guide/android-location/getlocation/
最后是我最后实现的效果动图:
因为涉及项目相关,所以不能把全部源码贴上来了。
有问题的朋友在评论区留言,我会一一解答。
**********************************************分隔线***************************************************
应评论区朋友的要求,在这里贴上响应逆地理编码的代码:
/**
* 响应逆地理编码
*/
public void getAddress(final LatLonPoint latLonPoint) {
showDialog();
RegeocodeQuery query = new RegeocodeQuery(latLonPoint, 200,
GeocodeSearch.AMAP);// 第一个参数表示一个Latlng,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系
geocoderSearch.getFromLocationAsyn(query);// 设置同步逆地理编码请求
}
/**
* 逆地理编码回调
*/
@Override
public void onRegeocodeSearched(RegeocodeResult result, int rCode) {
dismissDialog();
if (rCode == 1000) {
if (result != null && result.getRegeocodeAddress() != null
&& result.getRegeocodeAddress().getFormatAddress() != null) {
addressName = result.getRegeocodeAddress().getFormatAddress()
+ "附近";
aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
AMapUtil.convertToLatLng(latLonPoint), 15));
regeoMarker.setPosition(AMapUtil.convertToLatLng(latLonPoint));
ToastUtil.show(GeocoderActivity.this, addressName);
} else {
ToastUtil.show(GeocoderActivity.this, R.string.no_result);
}
} else {
ToastUtil.showerror(this, rCode);
}
}