使用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) } }) ) }