高德定位模块使用说明
权限和KEY
在AndroidManifest.xml添加权限,如果仅使用定位功能,其他不需要的权限可去掉。
<!-- Normal Permissions 不需要运行时注册 -->
<!-- 获取运营商信息,用于支持提供运营商信息相关的接口 -->
<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.CHANGE_CONFIGURATION"/>
<!-- 请求网络 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- 不是SDK需要的权限,是示例中的后台唤醒定位需要的权限 -->
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<!-- 需要运行时注册的权限 -->
<!-- 用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- 用于访问GPS定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!-- 用于提高GPS定位速度 -->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
<!-- 写入扩展存储,向扩展卡写入数据,用于写入缓存定位数据 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 读取缓存数据 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- 用于读取手机当前的状态 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!-- 更改设置 -->
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<!--如果设置了target >= 28 如果需要启动后台定位则必须声明这个权限-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<!--如果您的应用需要后台定位权限,且有可能运行在Android Q设备上,并且设置了target>28,必须增加这个权限声明-->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
在AndroidManifest.xml的application中添加APSService和KEY
<!-- 设置key -->
<meta-data
android:name="com.amap.api.v2.apikey"
android:value="您申请的key"/>
<service
android:name="com.amap.api.location.APSService"
android:foregroundServiceType="location" />
添加依赖
在相关下载-Android 定位SDK|高德地图API (amap.com)下载对应的jar,直接导入到项目libs
在app的build.gradle添加依赖
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
}
代码
/**
* author : 吴明辉
* e-mail : 1412378121@qq.com
* date : 2022/3/2213:55
* git : https://gitee.com/yunianvh
* desc :
*/
import androidx.fragment.app.FragmentActivity
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.yangchoi.lib_base.utils.LogUtil.e
import java.io.File
import java.io.FileWriter
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*
class LocationManager(
context: FragmentActivity?,
private val offlineSavePath: String?,
locationCallBack: LocationCallBack?
) {
//声明AMapLocationClient类对象
private var mLocationClient: AMapLocationClient? = null
private var DATE_FORMAT = SimpleDateFormat("yyyyMMdd")
private var todayName: String? = null
var isSaveOfflineLocation: Boolean = false
companion object {
private val TAG = LocationManager::class.java.simpleName
}
//回调信息对象
class LocationBean {
var time: Long? = null
var latitude: Double? = null
var longitude: Double? = null
var address: String? = null
var locationDetail: String? = null
}
//回调
interface LocationCallBack {
fun onLocationInfo(locationBean: LocationBean?)
}
//声明定位回调监听器
private var mLocationListener = AMapLocationListener { aMapLocation ->
if (aMapLocation != null) {
e(TAG, "onLocationChanged errorCode: [ " + aMapLocation.errorCode + " ]")
if (aMapLocation.errorCode == 0) {
val gpsAccuracyStatus = aMapLocation.gpsAccuracyStatus //0差 1好 -1未知
val locationType =
aMapLocation.locationType //0失败 1gps 2前次定位 4:缓存 5:wifi 6:基站 8:离线 9:缓存
val accuracy = aMapLocation.accuracy //精度
val gpsSatellites = aMapLocation.satellites //搜星数
val trustedLevel = aMapLocation.trustedLevel //定位可信度 1好 2正常 3低 4差
val speed = aMapLocation.speed //速度
val locationDetail =
"卫星信号强度:$gpsAccuracyStatus 定位类型:$locationType 精度:$accuracy gps搜星数:$gpsSatellites 可信度:$trustedLevel 速度:$speed"
e(TAG, "onLocationChanged : $locationDetail")
//去掉离线缓存
if (locationType == AMapLocation.LOCATION_TYPE_FIX_CACHE || locationType == AMapLocation.LOCATION_TYPE_LAST_LOCATION_CACHE) {
return@AMapLocationListener
}
//通过回调接口返回回去
var bean = LocationBean()
bean.time = aMapLocation.time
bean.latitude = aMapLocation.latitude
bean.longitude = aMapLocation.longitude
bean.address = aMapLocation.address
bean.locationDetail = locationDetail
locationCallBack!!.onLocationInfo(bean)
//保存经纬度到本地文件(长链接没有连接时)
saveOfflineLocation(aMapLocation.latitude, aMapLocation.longitude)
} else {
//定位失败时,可通过ErrCode(错误码)信息来确定失败的原因,errInfo是错误信息,详见错误码表。
e(
TAG, "location Error, ErrCode:"
+ aMapLocation.errorCode
+ ", errInfo:"
+ aMapLocation.errorInfo
)
}
}
}
//isSaveOfflineLocation=true保存经纬度到本地,false不保存
fun isSaveOfflineLocation(isSaveOfflineLocation: Boolean) {
this.isSaveOfflineLocation = isSaveOfflineLocation
}
//本地保存经纬度
private fun saveOfflineLocation(lat: Double, lon: Double) {
if (offlineSavePath!!.isBlank() || !isSaveOfflineLocation) return
e(TAG, "saveOfflineLocation 保存经纬度: $lat,$lon")
val todayPath: String = offlineSavePath + todayName
val locFile = File(todayPath)
try {
if (!locFile.exists()) locFile.createNewFile()
val time = System.currentTimeMillis() / 1000
val strData = "$time,$lat,$lon;"
// 打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
val writer = FileWriter(todayPath, true)
writer.write(strData)
writer.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
fun startLocation() {
mLocationClient!!.startLocation()//启动定位
}
fun stopLocation() {
mLocationClient!!.stopLocation() //停止定位后,本地定位服务并不会被销毁
}
init {
//获取当天时间用于本地保存的文件名
val format = DATE_FORMAT.format(Date())
todayName = File.separator + "$format.txt"
if (mLocationClient != null) {
e(TAG, "mLocationClient != null")
} else {
//初始化定位
mLocationClient = AMapLocationClient(context)
//声明AMapLocationClientOption对象
val locationOption = AMapLocationClientOption()
locationOption.locationMode =
AMapLocationClientOption.AMapLocationMode.Hight_Accuracy
locationOption.interval = (10 * 1000).toLong()
locationOption.isSensorEnable = true
//给定位客户端对象设置定位参数
mLocationClient!!.setLocationOption(locationOption)
//设置定位回调监听
mLocationClient!!.setLocationListener(mLocationListener)
}
}
}
调用
在调用之前要确保权限已打开,推荐用PermissionX打开权限
var c = LocationManager(this, null, null)
c.startLocation()
c.isSaveOfflineLocation(false)
PermissionX申请权限
记得添加依赖:com.permissionx.guolindev:permissionx:1.3.0
PermissionX.init(this).permissions(
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS
).onExplainRequestReason { scope: ExplainScope, deniedList: List<String?>? ->
scope.showRequestReasonDialog(
deniedList,
"需要您同意以下授权才能正常使用定位功能",
"同意",
"拒绝"
)
}.request { allGranted: Boolean, grantedList: List<String?>?, deniedList: List<String?> ->
if (allGranted) {
Toast.makeText(this, "您同意了所有权限!", Toast.LENGTH_SHORT).show()
// 获取系统的LocationManager服务
var c = LocationManager(this, null)
c.startLocation()
} else {
Toast.makeText(this, "您拒绝了以下权限:$deniedList", Toast.LENGTH_SHORT).show()
}
}