使用google地图定位
使用Google地图,需要手机支持google服务 (国产手机很多都不支持),如果不支持可以手动安装:
如果还是不能定位,可以安装下google地图App,然后定个位 ,不出意外这样就可以了
集成:
implementation 'com.google.android.gms:play-services-maps:17.0.0'//谷歌地图 implementation 'com.google.android.gms:play-services-places:17.0.0' //基础包 implementation 'com.google.android.gms:play-services-location:17.0.0'//谷歌定位
<!-- application标签里添加 基于Google Maps的API的API密钥定义为字符串资源。 (请参见文件“ res / values / google_maps_api.xml”)。 请注意,API密钥链接到用于对APK签名的加密密钥。 每个加密密钥都需要一个不同的API密钥,包括用于 在APK上签名以发布。 您可以在src / debug /和src / release /中定义调试和发布目标的键。 --> <meta-data android:name="com.google.android.geo.API_KEY" android:value="@string/google_maps_key" />
<resources> <!-- 为此,您可以将发布密钥凭据添加到现有的 密钥,或创建一个新密钥。 请注意,此文件为发布构建目标指定API密钥。 如果您之前已使用调试签名证书为调试目标设置了密钥, 您还需要为发布证书设置密钥。 请按照以下说明进行操作: https://developers.google.com/maps/documentation/android/signup 拥有密钥(以“ AIza”开头)后,请替换“ google_maps_key” 该文件中的字符串。 --> <string name="google_maps_key" templateMergeStrategy="preserve" translatable="false"> AIzaSyC_-_ze8LEqnFhf12bat6J2BQ5M0fDGpNE </string> </resources>
使用:
import android.annotation.SuppressLint import android.app.Activity import android.content.Context import android.location.Location import android.os.Looper import com.google.android.gms.common.api.ApiException import com.google.android.gms.common.api.ResolvableApiException import com.google.android.gms.location.* /**
每2秒 定一次位 */ class LocationUtil { private val mLocationRequest: LocationRequest private var mFusedLocationClient: FusedLocationProviderClient? = null private var mLocationCallback = object : LocationCallback() { override fun onLocationResult(p0: LocationResult?) { super.onLocationResult(p0) LogUtil.e("定位结果:po = ${p0}") } } constructor(){ mLocationRequest = LocationRequest() mLocationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY //高精度定位 mLocationRequest.interval = 2000 //2秒 定位一次 定位间隔 mLocationRequest.fastestInterval = 2000 //最快的定位间隔 } /** * 开始定位 */ fun requestLocationUpdate(context: Context) { if(mFusedLocationClient == null){ if (context is Activity) { mFusedLocationClient = LocationServices.getFusedLocationProviderClient(context) } else { mFusedLocationClient = LocationServices.getFusedLocationProviderClient(context) } } // 使用位置请求创建LocationSettingsRequest对象 val builder = LocationSettingsRequest.Builder() builder.addLocationRequest(mLocationRequest) val locationSettingsRequest = builder.build() val settingsClient: SettingsClient // 检查是否满足位置设置 // https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient if (context is Activity) { settingsClient = LocationServices.getSettingsClient(context) } else { settingsClient = LocationServices.getSettingsClient(context) } settingsClient .checkLocationSettings(locationSettingsRequest) .addOnSuccessListener { LogUtil.e("可以定位-----------------------------") //权限检测 没有权限 定位失败 谷歌定位不回调 //if(有权限){ startLocationUpdates() //}else{ // //} } .addOnCompleteListener{ LogUtil.e("条件检测完成-----------------------------${it.isSuccessful}") } .addOnFailureListener { e -> LogUtil.e("不可定位---------------------------- ${e.message}") if(e is ApiException){ when (e.statusCode) { LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> { LogUtil.e("不满足定位要求,请求设置") if (context is Activity) { try { // 通过调用startResolutionForResult()显示对话框,然后检查 产生onActivityResult()。 val rae = e as ResolvableApiException rae.startResolutionForResult(context, 789) } catch (sie: Exception) { LogUtil.e("PendingIntent无法执行请求。") } } } LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> { LogUtil.e("无法更改设置") } } } } } @SuppressLint("MissingPermission") private fun startLocationUpdates() { mFusedLocationClient?.requestLocationUpdates( mLocationRequest, mLocationCallback, Looper.myLooper() ) } fun stopLocation() { mFusedLocationClient?.removeLocationUpdates(mLocationCallback) } } interface MyLocationCallback{ fun locationFailure() fun locationSuccess(location: Location) }
手动检测手机是否支持google服务:
/** * 是否支持Google Play服务 */ fun isHaveGooglePlay(activity: Activity, requestCode: Int): Boolean { val googleApiAvailability = GoogleApiAvailability.getInstance(); val resultCode = googleApiAvailability.isGooglePlayServicesAvailable(activity); if(resultCode != ConnectionResult.SUCCESS) { /** * 通过isUserResolvableError来确定是否可以通过用户操作解决错误 */ if (GoogleApiAvailability.getInstance().isUserResolvableError(resultCode)) { /** * 返回一个对话框,用于解决提供的errorCode。 * @param activity 用于创建对话框的父活动 * @param code 通过调用返回的错误代码 * @param activity 调用startActivityForResult时给出的requestCode */ GoogleApiAvailability.getInstance().getErrorDialog(activity, resultCode, requestCode).show(); } return false } return true }
定位成功后,通过经纬度获取更加详细的地址信息:
/** * https://maps.googleapis.com/maps/api/geocode/json?latlng=37.422,-122.084&language=zh-CN&sensor=false */ @GET fun getGoogleLocationInfo(@Url url: String): Observable<JsonObject>
fun locationToStr(location: Location) { val url = Uri.parse("https://maps.googleapis.com/maps/api/geocode/json").buildUpon().let { it.appendQueryParameter("latlng","${location.latitude},${location.longitude}") it.appendQueryParameter("language","zh-CN")// language=en-US 返回是英文,language=cn-ZH 返回是中文,默认是返回中文 it.appendQueryParameter("key","AIzaSyC_-_ze8LEqnFhf12bat6J2BQ5M0fDGpNE") it.appendQueryParameter("sensor","false") .toString() } addDdisposable( ApiRetrofitClient.service.getGoogleLocationInfo(url) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .map { //var address = it.get("results").asJsonArray.get(0).asJsonObject.get("formatted_address").asString //最后一组,只有国家信息 var components = it.get("results").asJsonArray.get(it.get("results").asJsonArray.size() - 1).asJsonObject.get("address_components").asJsonArray val countryCode = components[0].asJsonObject.get("short_name").asString //LogUtil.e("国家编码 = $countryCode 地址 = $address") if(countryCode == null){ throw Exception() }else{ return@map countryCode } } .subscribeWith(object : HttpObserver<String>(loginView){ override fun onNext(t: String) { super.onNext(t) } }) ) }