前提
每次做的项目中或者维护公司之前旧项目的时候,都会用到通过定位来获取经纬度,我们都知道,Android官方也提供了获取经纬度的方法,但是不太好使,所以就用了高德地图的API,不能每次用的时候都要写一堆代码,效率挺低的,于是就想着,封装成一个工具类,方便调用,为以后的项目,不管是管理方面还是查找方面都简洁了不少。
第一步、去官网创建高德Key
带*号的填完后,点击提交,获取SHA1值如下(通过代码获取的)或者通过命令行获取,两者都行。 Android studio代码获取SHA1值
调用 Log.e("-->打印sha1 ","${sha1(this)}")
fun sha1(context: Context): String {
try {
val info: PackageInfo = context.packageManager.getPackageInfo(
context.packageName, PackageManager.GET_SIGNATURES)
val cert: ByteArray = info.signatures.get(0).toByteArray()
val md: MessageDigest = MessageDigest.getInstance("SHA1")
val publicKey: ByteArray = md.digest(cert)
val hexString = StringBuffer()
for (i in publicKey.indices) {
val appendString = Integer.toHexString(0xFF and publicKey[i].toInt())
.toUpperCase(Locale.US)
if (appendString.length == 1) hexString.append("0")
hexString.append(appendString)
hexString.append(":")
}
val result = hexString.toString()
return result.substring(0, result.length - 1)
} catch (e: PackageManager.NameNotFoundException) {
e.printStackTrace()
} catch (e: NoSuchAlgorithmException) {
e.printStackTrace()
}
return ""
}
复制代码
第二步 通过Gradle集成SDK(方便):
1、在Project的build.gradle文件中配置repositories,添加maven或jcenter仓库地址:
allprojects { repositories { jcenter() // 或者 mavenCentral() } }
复制代码
2、在主工程的build.gradle文件配置dependencies
//定位
implementation 'com.amap.api:location:latest.integration'
复制代码
第三步 配置参数
第1步,配置AndroidManifest.xml
请在application标签中声明service组件,每个app拥有自己单独的定位service。
<!-- 定位需要的服务 使用2.0的定位需要加上这个 -->
<service android:name="com.amap.api.location.APSService" >
</service>
复制代码
第2步,声明权限 如果项目中已有其中的权限,那就不用加了
<!--用于进行网络定位-->
<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>
复制代码
第3步,设置高德Key:
<meta-data android:name="com.amap.api.v2.apikey" android:value="key">//开发者申请的key </meta-data>
复制代码
第四步 获取定位数据
在需要获取经纬度的页面调用如下代码:
private var amapLocationUtil: AmapLocationUtil? = null
fun initLocationOption() {
if (null == amapLocationUtil) {
amapLocationUtil = AmapLocationUtil(CommApplication.getApplication())
}
amapLocationUtil!!.initLocation()
amapLocationUtil!!.startLocation()
amapLocationUtil!!.setOnCallBackListener { longitude, latitude, location, isSucdess, address ->
//Log.e("--->", "longitude" + longitude + "\n" + "latitude" + latitude + "\n" + "isSucdess" + isSucdess + "\n" + "address" + address);
//Log.e("--->",location.getProvince()+ "\n" +location.getCity()+"\n"+location.getDistrict());
//isSucdess true 定位成功 false 失败
if (isSucdess) {
} else {
//定位失败,重试定位
amapLocationUtil!!.startLocation()
}
}
}
复制代码
注意:如果是在当前Activity实例化的,不要忘了销毁
override fun onDestroy() {
super.onDestroy()
if (amapLocationUtil != null) {
amapLocationUtil!!.destroyLocation()
}
}
复制代码
看到了代码里调用了AmapLocationUtil,这个是我封装好的一个工具类,方便调用,代码如下:
/**
*
* Created by JasonYin
* Description:封装高德地图Util
*
*/
class AmapLocationUtil(private val mContext: Context) {
private var locationClient: AMapLocationClient? = null
private var locationOption: AMapLocationClientOption? = null
private var mOnCallBackListener: onCallBackListener? = null
/**
* 初始化定位
*/
fun initLocation() { //初始化client
if (null == locationClient) {
locationClient = AMapLocationClient(mContext)
}
locationOption = defaultOption
//设置定位参数
locationClient!!.setLocationOption(locationOption)
// 设置定位监听
locationClient!!.setLocationListener(locationListener)
}//可选,设置定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式
//可选,设置是否gps优先,只在高精度模式下有效。默认关闭
//可选,设置网络请求超时时间。默认为30秒。在仅设备模式下无效
//可选,设置定位间隔。默认为2秒
//可选,设置是否返回逆地理地址信息。默认是true
//可选,设置是否单次定位。默认是false
//可选,设置是否等待wifi刷新,默认为false.如果设置为true,会自动变为单次定位,持续定位时不要使用
//可选, 设置网络请求的协议。可选HTTP或者HTTPS。默认为HTTP
//可选,设置是否使用传感器。默认是false
//可选,设置是否开启wifi扫描。默认为true,如果设置为false会同时停止主动刷新,停止以后完全依赖于系统刷新,定位位置可能存在误差
//可选,设置是否使用缓存定位,默认为true
//可选,设置定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式
//可选,设置是否gps优先,只在高精度模式下有效。默认关闭
//如果网络可用就选择高精度
private val defaultOption: AMapLocationClientOption
private get() {
val mOption = AMapLocationClientOption()
//如果网络可用就选择高精度
if (NetworkUtils.isConnected()) { //可选,设置定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式
mOption.locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy
mOption.isGpsFirst = true //可选,设置是否gps优先,只在高精度模式下有效。默认关闭
} else {
mOption.locationMode = AMapLocationClientOption.AMapLocationMode.Device_Sensors //可选,设置定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式
mOption.isGpsFirst = true //可选,设置是否gps优先,只在高精度模式下有效。默认关闭
}
mOption.httpTimeOut = 30000 //可选,设置网络请求超时时间。默认为30秒。在仅设备模式下无效
mOption.interval = 2000 //可选,设置定位间隔。默认为2秒
mOption.isNeedAddress = true //可选,设置是否返回逆地理地址信息。默认是true
mOption.isOnceLocation = false //可选,设置是否单次定位。默认是false
mOption.isOnceLocationLatest = false //可选,设置是否等待wifi刷新,默认为false.如果设置为true,会自动变为单次定位,持续定位时不要使用
AMapLocationClientOption.setLocationProtocol(AMapLocationClientOption.AMapLocationProtocol.HTTP) //可选, 设置网络请求的协议。可选HTTP或者HTTPS。默认为HTTP
mOption.isSensorEnable = true //可选,设置是否使用传感器。默认是false
mOption.isWifiScan = true //可选,设置是否开启wifi扫描。默认为true,如果设置为false会同时停止主动刷新,停止以后完全依赖于系统刷新,定位位置可能存在误差
mOption.isLocationCacheEnable = true //可选,设置是否使用缓存定位,默认为true
return mOption
}
var locationListener = AMapLocationListener { location ->
val sb = StringBuilder()
if (null != location) { //errCode等于0代表定位成功,其他的为定位失败,具体的可以参照官网定位错误码说明
if (location.errorCode == 0) {
longitude = location.longitude
latitude = location.latitude
val district = location.district
locationSuccess(longitude, latitude, true, location, district)
//定位成功,停止定位:如果实时定位,就把stopLocation()关闭
stopLocation()
} else { //定位失败
// sb.append("定位失败" + "\n");
// sb.append("错误码:" + location.getErrorCode() + "\n");
// sb.append("错误信息:" + location.getErrorInfo() + "\n");
// sb.append("错误描述:" + location.getLocationDetail() + "\n");
// Log.e("---> 定位失败", sb.toString());
LocationFarile(false, location)
}
} else {
LocationFarile(false, location)
}
}
private fun LocationFarile(isSucdess: Boolean, location: AMapLocation) {
if (mOnCallBackListener != null) {
mOnCallBackListener!!.onCallBack(0.0, 0.0, location, false, "")
}
}
fun locationSuccess(longitude: Double, latitude: Double, isSucdess: Boolean, location: AMapLocation?, address: String?) {
if (mOnCallBackListener != null) {
mOnCallBackListener!!.onCallBack(longitude, latitude, location, true, address)
}
}
fun setOnCallBackListener(listener: onCallBackListener?) {
mOnCallBackListener = listener
}
interface onCallBackListener {
fun onCallBack(longitude: Double, latitude: Double, location: AMapLocation?, isSucdess: Boolean, address: String?)
}
/**
* 开始定位
*/
fun startLocation() {
locationClient!!.startLocation()
}
/**
* 停止定位
*/
fun stopLocation() {
locationClient!!.stopLocation()
}
/**
* 销毁定位
*/
fun destroyLocation() {
if (null != locationClient) {
/**
* 如果AMapLocationClient是在当前Activity实例化的,
* 在Activity的onDestroy中一定要执行AMapLocationClient的onDestroy
*/
locationClient!!.onDestroy()
locationClient = null
locationOption = null
}
}
companion object {
var longitude = 0.0
var latitude = 0.0
}
}
本文在开源项目:https://github.com/Android-Alvin/Android-LearningNotes 中已收录,里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中...