高德地图的集成和实现
高德地图目前的定位类型有 3 种:
LOCATION_TYPE_LOCATE :只在第一次定位移动到地图中心点;
LOCATION_TYPE_MAP_FOLLOW :定位,移动到地图中心点并跟随;
LOCATION_TYPE_MAP_ROTATE :定位,移动到地图中心点,跟踪并根据面向方向旋转地图。
注意它在自己的模拟器上不能定位,要在手机上才能使用定位和旋转,不要忘记开手机上的GPS定位哦
1.如果没有注册过,就先去高德开放平台先去注册,首先在 http://id.amap.com/ 站点注册用户名,密码(如果没有):
然后创建应用,再生成获取ApiKey
获取Key
如何申请 Key
1、创建新应用
进入控制台,创建一个新应用。如果您之前已经创建过应用,可直接跳过这个步骤。
应用名称可以自己定义
获取key
获取key的链接可参考:http://lbs.amap.com/api/android-sdk/guide/create-project/get-key#key。
2、添加新Key
在创建的应用上点击"添加新Key"按钮,在弹出的对话框中,依次输入应用名名称,选择绑定的服务为“Android平台SDK”,输入发布版安全码 SHA1、调试版安全码 SHA1、以及 Package,如下图所示:
需要注意的是: 1个KEY只能用于一个应用(多渠道安装包属于多个应用),1个Key在多个应用上使用会出现服务调用失败。
在阅读完高德地图API服务条款后,勾选此选项,点击“提交”,完成 Key 的申请,此时您可以在所创建的应用下面看到刚申请的 Key 了。
如何获取 SHA1
调试版本(debug)和发布版本(release)下的 SHA1 值是不同的,发布 apk 时需要根据发布 apk 对应的 keystore 重新配置 Key。
- 获取调试版本 SHA1 需要根据不同的开发工具,分别参考 通过Eclipse获取SHA1 和 通过Android Studio获取SHA1。
- 获取发布版本下 SHA1 的方法请参考 使用 keytool(jdk自带工具)获取SHA1。
通过 eclipse 获取 SHA1
使用 adt 22 以上版本,可以在 eclipse 中直接查看。
Windows:依次在 eclipse 中打开 Window -> Preferances -> Android -> Build。
Mac:依次在 eclipse 中打开 Eclipse/ADT->Preferances -> Android -> Build。
在弹出的 Build 对话框中 “SHA1 fingerprint” 中的值即为 Android 签名证书的 SHA1 值,如下图所示:
通过Android Studio获取SHA1
第一步、打开 Android Studio 的 Terminal 工具。
第二步、输入命令:keytool -v -list -keystore keystore文件路径。
第三步、输入 Keystore 密码
使用 keytool(jdk自带工具)获取 SHA1
1、运行进入控制台。
2、在弹出的控制台窗口中输入 cd .android 定位到 .android 文件夹。
3.继续在控制台输入命令。
调试版本使用 debug.keystore,命令为:keytool -list -v -keystore debug.keystore。 发布版本使用 apk 对应的 keystore,命令为:keytool -list -v -keystore apk 的 keystore。
如下所示:
提示输入密钥库密码,开发模式默认密码是 android,发布模式的密码是为 apk 的 keystore 设置的密码。输入密钥后回车(如果没设置密码,可直接回车),
此时可在控制台显示的信息中获取 Sha1 值,如下图所示:
说明:keystore 文件为 Android 签名证书文件。
如何获取 PackageName
打开 Android 项目的 AndroidManifest.xml 配置文件,package 属性所对应的内容为应用包名,如下图所示:
也请检查 build.gradle 文件的 applicationid 属性是否与上文提到的 package 属性一致,如果不一致会导致 INVALID_USER_SCODE,请调整一致。
先在清单文件里加入一些网络权限和Apikey
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com..gaodeditu">
<!--允许程序打开网络套接字-->
<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" />
<!--用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<!--用于访问GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<!--用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
<!--用于读取手机当前的状态-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<!--用于申请调用A-GPS模块-->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
<!--获取运营商信息,用于支持提供运营商信息相关的接口-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--用于访问wifi网络信息,wifi信息会用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!--用于访问网络,网络定位需要上网-->
<uses-permission android:name="android.permission.INTERNET" />
<!--用于读取手机当前的状态-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!--写入扩展存储,向扩展卡写入数据,用于写入缓存定位数据-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<meta-data
android:name="com.amap.api.v2.apikey"
android:value="6b273938762bde148d424b5d4bf014fd">//换成您的key
</meta-data>
<service android:name="com.amap.api.location.APSService"></service>
<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>
</application>
</manifest>
然后在项目的build.gradle里添加依赖
defaultConfig {
........
ndk {
//设置支持的SO库架构(开发者可以根据需要,选择一个或多个平台的so)
abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86","arm64-v8a","x86_64"
}
}
dependencies {
........
compile 'com.amap.api:3dmap:5.0.0'
compile 'com.amap.api:location:3.3.0'
compile 'com.amap.api:search:5.0.0'
}
然后就开始写activity—main的布局
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.amap.api.maps.MapView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</com.amap.api.maps.MapView>
<TextView
android:id="@+id/location_errInfo_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|left"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:background="@android:color/holo_red_light"
android:textColor="@android:color/darker_gray"
android:text="TextView"
android:visibility="gone"/>
<RadioGroup
android:id="@+id/gps_radio_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|left"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:background="@android:color/holo_orange_light"
android:orientation="horizontal" >
<RadioButton
android:id="@+id/gps_locate_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="定位"
android:textColor="@android:color/black" />
<RadioButton
android:id="@+id/gps_follow_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="追踪"
android:textColor="@android:color/black" />
<RadioButton
android:id="@+id/gps_rotate_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="旋转"
android:textColor="@android:color/black" />
</RadioGroup>
</FrameLayout>
MainActivity
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
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.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.UiSettings;
import com.amap.api.maps.model.LatLng;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity implements LocationSource, AMapLocationListener,OnCheckedChangeListener{
private MapView mapView;
//AMap是地图对象
private AMap aMap;
//声明AMapLocationClient类对象,定位发起端
private AMapLocationClient mLocationClient = null;
//声明mLocationOption对象,定位参数
public AMapLocationClientOption mLocationOption = null;
//声明mListener对象,定位监听器
private LocationSource.OnLocationChangedListener mListener = null;
//标识,用于判断是否只显示一次定位信息和用户重新定位
private boolean isFirstLoc = true;
private Bundle savedInstanceState;
private RadioGroup mGPSModeGroup;
private TextView mLocationErrText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);// 不显示程序的标题栏
setContentView(R.layout.activity_main);
//隐藏标题栏
ActionBar actionBar=getSupportActionBar();
actionBar.hide();
//初始化控件
initView();
}
/**
* 获取控件
*/
private void initView() {
mapView= (MapView) findViewById(R.id.map);
//在activity执行onCreate时执行mMapView.onCreate(savedInstanceState),实现地图生命周期管理
mapView.onCreate(savedInstanceState);
if (aMap == null) {
aMap = mapView.getMap();
//设置显示定位按钮 并且可以点击
UiSettings settings = aMap.getUiSettings();
aMap.setLocationSource(this);//设置了定位的监听
// 是否显示定位按钮
settings.setMyLocationButtonEnabled(true);
aMap.setMyLocationEnabled(true);//显示定位层并且可以触发定位,默认是flase
}
//找控件
mGPSModeGroup = (RadioGroup) findViewById(R.id.gps_radio_group);
mGPSModeGroup.setOnCheckedChangeListener(this);
mLocationErrText = (TextView)findViewById(R.id.location_errInfo_text);
mLocationErrText.setVisibility(View.GONE);
//开始定位
location();
}
private void location() {
//初始化定位
mLocationClient = new AMapLocationClient(getApplicationContext());
//设置定位回调监听
mLocationClient.setLocationListener(this);
//初始化定位参数
mLocationOption = new AMapLocationClientOption();
//设置定位模式为Hight_Accuracy高精度模式,Battery_Saving为低功耗模式,Device_Sensors是仅设备模式
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
//设置是否返回地址信息(默认返回地址信息)
mLocationOption.setNeedAddress(true);
//设置是否只定位一次,默认为false
mLocationOption.setOnceLocation(false);
//设置是否强制刷新WIFI,默认为强制刷新
mLocationOption.setWifiActiveScan(true);
//设置是否允许模拟位置,默认为false,不允许模拟位置 true方法开启允许位置模拟
mLocationOption.setMockEnable(true);
//设置定位间隔,单位毫秒,默认为2000ms
mLocationOption.setInterval(2000);
//给定位客户端对象设置定位参数
mLocationClient.setLocationOption(mLocationOption);
//启动定位
mLocationClient.startLocation();
}
@Override
public void activate(OnLocationChangedListener onLocationChangedListener) {
mListener = onLocationChangedListener;
}
@Override
public void deactivate() {
mListener = null;
}
/**
* 定位成功后回调函数
*/
@Override
public void onLocationChanged(AMapLocation aMapLocation) {
if (aMapLocation != null) {
if (aMapLocation.getErrorCode() == 0) {
//定位成功回调信息,设置相关消息
aMapLocation.getLocationType();//获取当前定位结果来源,如网络定位结果,详见官方定位类型表
aMapLocation.getLatitude();//获取纬度
aMapLocation.getLongitude();//获取经度
aMapLocation.getAccuracy();//获取精度信息
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date(aMapLocation.getTime());
df.format(date);//定位时间
aMapLocation.getAddress();
//地址,如果option中设置isNeedAddress为false,则没有此结果,网络定位结果中会有地址信息,GPS定位不返回地址信息。
aMapLocation.getCountry();//国家信息
aMapLocation.getProvince();//省信息
aMapLocation.getCity();//城市信息
aMapLocation.getDistrict();//城区信息
aMapLocation.getStreet();//街道信息
aMapLocation.getStreetNum();//街道门牌号信息
aMapLocation.getCityCode();//城市编码
aMapLocation.getAdCode();//地区编码
// 如果不设置标志位,此时再拖动地图时,它会不断将地图移动到当前的位置
if (isFirstLoc) {
//设置缩放级别
aMap.moveCamera(CameraUpdateFactory.zoomTo(17));
//将地图移动到定位点
aMap.moveCamera(CameraUpdateFactory.changeLatLng(new LatLng(aMapLocation.getLatitude(), aMapLocation.getLongitude())));
//点击定位按钮 能够将地图的中心移动到定位点
mListener.onLocationChanged(aMapLocation);
//添加图钉
// aMap.addMarker(getMarkerOptions(amapLocation));
//获取定位信息
StringBuffer buffer = new StringBuffer();
buffer.append(aMapLocation.getCountry() + ""
+ aMapLocation.getProvince() + ""
+ aMapLocation.getCity() + ""
+ aMapLocation.getProvince() + ""
+ aMapLocation.getDistrict() + ""
+ aMapLocation.getStreet() + ""
+ aMapLocation.getStreetNum());
Toast.makeText(getApplicationContext(), buffer.toString(), Toast.LENGTH_LONG).show();
isFirstLoc = false;
}
} else {
//显示错误信息ErrCode是错误码,errInfo是错误信息,详见错误码表。
Log.e("AmapError", "location Error, ErrCode:"
+ aMapLocation.getErrorCode() + ", errInfo:"
+ aMapLocation.getErrorInfo());
Toast.makeText(getApplicationContext(), "定位失败", Toast.LENGTH_LONG).show();
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理
mapView.onDestroy();
mLocationClient.stopLocation();//停止定位
mLocationClient.onDestroy();//销毁定位客户端。
}
@Override
protected void onResume() {
super.onResume();
//在activity执行onResume时执行mMapView.onResume (),实现地图生命周期管理
mapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
//在activity执行onPause时执行mMapView.onPause (),实现地图生命周期管理
mapView.onPause();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//在activity执行onSaveInstanceState时执行mMapView.onSaveInstanceState (outState),实现地图生命周期管理
mapView.onSaveInstanceState(outState);
}
//监听事件,实现3D旋转
@Override
public void onCheckedChanged(RadioGroup radioGroup, @IdRes int i) {
switch (i) {
case R.id.gps_locate_button:
// 设置定位的类型为定位模式
aMap.setMyLocationType(AMap.LOCATION_TYPE_LOCATE);
break;
case R.id.gps_follow_button:
// 设置定位的类型为 跟随模式
aMap.setMyLocationType(AMap.LOCATION_TYPE_MAP_FOLLOW);
break;
case R.id.gps_rotate_button:
// 设置定位的类型为根据地图面向方向旋转
aMap.setMyLocationType(AMap.LOCATION_TYPE_MAP_ROTATE);
break;
}
}
}