当前位置: 首页 > news >正文

河南省建设行业证书查询网站吉林网站建设代理渠道

河南省建设行业证书查询网站,吉林网站建设代理渠道,网站需求分析怎么写,wordpress 閱讀 主题Android中获取定位信息的方式有很多种,系统自带的LocationManager,以及第三方厂商提供的一些定位sdk,都能帮助我们获取当前经纬度,但第三方厂商一般都需要申请相关的key,且调用量高时,还会产生资费问题。这…

Android中获取定位信息的方式有很多种,系统自带的LocationManager,以及第三方厂商提供的一些定位sdk,都能帮助我们获取当前经纬度,但第三方厂商一般都需要申请相关的key,且调用量高时,还会产生资费问题。这里采用LocationManager + FusedLocationProviderClient 的方式进行经纬度的获取,以解决普通场景下获取经纬度和经纬度转换地址的功能。

一,添加定位权限

<!--允许获取精确位置,精准定位必选-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!--后台获取位置信息,若需后台定位则必选-->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<!--用于申请调用A-GPS模块,卫星定位加速-->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />

二,添加依赖库

    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2'implementation 'com.google.android.gms:play-services-location:21.0.1'

三,使用LocationManager获取当前经纬度

获取经纬度时,可根据自己的诉求进行参数自定义,如果对经纬度要求不是很精确的可以自行配置Criteria里面的参数。

获取定位前需要先判断相关的服务是否可用,获取定位的服务其实有很多种选择,因为个人项目对经纬度准确性要求较高,为了保证获取的成功率和准确性,只使用了GPS和网络定位两种,如果在国内还会有基站获取等方式,可以自行修改。

import android.Manifest.permission
import android.location.*
import android.os.Bundle
import android.util.Log
import androidx.annotation.RequiresPermission
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeout
import kotlin.coroutines.resumeobject LocationManagerUtils {val TAG = "LocationManagerUtils"/*** @mLocationManager 传入LocationManager对象* @minDistance  位置变化最小距离:当位置距离变化超过此值时,将更新位置信息(单位:米)* @timeOut 超时时间,如果超时未返回,则直接使用默认值*/@RequiresPermission(anyOf = [permission.ACCESS_COARSE_LOCATION, permission.ACCESS_FINE_LOCATION])suspend  fun getCurrentPosition(mLocationManager: LocationManager,timeOut: Long = 3000,):Location{var locationListener : LocationListener?=nullreturn  try {//超时未返回则直接获取失败,返回默认值withTimeout(timeOut){suspendCancellableCoroutine {continuation ->//获取最佳定位方式,如果获取不到则默认采用网络定位。var bestProvider = mLocationManager.getBestProvider(createCriteria(),true)if (bestProvider.isNullOrEmpty()||bestProvider == "passive"){bestProvider = "network"}Log.d(TAG, "getCurrentPosition:bestProvider:${bestProvider}")locationListener = object : LocationListener {override fun onLocationChanged(location: Location) {Log.d(TAG, "getCurrentPosition:onCompete:${location.latitude},${location.longitude}")if (continuation.isActive){continuation.resume(location)mLocationManager.removeUpdates(this)}}override fun onProviderDisabled(provider: String) {}override fun onProviderEnabled(provider: String) {}}//开始定位mLocationManager.requestLocationUpdates(bestProvider,1000,0f,locationListener!!)}}}catch (e:Exception){try {locationListener?.let {mLocationManager.removeUpdates(it)}}catch (e:Exception){Log.d(TAG, "getCurrentPosition:removeUpdate:${e.message}")}//超时直接返回默认的空对象Log.d(TAG, "getCurrentPosition:onError:${e.message}")return createDefaultLocation()}}@RequiresPermission(anyOf = [permission.ACCESS_COARSE_LOCATION, permission.ACCESS_FINE_LOCATION])suspend fun repeatLocation(mLocationManager: LocationManager):Location{return  suspendCancellableCoroutine {continuation ->//获取最佳定位方式,如果获取不到则默认采用网络定位。var bestProvider = mLocationManager.getBestProvider(createCriteria(),true)if (bestProvider.isNullOrEmpty()||bestProvider == "passive"){bestProvider = "network"}Log.d(TAG, "getCurrentPosition:bestProvider:${bestProvider}")val locationListener = object : LocationListener {override fun onLocationChanged(location: Location) {Log.d(TAG, "getCurrentPosition:onCompete:${location.latitude},${location.longitude}")if (continuation.isActive){continuation.resume(location)}mLocationManager.removeUpdates(this)}override fun onProviderDisabled(provider: String) {}override fun onProviderEnabled(provider: String) {}}//开始定位mLocationManager.requestLocationUpdates(bestProvider,1000, 0f, locationListener)}}@RequiresPermission(anyOf = [permission.ACCESS_COARSE_LOCATION, permission.ACCESS_FINE_LOCATION])fun getLastLocation( mLocationManager: LocationManager): Location {//获取最佳定位方式,如果获取不到则默认采用网络定位。var currentProvider = mLocationManager.getBestProvider(createCriteria(), true)if (currentProvider.isNullOrEmpty()||currentProvider == "passive"){currentProvider = "network"}return mLocationManager.getLastKnownLocation(currentProvider) ?: createDefaultLocation()}//创建定位默认值fun createDefaultLocation():Location{val location = Location("network")location.longitude = 0.0location.latitude = 0.0return location}private fun createCriteria():Criteria{return  Criteria().apply {accuracy = Criteria.ACCURACY_FINEisAltitudeRequired = falseisBearingRequired = falseisCostAllowed = truepowerRequirement = Criteria.POWER_HIGHisSpeedRequired = false}}///定位是否可用fun checkLocationManagerAvailable(mLocationManager: LocationManager):Boolean{return mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)||mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)}
}

二,使用FusedLocationProviderClient

在获取经纬度时会出现各种异常的场景,会导致成功的回调一直无法触发,这里使用了协程,如果超过指定超时时间未返回,则直接默认为获取失败,进行下一步的处理。

import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.Context.LOCATION_SERVICE
import android.content.Intent
import android.location.Geocoder
import android.location.Location
import android.location.LocationManager
import android.provider.Settings
import android.util.Log
import androidx.annotation.RequiresPermission
import com.google.android.gms.location.LocationServices
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
import java.io.IOException
import java.util.*
import kotlin.coroutines.resumeobject FusedLocationProviderUtils {val TAG = "FusedLocationUtils"@RequiresPermission(anyOf = ["android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"])suspend  fun checkFusedLocationProviderAvailable(fusedLocationClient: FusedLocationProviderClient):Boolean{return  try {withTimeout(1000){suspendCancellableCoroutine { continuation ->fusedLocationClient.locationAvailability.addOnFailureListener {Log.d(TAG, "locationAvailability:addOnFailureListener:${it.message}")if (continuation.isActive){continuation.resume(false)}}.addOnSuccessListener {Log.d(TAG, "locationAvailability:addOnSuccessListener:${it.isLocationAvailable}")if (continuation.isActive){continuation.resume(it.isLocationAvailable)}}}}}catch (e:Exception){return false}}///获取最后已知的定位信息@RequiresPermission(anyOf = ["android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"])suspend fun getLastLocation(fusedLocationClient: FusedLocationProviderClient):Location{return  suspendCancellableCoroutine {continuation ->fusedLocationClient.lastLocation.addOnSuccessListener {if (continuation.isActive){Log.d(TAG, "current location success:$it")if (it != null){continuation.resume(it)}else{continuation.resume(createDefaultLocation())}}}.addOnFailureListener {continuation.resume(createDefaultLocation())}}}/*** 获取当前定位,需要申请定位权限**/@RequiresPermission(anyOf = ["android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"])suspend fun getCurrentPosition(fusedLocationClient: FusedLocationProviderClient): Location {return suspendCancellableCoroutine {continuation ->fusedLocationClient.getCurrentLocation(createLocationRequest(),object : CancellationToken(){override fun onCanceledRequested(p0: OnTokenCanceledListener): CancellationToken {return CancellationTokenSource().token}override fun isCancellationRequested(): Boolean {return false}}).addOnSuccessListener {if (continuation.isActive){Log.d(TAG, "current location success:$it")if (it != null){continuation.resume(it)}else{continuation.resume(createDefaultLocation())}}}.addOnFailureListener {Log.d(TAG, "current location fail:$it")if (continuation.isActive){continuation.resume(createDefaultLocation())}}.addOnCanceledListener {Log.d(TAG, "current location cancel:")if (continuation.isActive){continuation.resume(createDefaultLocation())}}}}//创建当前LocationRequest对象private fun createLocationRequest():CurrentLocationRequest{return CurrentLocationRequest.Builder().setDurationMillis(1000).setMaxUpdateAgeMillis(5000).setPriority(Priority.PRIORITY_HIGH_ACCURACY).build()}//创建默认值private fun createDefaultLocation():Location{val location = Location("network")location.longitude = 0.0location.latitude = 0.0return location}
}

三,整合LocationManager和FusedLocationProviderClient

在获取定位时,可能会出现GPS定位未开启的情况,所以不管是LocationManager或FusedLocationProviderClient都需要判断当前服务是否可用,获取定位时,如果GPS信号较弱等异常情况下,就需要考虑到获取定位超时的情况,这里使用了协程,如FusedLocationProviderClient超过3秒未获取成功,则直接切换到LocationManager进行二次获取,这是提升获取经纬度成功的关键。

在实际项目中,如果对获取经纬度有较高的考核要求时,通过结合LocationManager和FusedLocationProviderClient如果还是获取不到,可考虑集成第三方的进行进一步获取,可以考虑使用华为的免费融合定位服务,因为我们使用过百度地图的sdk,每天会出现千万分之五左右的定位错误和定位漂移问题。

import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.Context.LOCATION_SERVICE
import android.content.Intent
import android.location.Geocoder
import android.location.Location
import android.location.LocationManager
import android.provider.Settings
import android.util.Log
import androidx.annotation.RequiresPermission
import com.google.android.gms.location.LocationServices
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
import java.io.IOException
import java.util.*
import kotlin.coroutines.resumeobject LocationHelper {fun getLocationServiceStatus(context: Context):Boolean{return (context.getSystemService(LOCATION_SERVICE) as LocationManager).isProviderEnabled(LocationManager.GPS_PROVIDER)}/*** 打开定位服务设置*/fun openLocationSetting(context: Context):Boolean{return try {val settingsIntent = Intent()settingsIntent.action = Settings.ACTION_LOCATION_SOURCE_SETTINGSsettingsIntent.addCategory(Intent.CATEGORY_DEFAULT)settingsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)settingsIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)settingsIntent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)context.startActivity(settingsIntent)true} catch (ex: java.lang.Exception) {false}}/*** 获取当前定位*/@RequiresPermission(anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION])suspend fun getLocation(context: Activity,timeOut: Long = 2000):Location{val location = getLocationByFusedLocationProviderClient(context)//默认使用FusedLocationProviderClient 如果FusedLocationProviderClient不可用或获取失败,则使用LocationManager进行二次获取Log.d("LocationHelper", "getLocation:$location")return  if (location.latitude == 0.0){getLocationByLocationManager(context, timeOut)}else{location}}@RequiresPermission(anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION])private suspend fun getLocationByLocationManager(context: Activity,timeOut: Long = 2000):Location{Log.d("LocationHelper", "getLocationByLocationManager")val locationManager =  context.getSystemService(LOCATION_SERVICE) as LocationManager//检查LocationManager是否可用return  if (LocationManagerUtils.checkLocationManagerAvailable(locationManager)){//使用LocationManager获取当前经纬度val location = LocationManagerUtils.getCurrentPosition(locationManager, timeOut)if (location.latitude == 0.0){LocationManagerUtils.getLastLocation(locationManager)}else{location}}else{//获取失败,则采用默认经纬度LocationManagerUtils.createDefaultLocation()}}@RequiresPermission(anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION])private suspend fun getLocationByFusedLocationProviderClient(context: Activity):Location{Log.d("LocationHelper", "getLocationByFusedLocationProviderClient")//使用FusedLocationProviderClient进行定位val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)return if (FusedLocationProviderUtils.checkFusedLocationProviderAvailable(fusedLocationClient)){withContext(Dispatchers.IO){//使用FusedLocationProviderClient获取当前经纬度val location = FusedLocationProviderUtils.getCurrentPosition(fusedLocationClient)if (location.latitude == 0.0){FusedLocationProviderUtils.getLastLocation(fusedLocationClient)}else{location}}}else{LocationManagerUtils.createDefaultLocation()}}
}
注:因为获取定位是比较耗电的操作,在实际使用时,可增加缓存机制,比如2分钟之内频繁,则返回上一次缓存的数据,如果超过2分钟则重新获取一次,并缓存起来。

四,获取当前经纬度信息或经纬度转换地址

1,获取当前经纬度
 @RequiresPermission(anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION])fun getCurrentLocation(activity:Activity){if (activity != null){val exceptionHandler = CoroutineExceptionHandler { _, exception ->}viewModelScope.launch(exceptionHandler) {val location = LocationHelper.getLocation(activity!!)val map = HashMap<String,String>()map["latitude"] ="${location.latitude}"map["longitude"] = "${location.longitude}"}}}
2,经纬度转换地址
 /*** @param latitude 经度* @param longitude 纬度* @return 详细位置信息*/suspend fun convertAddress(context: Context, latitude: Double, longitude: Double): String {return try {withTimeout(3000){suspendCancellableCoroutine {  continuation ->try {val mGeocoder = Geocoder(context, Locale.getDefault())val mStringBuilder = StringBuilder()if (Geocoder.isPresent()){val mAddresses = mGeocoder.getFromLocation(latitude, longitude, 1)if (mAddresses!= null &&mAddresses.size >0) {val address = mAddresses[0]Log.d("LocationUtils", "convertAddress()--->$address")mStringBuilder.append(address.getAddressLine(0)?:"").append(",").append(address.adminArea?:address.subAdminArea?:"").append(",").append(address.locality?:address.subLocality?:"").append(",").append(address.thoroughfare?:address.subThoroughfare?:"")}}if (continuation.isActive){continuation.resume(mStringBuilder.toString())}} catch (e: IOException) {Log.d("LocationUtils", "convertAddress()--IOException->${e.message}")if (continuation.isActive){continuation.resume("")}}}}}catch (e:Exception){Log.d("LocationUtils", "convertAddress()--->timeout")return ""}}

调用时:

fun covertAddress(latitude:double,longitude:double){if (activity != null){val exceptionHandler = CoroutineExceptionHandler { _, exception ->}viewModelScope.launch(exceptionHandler) {val hashMap = argument as HashMap<*, *>withContext(Dispatchers.IO){val address = LocationHelper.convertAddress(activity!!,"${hashMap["latitude"]}".toDouble(),"${hashMap["longitude"]}".toDouble())}}}}

注:经纬度转换地址时,需要开启一个线程或者协程进行转换,不然会阻塞主线程,引发异常。

http://www.yayakq.cn/news/157163/

相关文章:

  • 汕头网站制作网站做教育网站的er图
  • 医疗网站不备案设计企业网站布局考虑的因素
  • 做一网站需要多少钱东莞网站空间
  • 天津红桥网站建设如何创建自己的网址
  • 郑州做网站的专业公司有哪些昨晚广州天河发生事件
  • 栖霞企业网站建设丰台专业网站建设公司
  • 大连企业免费建站网站怎么做切换图片
  • 成都市建设厅官方网站做招聘网站需要什么资质
  • 中小微企业查询网站品牌vi设计公司啊
  • 推荐个做淘宝主图视频的网站专门做旅游攻略的网站有哪些
  • 免费快速网站北京seo公司
  • 外贸网站域名服务商设计师网名叫什么好听
  • 免费企业网站管理系统网站地图 格式
  • 汽车网站名称湛江专业雷剧全集
  • wordpress成品站源码有没有专做游戏脚本的网站
  • 青岛新网站设计公司ppt做视频的模板下载网站有哪些
  • 为什么 要建设网站英迈思网站建设
  • 网站定制要求淘宝客怎么做网站推广
  • 汕头响应式网站教程厦门网站建设xm37
  • 淘宝客网站开发定制主流网站类型
  • 有哪些专门做写字楼的网站做国际生意的网站有哪些
  • 网站建设费用都选网络自己做网站的好处
  • 信息类网站制作中国建设银行网站地址
  • 网站建设需要哪些工作html网页制作代码作业
  • 如何做简易网站wordpress 中文社区
  • 罗源网站建设泉州网站制作哪个好薇
  • 网页设计与制作专业优化官方网站设计
  • 贵州萝岗seo整站优化新手如何做外贸生意
  • 网站换模板对seo外贸网站的特色
  • 网站建设制作优帮云仿做网站