Android 高德地图定位

前言

今天,我们一起来聊聊有关地图方面的内容吧。

目前比较好的地图第三方分别如下:

经过网上简单搜索后,简单得出以下结论:

  1. 百度地图,功能齐全,牛掰,无奈地图更新不是很及时;

  2. 高德地图,专注地图n余年,开发文档以及后续支持比较好,苹果手机内置地图也同样为高德地图(大高德666~);

  3. 腾讯地图,没怎么使用过;

  4. 谷歌Baba大地图,貌似需要翻墙,比较心累~

So,经过简单了解后,让我们愉快的开启玩转高德地图之旅吧~

开启高德地图探索之旅

一. 查看官方攻略

这个就很简单了,我们找到高德地图API,按照官方溜达溜达去。

1.百度搜索高德地图api

这里写图片描述

点击进入,选择 “开发与支持” 在点击”Android 地图 SDK”

这里写图片描述

2.获取地图开发Key

首先我们需要注册成为高德地图开发者,这里不做过多说明。

接下来在控制台创建应用,如下图:

这里写图片描述

之后点击创建Key,高德hint给的很全面,大家按照要求来即可。

关于获取SHA1,大家可以参考LZ之前写的博文:AndroidStudio获取SHA1值

这里写图片描述

获取到key,我们一起粗略了解下官方提供相关知识。

3.了解官方干货

谷歌官方将地图相关SDK区分为五大类,如下图:

这里写图片描述

在这里,大家可能会疑问,2D地图 3D地图,这又是什么鬼?别急,下面为大家附上官方解释。

这里写图片描述

LZ果断选择3D地图,不要问为什么,就是喜欢新的!!!

4.下载SDK

这里写图片描述

下载完成之后,运行的时候需要在高德上申请key,否则无法运行!

最好还是下载SDK所有的,都看看,也耽误不了多少功夫。

如下图,简介明了,大家根据需求去进行开发,这里就不做过多说明了。

这里写图片描述

该了解的也差不多了,下面开启撸码之路~

二. 编码路漫漫其修远兮,吾必将上下而求索。

先来个小目标,实现显示高德地图

第一步,配置AndroidManifest.xml,添加基本权限

    <!--项目权限模块(这里写这个的目的就是为了方便,将权限中区分开不同的模块,便于后期其他人进行维护,管理)-->
    <!--允许程序打开网络套接字-->
    <uses-permission android:name="android.permission.INTERNET"/>
    <!--允许程序设置内置sd卡的写权限-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <!--允许程序获取网络状态-->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <!--允许程序访问WiFi网络信息-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <!--允许程序读写手机状态和身份-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <!--允许程序访问CellID或WiFi热点来获取粗略的位置-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

设置高德Key

        <!-- 项目第三方key配置模块 -->
        <!-- 高德地图key -->
        <meta-data
            android:name="com.amap.api.v2.apikey"
            android:value="98e3f4440af277a2f390b724602168f7(这里填写个人申请的key即可)"/>

第二步,向工程中添加地图所需so库以及引入开发包

首先添加so文件,在src/main/目录下新建jniLibs目录,并将文件放入其中,LZ这里只兼容armeabi以及arm64-v8a;

有关armeabi简单知识,大家可查阅LZ之前总结的博文:

Android 中arm64-v8a、armeabi-v7a、armeabi、x86简介~

添加完成后,如下所示:

这里写图片描述

接下来,配置dependencies,由于我们第一个目标是要实现显示地图,所以我们要在项目的build.gradle中添加如下一行地址即可。

compile ‘com.amap.api:3dmap:latest.integration’

如下图:

这里写图片描述

之后点击右上方的sync now,万能的死丢丢会亲自下载相关包~

第三步,初始化地图容器

在我们的layout中,添加地图控件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="cn.hlq.gaodemapdemo.map.GaoDeLocationActivity">

    <com.amap.api.maps.MapView
        android:id="@+id/id_gaode_location_map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

Activity管理地图生命周期

package cn.hlq.gaodemapdemo.map;

import android.app.Activity;
import android.os.Bundle;

import com.amap.api.maps.AMap;
import com.amap.api.maps.MapView;

import cn.hlq.gaodemapdemo.R;

/**
 * create by heliquan at 2017年5月4日23:26:59
 */
public class GaoDeLocationActivity extends Activity {

    private MapView mapView;

    private AMap aMap;

    @Override
    protected void onResume() {
        super.onResume();
        // 重新绘制加载地图
        mapView.onResume();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gao_de_location);
        initView();
        // 创建地图
        mapView.onCreate(savedInstanceState);
    }

    @Override
    protected void onPause() {
        super.onPause();
        // 暂停地图的绘制
        mapView.onPause();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 销毁地图
        mapView.onDestroy();
    }

    /**
     * 重写此方法,在activity执行onSaveInstanceState时执行mMapView.onSaveInstanceState (outState),保存地图当前的状态
     *
     * @param outState
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mapView.onSaveInstanceState(outState);
    }

    private void initView() {
        // 实例化地图控件
        mapView = (MapView) findViewById(R.id.id_gaode_location_map);
    }

}

在这里也简单为大家拓展下小知识。

这里写图片描述

第四步,显示地图

    private void initView() {
        // 实例化地图控件
        mapView = (MapView) findViewById(R.id.id_gaode_location_map);
        if (aMap == null) {
            // 显示地图
            aMap = mapView.getMap();
        }
    }

第五步,查看我们的成果

这里写图片描述

到此,地图显示,我们已经完成了~

接下来,开启定位之旅~

接着,再来个小目标,实现高德地图定位

第一步,引入定位依赖~

compile ‘com.amap.api:location:latest.integration’

第二步,添加高德地图定位服务

<!-- 项目Service模块 -->

    <!-- GaoDeLocationService -->
    <service android:name="com.amap.api.location.APSService"/>

第三步,实现定位监听,重写三个方法

implements <font color="#FF0000" style="box-sizing: border-box;">LocationSource, AMapLocationListener</font>

LZ在这里就直接贴代码了,相关注释也写的很明确了~!

    @TargetApi(Build.VERSION_CODES.N)
    @Override
    public void onLocationChanged(AMapLocation aMapLocation) {
        // 解析AMapLocation对象
        // 判断AMapLocation对象不为空,当定位错误码类型为0时定位成功
        if (aMapLocation != null) {
            if (aMapLocation.getErrorCode() == 0) {
                aMapLocation.getLocationType(); // 获取当前定位结果来源,如网络定位结果,详见定位类型表
                aMapLocation.getLatitude(); // 获取纬度
                aMapLocation.getLongitude(); // 获取经度
                aMapLocation.getAccuracy(); // 获取精度信息
                aMapLocation.getAddress(); // 地址,如果option中设置isNeedAddress为false,则没有此结果,网络定位结果中会有地址信息,GPS定位不返回地址信息。
                aMapLocation.getCountry(); // 国家信息
                aMapLocation.getProvince(); // 省信息
                aMapLocation.getCity(); // 城市信息
                aMapLocation.getDistrict(); // 城区信息
                aMapLocation.getStreet(); // 街道信息
                aMapLocation.getStreetNum(); // 街道门牌号信息
                aMapLocation.getCityCode(); // 城市编码
                aMapLocation.getAdCode(); // 地区编码
                aMapLocation.getAoiName(); // 获取当前定位点的AOI信息
                aMapLocation.getBuildingId(); // 获取当前室内定位的建筑物Id
                aMapLocation.getFloor(); // 获取当前室内定位的楼层
                aMapLocation.getGpsAccuracyStatus(); // 获取GPS的当前状态
                // 获取定位时间
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date date = new Date(aMapLocation.getTime());
                df.format(date);
                // 设置缩放级别
                aMap.moveCamera(CameraUpdateFactory.zoomTo(17));
                // 将地图移动到定位点
                aMap.moveCamera(CameraUpdateFactory.changeLatLng(new LatLng(aMapLocation.getLatitude(), aMapLocation.getLongitude())));
                // 点击定位按钮 能够将地图的中心移动到定位点
                mListener.onLocationChanged(aMapLocation);
            } else {
                // 定位失败时,可通过ErrCode(错误码)信息来确定失败的原因,errInfo是错误信息,详见错误码表。
                Log.e("HLQ_Struggle", "location Error, ErrCode:"
                        + aMapLocation.getErrorCode() + ", errInfo:"
                        + aMapLocation.getErrorInfo());
            }
        }
    }

    @Override
    public void activate(OnLocationChangedListener onLocationChangedListener) {
        mListener = onLocationChangedListener;
    }

    @Override
    public void deactivate() {
        mListener = null;
    }

第四步,初始化高德地图以及基本配置并开启定位

        aMap.getUiSettings().setZoomControlsEnabled(false);
        // 设置地图默认的指南针是否显示
        aMap.getUiSettings().setCompassEnabled(true);
        // 设置定位监听
        aMap.setLocationSource(this);
        // 设置默认定位按钮是否显示
        aMap.getUiSettings().setMyLocationButtonEnabled(true);
        // 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false
        aMap.setMyLocationEnabled(true);
        aMap.setMyLocationType(AMap.LOCATION_TYPE_LOCATE);

初始化高德地图,开启定位

    /**
     * 初始化高德地图
     */
    public void initGaoDeMap() {
        // 初始化定位
        mLocationClient = new AMapLocationClient(getApplicationContext());
        // 设置高德地图定位回调监听
        mLocationClient.setLocationListener(this);
        // 初始化AMapLocationClientOption对象
        mLocationOption = new AMapLocationClientOption();
        // 高精度定位模式:会同时使用网络定位和GPS定位,优先返回最高精度的定位结果,以及对应的地址描述信息
        // 设置定位模式为AMapLocationMode.Hight_Accuracy,高精度模式
        mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
        // 低功耗定位模式:不会使用GPS和其他传感器,只会使用网络定位(Wi-Fi和基站定位);
        //设置定位模式为AMapLocationMode.Battery_Saving,低功耗模式。
//        mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Battery_Saving);
        // 仅用设备定位模式:不需要连接网络,只使用GPS进行定位,这种模式下不支持室内环境的定位,自 v2.9.0 版本支持返回地址描述信息。
        // 设置定位模式为AMapLocationMode.Device_Sensors,仅设备模式。
//        mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Device_Sensors);
        // SDK默认采用连续定位模式,时间间隔2000ms
        // 设置定位间隔,单位毫秒,默认为2000ms,最低1000ms。
        mLocationOption.setInterval(3000);
        // 设置定位同时是否需要返回地址描述
        //设置是否返回地址信息(默认返回地址信息)
        mLocationOption.setNeedAddress(true);
        // 设置是否强制刷新WIFI,默认为强制刷新。每次定位主动刷新WIFI模块会提升WIFI定位精度,但相应的会多付出一些电量消耗。
        // 设置是否强制刷新WIFI,默认为true,强制刷新。
        mLocationOption.setWifiActiveScan(true);
        // 设置是否允许模拟软件Mock位置结果,多为模拟GPS定位结果,默认为false,不允许模拟位置。
        // 设置是否允许模拟位置,默认为false,不允许模拟位置
        mLocationOption.setMockEnable(false);
        // 设置定位请求超时时间,默认为30秒
        // 单位是毫秒,默认30000毫秒,建议超时时间不要低于8000毫秒。
        mLocationOption.setHttpTimeOut(50000);
        // 设置是否开启定位缓存机制
        // 缓存机制默认开启,可以通过以下接口进行关闭。
        // 当开启定位缓存功能,在高精度模式和低功耗模式下进行的网络定位结果均会生成本地缓存,不区分单次定位还是连续定位。GPS定位结果不会被缓存。
        // 关闭缓存机制
        mLocationOption.setLocationCacheEnable(false);
        // 设置是否只定位一次,默认为false
        mLocationOption.setOnceLocation(false);
        // 给定位客户端对象设置定位参数
        mLocationClient.setLocationOption(mLocationOption);
        // 启动高德地图定位
        mLocationClient.startLocation();
    }

撸了一会儿码,现在来瞅瞅效果吧~

这里写图片描述

咦,这个时候大家可能会问了,怎么移动别的地方之后还是会定位到当前呢?表急,让我们一起来看看这个问题究竟是什么导致的,当然LZ能力有限,只能简单推测,不正之处欢迎指正~

咦,怎么滑动地图总是会定位到原点呢?

怀着这个问题,让我们一起来回顾下之前的代码,大概如下:

  • 我们设置高德地图为连续的精度定位,且在回调的时候,我们会根据当前获取到的经度纬度去移动当某个点。这时候,大家会不会知道在哪儿动手脚可以简单,快速解决这个问题了呢?

解决办法如下:

                if(isFirstLocation){
                    // 设置缩放级别
                    aMap.moveCamera(CameraUpdateFactory.zoomTo(17));
                    // 将地图移动到定位点
                    aMap.moveCamera(CameraUpdateFactory.changeLatLng(new LatLng(aMapLocation.getLatitude(), aMapLocation.getLongitude())));
                    // 点击定位按钮 能够将地图的中心移动到定位点
                    mListener.onLocationChanged(aMapLocation);
                    isFirstLocation=false;
                }

此时,我们再次运行看看效果如何~

这里写图片描述

结束语

到现在,我们已经实现关于高德地图显示,定位,以及在实现定位过程中间出现的小插曲,相信大家看到这里已经掌握了关于高德地图的显示以及定位。

猜你喜欢

转载自blog.csdn.net/qq_32368129/article/details/72244337