背景
安卓开发经常需要获取地理位置,所以对获取地理位置做了下整理,方便大家使用。
解决方案:- Manifest文件添加权限:
- 添加依赖
implementation "com.google.code.gson:gson:2.8.5"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1"
implementation "org.jetbrains.kotlinx:kotlinx
implementation 'com.afollestad:assent:2.3.1'
- 主要代码: LocationUtils.kt
object LocationUtils {
private val TAG = LocationUtils::class.java.simpleName
/**
* 获取地理位置,先根据GPS获取,再根据网络获取
*
* @return
*/
@SuppressLint("MissingPermission")
fun getLocation(context: Context, callback: Callback) {
val locationListener: LocationListener = getLocationListener(callback)
try {
val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { //从gps获取经纬度
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0f, locationListener)
} else {//从网络获取经纬度
getLocationByNetwork(context, callback)
}
} catch (e: Exception) {
Log.e(TAG, e.message)
}
}
private fun getLocationListener(callback: Callback): LocationListener {
return object : LocationListener {
// Provider的状态在可用、暂时不可用和无服务三个状态直接切换时触发此函数
override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
Log.d(TAG, "onStatusChanged")
}
// Provider被enable时触发此函数,比如GPS被打开
override fun onProviderEnabled(provider: String) {
Log.d(TAG, "onProviderEnabled")
}
// Provider被disable时触发此函数,比如GPS被关闭
override fun onProviderDisabled(provider: String) {
Log.d(TAG, "onProviderDisabled")
}
//当坐标改变时触发此函数,如果Provider传进相同的坐标,它就不会被触发
override fun onLocationChanged(location: Location) {
callback.onLocationChanged(location)
}
}
}
/**
* 判断是否开启了GPS或网络定位开关
*
* @return
*/
fun isLocationProviderEnabled(context: Context): Boolean {
var result = false
val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
|| locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
result = true
}
return result
}
/**
* 获取地理位置,先根据GPS获取,再根据网络获取
*
* @return
*/
@SuppressLint("MissingPermission")
private fun getLocationByNetwork(context: Context, callback: Callback) {
val locationListener: LocationListener = getLocationListener(callback)
val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
try {
if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0f, locationListener)
}
} catch (e: Exception) {
Log.e(TAG, e.message)
}
}
}
interface Callback {
fun onLocationChanged(location: Location)
}
调用样例(Kotlin):
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
locateBtn.setOnClickListener { locate() }
}
private fun locate() {
locationTv.text = ""
runWithPermissions(Permission.ACCESS_FINE_LOCATION) {
if (LocationUtils.isLocationProviderEnabled(this@MainActivity)) {
progressBar.visibility = VISIBLE
showLocationWithToast()
} else {
showAlert("本应用需要获取地理位置,请打开获取位置的开关", this)
}
}
}
private fun showLocationWithToast() {
LocationUtils.getLocation(this@MainActivity, object : Callback {
override fun onLocationChanged(location: Location) {
onGetLocation(location)
}
})
}
private fun onGetLocation(location: Location) {
GlobalScope.launch(Dispatchers.IO) {
val result = getAddressInfo(location)
launch(Dispatchers.Main) {
result?.let {
locationTv.text = it.toString()
progressBar.visibility = GONE
}
}
}
}
}
备注
- 上面代码中使用了第三方库assent来动态申请权限
- 采用了coroutines来执行异步任务
- 采用了百度web api来根据地理位置查询地址信息(ak需要自己申请) 效果图:
https://gitee.com/hspbc/geolocationDemo/tree/master/demo
关于我厦门大学计算机专业 | 前华为工程师 Java | 安卓 | 前端 | 小程序 | 鸿蒙 公众号:蓝不蓝编程