上周学习了高德地图和极光推送的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文件中:
<!--用于进行网络定位--> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission> <!--用于访问GPS定位--> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission> <!--获取运营商信息,用于支持提供运营商信息相关的接口--> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission> <!--用于访问wifi网络信息,wifi信息会用于进行网络定位--> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission> <!--这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位--> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission> <!--用于访问网络,网络定位需要上网--> <uses-permission android:name="android.permission.INTERNET"></uses-permission> <!--用于读取手机当前的状态--> <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission> <!--写入扩展存储,向扩展卡写入数据,用于写入缓存定位数据--> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
四、编码实现:
首先是布局文件:
设置高德sdk指定的MapView:
<com.amap.api.maps.MapView android:id="@+id/map" android:layout_width="match_parent" android:layout_height="0dp" android:layout_marginTop="10dp" android:layout_weight="1" android:focusable="true" android:focusableInTouchMode="true"> </com.amap.api.maps.MapView>
于是开始代码的编写。既然布局文件中用到了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;
都需要在onCreate之后就进行初始化:
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/
最后是我最后实现的效果动图:
因为涉及项目相关,所以不能把全部源码贴上来了。
有问题的朋友在评论区留言,我会一一解答。
实现当前位置系统小蓝点:
我们可以用当前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)来实现地图上位置的改变!