android 高德地图定位

2019-10-30 17:13:54 Amanda_alis 阅读数 626

Android高德地图定位功能,在部分机型定位成功却不返回地址信息处理方案。


最近做了一个关于定位相关的项目,使用的高德地图的API,结果却发生了一些问题,特此记录一下。
华为7.0,vivo8.0,小米8.0,vivo9.0,oppo9.0,红米6.0,全都没有问题。但是却在oppoR9机型出现了定位成功却不返回定位详细地址,网上找了好多方案都不行,最后没办法了想了一招,特此记录。

if (aMapLocation != null && aMapLocation.getErrorCode() == AMapLocation.LOCATION_SUCCESS )
//首先这个判断是没有任何问题的,返回的也是定位成功,并且返回了经纬度。

然后接着往下看

aMapLocation.getAdCode()	//发现数据为空
aMapLocation.getPoiName()	//发现数据为空
aMapLocation.getCityCode()	//发现数据为空

定位成功了却还是没有数据是怎么回事呢?
最后试了很多办法都不行,最后在Demo无意间看到这个地址编码的代码,只好拿出来使用,结果就好了,谁也不知道是怎么回事?有大佬知道的话可以留言告诉我一下。
下面是完整解决问题代码

private GeocodeSearch geocoderSearch =new GeocodeSearch(getmView().getmActivity());

//显示定位完成
if (aMapLocation != null && aMapLocation.getErrorCode() == AMapLocation.LOCATION_SUCCESS ) {
		//判断定位完成只给返回经纬度,却不返回定位详细地理信息时
 		if (EmptyUtils.isEmpty(aMapLocation.getAdCode())){
 			//根据经纬度去进行查询地理信息
 			 LatLonPoint point =new LatLonPoint(aMapLocation.getLatitude(),aMapLocation.getLongitude());
                                RegeocodeQuery query =new RegeocodeQuery(point, 200,GeocodeSearch.AMAP);
                                geocoderSearch.getFromLocationAsyn(query);
                                geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() {
                                    @Override
                                    public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int i) {
                                   		 //在这里解析得到的结果		
                                        String adCode = regeocodeResult.getRegeocodeAddress().getAdCode();
                                        String cityCode = egeocodeResult.getRegeocodeAddress().getCityCode();
                                        String formatAddress = regeocodeResult.getRegeocodeAddress().getFormatAddress();
                                       
                                    }
         }
}

此次踩坑,特此记录。
各位大佬有更好的解决方案的话,欢迎留言评论。

2019-09-18 17:04:42 Tobey_r1 阅读数 1227

关于

这篇主要讲如何使用高德sdk(不是下载的jar包是引用的),高德开发者平台我们注册成为个人开发者后,进入控制台选择新建应用,出现如下图所示,这里我们我们要注意的是一个包名,以及debug版本的SHA1和release版本的SHA1:
在这里插入图片描述

会获取SHA1的可自行跳过这一步

关于这两个的获取方法上面也有流程提示,这里我选择的是第二种方法(命令行方法)
(前提啊,你要把你自己的项目生成apk一个debug.apk一个你自己项目名release.apk这两个的生成方法我就不详细介绍了(可以在build中选择Generate Signed Bundle/APK)如下图:)
在这里插入图片描述
回到我们刚才说的,第一步打开命令行输入:

.android

如下图,会自动进入到我们androidstudio的.android目录
在这里插入图片描述
接着输入keytool -list -v -keystore debug.keystore,然后输入密钥库密码(debug的apk的默认密码是android)输入android得到结果如下:
在这里插入图片描述
在这里插入图片描述
途中箭头所指的就是调试版本的SHA1啦。我们把它复制到我们先前需要的地方。
接来下同理我们输入keytool -list -v -keystore 你的jks或是keystore后缀名的release签名文件地址 xxx.jks
在这里插入图片描述
好啦这样提交我们的数据上去,就可以获得key了。
在这里插入图片描述

第二步引用高德sdk

配置步骤可以参考开发文档
第一步,在项目的build.gradle中添加如下:

//高德定位及3D地图
    implementation'com.amap.api:3dmap:latest.integration'
    implementation'com.amap.api:location:latest.integration'

第二步,在androidmanifest.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>
    <!--用于申请调用A-GPS模块-->
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"></uses-permission>
    <!--用于申请获取蓝牙信息进行室内定位-->
    <uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"></uses-permission>

在androidmanifest.xml文件的application内添加如下:

 <!--在application标签中声明service组件,每个app拥有自己单独的定位service-->
        <service android:name="com.amap.api.location.APSService"></service>
        <meta-data android:name="com.amap.api.v2.apikey" android:value="xxxxxxxxxxxxkey"/>
        //开发者申请的key

第三步修改MainActivity.java

package com.example.weathertest;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.google.gson.Gson;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    public AMapLocationClient mLocationClient=null;
    //声明定位回调监听器
    public AMapLocationClientOption mLocationOption=null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);    
        initMap();
    }

    private void initMap() {
        //初始化定位
                mLocationClient=new AMapLocationClient(MainActivity.this);
                //设置定位回调监听
mLocationClient.setLocationListener(mLocationListener);
mLocationOption = new AMapLocationClientOption();
//设置定位模式为高精度模式,AMapLocationMode.Battery_Saving为低功耗模式,AMapLocationMode.Device_Sensors是仅设备模式
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
mLocationOption.setNeedAddress(true);//设置是否返回地址信息(默认返回地址信息)
mLocationOption.setOnceLocation(false);//设置是否只定位一次,默认为false
mLocationOption.setWifiActiveScan(true);//设置是否强制刷新WIFI,默认为强制刷新
mLocationOption.setMockEnable(false);//设置是否允许模拟位置,默认为false,不允许模拟位置
mLocationOption.setInterval(15000);//设置定位间隔,单位毫秒,默认为2000ms
mLocationOption.setOnceLocation(false);//可选,是否设置单次定位默认为false即持续定位
mLocationOption.setOnceLocationLatest(false); //可选,设置是否等待wifi刷新,默认为false.如果设置为true,会自动变为单次定位,持续定位时不要使用
mLocationOption.setWifiScan(true); //可选,设置是否开启wifi扫描。默认为true,如果设置为false会同时停止主动刷新,停止以后完全依赖于系统刷新,定位位置可能存在误差
mLocationOption.setLocationCacheEnable(true); //可选,设置是否使用缓存定位,默认为true
//给定位客户端对象设置定位参数
mLocationClient.setLocationOption(mLocationOption);
//启动定位
mLocationClient.startLocation();
    }
    public AMapLocationListener mLocationListener=new AMapLocationListener() {
        @Override
        public void onLocationChanged(AMapLocation aMapLocation) {
            if (aMapLocation != null) {
                if (aMapLocation.getErrorCode() == 0) {
                   //定位成功回调信息,设置相关消息
                    aMapLocation.getLocationType();//获取当前定位结果来源,如网络定位结果,详见定位类型表
                   // aMapLocation.getLatitude();//获取纬度
                   // aMapLocation.getLongitude();//获取经度
                    aMapLocation.getAccuracy();//获取精度信息
                    java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

                  //  aMapLocation.getAddress();//地址,如果option中设置isNeedAddress为false,则没有此结果,网络定位结果中会有地址信息,GPS定位不返回地址信息。
                  //  aMapLocation.getCountry();//国家信息
                  //  aMapLocation.getProvince();//省信息
                  //  aMapLocation.getCity();//城市信息
                 //   aMapLocation.getDistrict();//城区信息
                //    aMapLocation.getStreet();//街道信息
               //     aMapLocation.getStreetNum();//街道门牌号信息
                //    aMapLocation.getCityCode();//城市编码
               //     aMapLocation.getAdCode();//地区编码  
                   System.out.println("所在城市:"+aMapLocation.getCountry()+aMapLocation.getProvince()+aMapLocation.getCity());
                    mLocationClient.stopLocation();//停止定位
                } else {
                    //显示错误信息ErrCode是错误码,errInfo是错误信息,详见错误码表。
                    Log.e("info", "location Error, ErrCode:"
                            + aMapLocation.getErrorCode() + ", errInfo:"
                            + aMapLocation.getErrorInfo());
                }
            }
        }
    };
      
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //销毁
        if (mLocationClient !=null){
            mLocationClient.onDestroy();
        }
    }
}

运行结果如下:
在这里插入图片描述
这篇只是简单的实现定位功能,后面将会组合使用放到本人的简易新闻app上,如果有问题欢迎指正!
关于定位获取实况天气的组合使用,本人已经在Android使用高德和风天气Sdk获取定位实况天气数据(二)实现,有兴趣的可以参考参考。

2019-01-30 15:59:20 w2821ymx 阅读数 2580

第一步、在高德开放平台先注册自己的用户
第二步、获取key高德地图获取key流程
特别注意在获取发布版本安全码时确定自己已经创建了一个****.jks文件,在控制台才能获取安全码。
创建自己的jks文件

第三步、修改Androidmanifest.xml文件
参考高德地图开发指南

第四步、在mainActivity.java中添加定位代码
参考高德地图定位
定位结果
记得开启后台自己app位置获取权限
附录:完整关键代码如下
1、Androidmanifest.xml

<?xml version="1.0" encoding="utf-8"?>













<!--用于进行网络定位-->
<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>
<!--用于申请调用A-GPS模块-->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"></uses-permission>
<!--用于申请获取蓝牙信息进行室内定位-->
<uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <meta-data
        android:name="com.amap.api.v2.apikey"
        android:value="183929d31ad6fd06e9b2951b20dc3cd6"/>

    <service
        android:name="com.amap.api.location.APSService">
    </service>
    
</application>

2、mainActivity.java文件
package com.fafu.administrator.fufamap;
import android.location.Location;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.LocationSource;
import com.amap.api.maps.MapView;
import com.amap.api.maps.model.MyLocationStyle;

public class MainActivity extends AppCompatActivity implements LocationSource, AMapLocationListener {

MapView mMapView = null;

//初始化地图控制器对象
AMap aMap;

//定位需要的数据
LocationSource.OnLocationChangedListener mListener;
AMapLocationClient mlocationClient;
AMapLocationClientOption mLocationOption;

//定位蓝点
MyLocationStyle myLocationStyle;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //获取地图控件引用
    mMapView = (MapView) findViewById(R.id.map);
    //在activity执行onCreate时执行mMapView.onCreate(savedInstanceState),创建地图
    mMapView.onCreate(savedInstanceState);
    if (aMap == null) {
        aMap = mMapView.getMap();

    }
    //设置地图的放缩级别
    aMap.moveCamera(CameraUpdateFactory.zoomTo(12));
    // 设置定位监听
    aMap.setLocationSource(this);
    // 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false
    aMap.setMyLocationEnabled(true);
    // 设置定位的类型为定位模式,有定位、跟随或地图根据面向方向旋转几种
    aMap.setMyLocationType(AMap.LOCATION_TYPE_LOCATE);


    //蓝点初始化
    myLocationStyle = new MyLocationStyle();//初始化定位蓝点样式类myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//连续定位、且将视角移动到地图中心点,定位点依照设备方向旋转,并且会跟随设备移动。(1秒1次定位)如果不设置myLocationType,默认也会执行此种模式。
    myLocationStyle.interval(2000); //设置连续定位模式下的定位间隔,只在连续定位模式下生效,单次定位模式下不会生效。单位为毫秒。
    aMap.setMyLocationStyle(myLocationStyle);//设置定位蓝点的Style
    //aMap.getUiSettings().setMyLocationButtonEnabled(true);设置默认定位按钮是否显示,非必需设置。
    aMap.setMyLocationEnabled(true);// 设置为true表示启动显示定位蓝点,false表示隐藏定位蓝点并不进行定位,默认是false。
    myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//连续定位、且将视角移动到地图中心点,定位点依照设备方向旋转,并且会跟随设备移动。(1秒1次定位)默认执行此种模式。


    myLocationStyle.showMyLocation(true);

    aMap.setOnMyLocationChangeListener(new AMap.OnMyLocationChangeListener() {
        @Override
        public void onMyLocationChange(Location location) {
            //从location对象中获取经纬度信息,地址描述信息,建议拿到位置之后调用逆地理编码接口获取
        }
    });
}


@Override
protected void onResume() {
    super.onResume();
    //在activity执行onResume时执行mMapView.onResume (),重新绘制加载地图
    mMapView.onResume();
}

@Override
protected void onPause() {
    super.onPause();
    //在activity执行onPause时执行mMapView.onPause (),暂停地图的绘制
    mMapView.onPause();
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    //在activity执行onSaveInstanceState时执行mMapView.onSaveInstanceState (outState),保存地图当前的状态
    mMapView.onSaveInstanceState(outState);
}


//--定位监听---------

/**
 * 激活定位
 */
@Override
public void activate(OnLocationChangedListener onLocationChangedListener) {
    mListener = onLocationChangedListener;
    if (mlocationClient == null) {
        //初始化定位
        mlocationClient = new AMapLocationClient(this);
        //初始化定位参数
        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() {
    mListener = null;
    if (mlocationClient != null) {
        mlocationClient.stopLocation();
        mlocationClient.onDestroy();
    }
    mlocationClient = null;
}


//定位回调  在回调方法中调用“mListener.onLocationChanged(amapLocation);”可以在地图上显示系统小蓝点。
@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);
        }
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    //在activity执行onDestroy时执行mMapView.onDestroy(),销毁地图
    mMapView.onDestroy();
    if (null != mlocationClient) {
        mlocationClient.onDestroy();
    }
}

}
详细请参考高德定位开发指南

2017-12-05 15:44:03 laizixingxingdewo 阅读数 724

                                                                                              android高德地图定位

今天刚学的高德地图定位,本篇博客在上一篇高德地图基础上加的定位,分享给大家!

直接上代码:

  1. //终于找到报错“10: 定位服务启动失败”的问题 
    //这个MapActivity放置的位置有关系,当Activity放在TabSpec中就有问题 
    //如果单独作为一个activity则没有问题 
  2. 代码:
    public class SecondActivity extends AppCompatActivity implements LocationSource,
            AMapLocationListener { 
    
  3.     private MapView mapView;
        private AMap map;
    
        //定位功能
        private OnLocationChangedListener mListener;
        private AMapLocationClient mlocationClient;
        private AMapLocationClientOption mLocationOption;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_second);
            mapView = (MapView) findViewById(R.id.map);//找到地图控件
    //在activity执行onCreate时执行mMapView.onCreate(savedInstanceState),创建地图
            mapView.onCreate(savedInstanceState);
           // AMap aMap = mapView.getMap();//初始化地图控制器对象\
            map = mapView.getMap();
    
    
            //修改地图的中心点位置
            CameraPosition cp = map.getCameraPosition();
            CameraPosition cpNew = CameraPosition.fromLatLngZoom(new LatLng(31.22, 121.48), cp.zoom);
            CameraUpdate cu = CameraUpdateFactory.newCameraPosition(cpNew);
            map.moveCamera(cu);
    
            //初始化定位服务
            initLocationService();
    
    
    
        }
        //初始化定位服务,这个地方有错误,这个地方map已经初始化
        //因此定位的初始化代码就进不去了。
        private void initLocationService() {
            if (map != null) {
                MyLocationStyle locationStyle = new MyLocationStyle();
                locationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.drawable.a_a));
                locationStyle.strokeColor(Color.BLACK);
                locationStyle.radiusFillColor(Color.argb(100, 0, 0, 180));
                locationStyle.strokeWidth(1.0f);
                map.setMyLocationStyle(locationStyle);
                map.setLocationSource(this);
                map.getUiSettings().setMyLocationButtonEnabled(true);
                map.setMyLocationEnabled(true);
            }
        }
    
        /**
         * 方法必须重写
         */
        @Override
        protected void onResume() {
            super.onResume();
            mapView.onResume();
        }
    
        /**
         * 方法必须重写
         */
        @Override
        protected void onPause() {
            super.onPause();
            mapView.onPause();
        }
    
    
        /**
         * 方法必须重写
         */
        @Override
        protected void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            mapView.onSaveInstanceState(outState);
        }
    
        /**
         * 方法必须重写
         */
        @Override
        protected void onDestroy() {
            super.onDestroy();
            mapView.onDestroy();
        }
    
        @Override
        public void onLocationChanged(AMapLocation amaplocation) {
            // TODO Auto-generated method stub
            if (amaplocation != null && mListener != null) {
                if (amaplocation != null && amaplocation.getErrorCode() == 0) {
                    mListener.onLocationChanged(amaplocation);
                }
                else {
                    String errText = "failed to locate," + amaplocation.getErrorCode()+ ": "
                            + amaplocation.getErrorInfo();
                    Log.e("error",errText);
                }
    
            }
        }
    
        @Override
        public void activate(OnLocationChangedListener listener) {
            // TODO Auto-generated method stub
            mListener = listener;
            if (mlocationClient == null) {
                mlocationClient = new AMapLocationClient(getApplicationContext());
                mLocationOption = new AMapLocationClientOption();
                mlocationClient.setLocationListener(this);
                mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
                mlocationClient.setLocationOption(mLocationOption);
                mlocationClient.startLocation();
            }
        }
    
        @Override
        public void deactivate() {
            // TODO Auto-generated method stub
            mListener = null;
            if (mlocationClient != null) {
                mlocationClient.stopLocation();
                mlocationClient.onDestroy();
            }
            mlocationClient = null;
            mLocationOption = null;
        }
    }
    
    





2017-05-16 11:48:02 qq_32368129 阅读数 1631

前言

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

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

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

  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;
                }

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

这里写图片描述

结束语

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