18034727885
2026-07-24 6180e2986ca3c39262486458cee97e54d5f67450
app/src/main/java/com/igo/user/utils/google/AMapKit.kt
@@ -1,9 +1,8 @@
package com.igo.user.utils.google
import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Color
import android.location.LocationManager
@@ -49,6 +48,7 @@
import com.igo.user.IGoApplication
import com.igo.user.R
import com.igo.user.utils.Const
import com.tbruyelle.rxpermissions2.RxPermissions
import okhttp3.MediaType
import okhttp3.OkHttpClient
import okhttp3.Request
@@ -61,59 +61,69 @@
object AMapKit {
    val TAG = "GoogleMap"
    @SuppressLint("MissingPermission")
    fun initLocation(context: Context, success: (Place) -> Unit, error: (String) -> Unit) {
        val placesClient = Places.createClient(context)
        val placeFields: List<Place.Field> = listOf(Place.Field.LAT_LNG,Place.Field.NAME,Place.Field.ADDRESS)
// Use the builder to create a FindCurrentPlaceRequest.
        val request: FindCurrentPlaceRequest = FindCurrentPlaceRequest.newInstance(placeFields)
// Call findCurrentPlace and handle the response (first check that the user has granted permission).
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) ==
            PackageManager.PERMISSION_GRANTED) {
            val placeResponse = placesClient.findCurrentPlace(request)
            placeResponse.addOnCompleteListener { task ->
                if (task.isSuccessful) {
                    val response = task.result
                    for (placeLikelihood: PlaceLikelihood in response?.placeLikelihoods ?: emptyList()) {
                        Log.i(TAG, "Place '${placeLikelihood.place.name}' has likelihood: ${placeLikelihood.likelihood}")
    fun initLocation(activity: Activity, success: (Place) -> Unit, error: (String) -> Unit) {
        RxPermissions(activity).request(
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION
        ).subscribe {
            if (it) {
                val placesClient = Places.createClient(activity)
                val placeFields: List<Place.Field> =
                    listOf(Place.Field.LAT_LNG, Place.Field.NAME, Place.Field.ADDRESS)
                // Use the builder to create a FindCurrentPlaceRequest.
                val request: FindCurrentPlaceRequest =
                    FindCurrentPlaceRequest.newInstance(placeFields)
                val placeResponse = placesClient.findCurrentPlace(request)
                placeResponse.addOnCompleteListener { task ->
                    if (activity.isFinishing || activity.isDestroyed) {
                        return@addOnCompleteListener
                    }
                    if (response?.placeLikelihoods?.isEmpty() != true){
                        success(response.placeLikelihoods[0].place)
                    if (task.isSuccessful) {
                        val response = task.result
                        for (placeLikelihood: PlaceLikelihood in response?.placeLikelihoods
                            ?: emptyList()) {
                            Log.i(
                                TAG,
                                "Place '${placeLikelihood.place.name}' has likelihood: ${placeLikelihood.likelihood}"
                            )
                        }
                        if (response?.placeLikelihoods?.isNotEmpty() == true) {
                            success(response.placeLikelihoods[0].place)
                        }
                    } else {
                        val exception = task.exception
                        if (exception is ApiException) {
                            Log.e(TAG, "Place not found: ${exception.message}")
                        }
                        error(exception?.message ?: "定位失败")
                    }
                } else {
                    val exception = task.exception
                    if (exception is ApiException) {
                        Log.e(TAG, "Place not found: ${exception.message}")
                    }
                    error(exception?.message?:"定位失败")
                }
            } else {
                Toast.makeText(
                    activity,
                    activity.getString(R.string.没有权限),
                    Toast.LENGTH_SHORT
                ).show()
                error("没有权限")
            }
        } else {
            // A local method to request required permissions;
            // See https://developer.android.com/training/permissions/requesting
            Toast.makeText(context, context.getString(R.string.没有权限), Toast.LENGTH_SHORT).show()
//            getLocationPermission()
            error("没有权限")
        }
    }
    fun initMap(mapView: SupportMapFragment,function: (GoogleMap) -> Unit) {
         mapView.getMapAsync { p0 ->
             val mMyLocationStyle = GoogleMapOptions()
             //                mMyLocationStyle.interval(5000)
             //                mMyLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER)
             //                mMyLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.mipmap.gps_point))
             //                p0.setLocationSource() = mMyLocationStyle
             //                p0.isMyLocationEnabled = false
             //                p0.animateCamera(CameraUpdateFactory.zoomTo(aMap.maxZoomLevel - 3))
             // 设置定位的类型为定位模式,有定位、跟随或地图根据面向方向旋转几种
             //                p0.setMyLocationType(GoogleMap.LOCATION_TYPE_LOCATE)
             //                val uiSettings: UiSettings = aMap.uiSettings
             //                uiSettings.isZoomControlsEnabled = false
             function(p0)
         }
    fun initMap(mapView: SupportMapFragment, function: (GoogleMap) -> Unit) {
        mapView.getMapAsync { p0 ->
            val mMyLocationStyle = GoogleMapOptions()
            //                mMyLocationStyle.interval(5000)
            //                mMyLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER)
            //                mMyLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.mipmap.gps_point))
            //                p0.setLocationSource() = mMyLocationStyle
            //                p0.isMyLocationEnabled = false
            //                p0.animateCamera(CameraUpdateFactory.zoomTo(aMap.maxZoomLevel - 3))
            // 设置定位的类型为定位模式,有定位、跟随或地图根据面向方向旋转几种
            //                p0.setMyLocationType(GoogleMap.LOCATION_TYPE_LOCATE)
            //                val uiSettings: UiSettings = aMap.uiSettings
            //                uiSettings.isZoomControlsEnabled = false
            function(p0)
        }
    }
@@ -150,13 +160,19 @@
            .color(ContextCompat.getColor(context, R.color.quantum_googgreen500))
        return aMap.addPolyline(options)
    }
     fun drawLine(context: Context, aMap: ConsumerGoogleMap, latLngs: List<LatLng?>?): Polyline? {
    fun drawLine(context: Context, aMap: ConsumerGoogleMap, latLngs: List<LatLng?>?): Polyline? {
        val options = PolylineOptions().addAll(latLngs!!).width(20f)
            .color(ContextCompat.getColor(context, R.color.quantum_googgreen500))
        return aMap.addPolyline(options)
    }
    fun drawLine(context: Context, aMap: GoogleMap, latLngs: List<LatLng?>?,color:Int): Polyline? {
    fun drawLine(
        context: Context,
        aMap: GoogleMap,
        latLngs: List<LatLng?>?,
        color: Int
    ): Polyline? {
        val options = PolylineOptions().addAll(latLngs!!).width(20f)
            .color(ContextCompat.getColor(context, color))
        return aMap.addPolyline(options)
@@ -169,7 +185,7 @@
        aMap.animateCamera(mCameraUpdate)
    }
    fun moveCamera(aMap: GoogleMap, latlng: LatLng?,zoom:Float) {
    fun moveCamera(aMap: GoogleMap, latlng: LatLng?, zoom: Float) {
        val mCameraUpdate = CameraUpdateFactory.newCameraPosition(
            CameraPosition(latlng!!, zoom, 0f, 0f)
        )
@@ -250,7 +266,7 @@
        peopleId: String
    ): Marker? {
        val options: MarkerOptions = getOption(LatLng(mLat, mLng), view)
        val marker: Marker =  aMap.addMarker(options)!!
        val marker: Marker = aMap.addMarker(options)!!
        if (!TextUtils.isEmpty(peopleId)) {
            marker.tag = peopleId
        }
@@ -262,9 +278,12 @@
            return IGoApplication.appContext!!.getString(R.string.zero_tance)
        }
        return if (tance > 1000) {
            String.format("%.1f"+IGoApplication.appContext!!.getString(R.string.公里), (tance / 1000f))
            String.format(
                "%.1f" + IGoApplication.appContext!!.getString(R.string.公里),
                (tance / 1000f)
            )
        } else {
            String.format("%.1f"+IGoApplication.appContext!!.getString(R.string.米), tance)
            String.format("%.1f" + IGoApplication.appContext!!.getString(R.string.米), tance)
        }
    }
@@ -279,18 +298,17 @@
    fun drawFace(context: Context, aMap: GoogleMap, latLngs: List<LatLng?>?): Polygon? {
        var po = PolygonOptions().addAll(latLngs!!)
            .fillColor(ContextCompat.getColor(context, R.color.l_transparent_10)).strokeColor(
            Color.RED
        ).strokeWidth(1f)
                Color.RED
            ).strokeWidth(1f)
        return aMap.addPolygon(po)
    }
    fun drawCricle(context: Context, aMap: GoogleMap, latLng: LatLng,bg:Double): Circle? {
        return  aMap.addCircle(CircleOptions().
            center(latLng).
            radius(bg).
            fillColor(ContextCompat.getColor(context, R.color.l_transparent_10)).
            strokeColor( Color.RED).
            strokeWidth(1f));
    fun drawCricle(context: Context, aMap: GoogleMap, latLng: LatLng, bg: Double): Circle? {
        return aMap.addCircle(
            CircleOptions().center(latLng).radius(bg)
                .fillColor(ContextCompat.getColor(context, R.color.l_transparent_10))
                .strokeColor(Color.RED).strokeWidth(1f)
        );
    }
    fun getTimeType(num: Int): String {
@@ -313,6 +331,7 @@
    ) {
        initRouteLine(context, start, end, null, onClick)
    }
    fun initRouteLine(
        start: LatLng, end: LatLng,
        onClick: (latLngs: MutableList<LatLng>, lineTance: Float, lineTime: Long) -> Unit
@@ -339,7 +358,8 @@
            var time = 0 //秒
            var tance = 0 //米
            var allPoint = arrayListOf<LatLng>()
            val decode = PolyUtil.decode(googleBean.routes?.firstOrNull()?.overview_polyline?.points ?: "")
            val decode =
                PolyUtil.decode(googleBean.routes?.firstOrNull()?.overview_polyline?.points ?: "")
            for (routes in googleBean.routes ?: arrayListOf()) {
                if (routes.legs.isNullOrEmpty()) {
@@ -367,14 +387,15 @@
            .build()
        val mediaType: MediaType = MediaType.parse("text/plain")!!
        val body: RequestBody = RequestBody.create(mediaType, "")
        var centerStr = getPointStr(centerPoint?: arrayListOf())
        var centerStr = getPointStr(centerPoint ?: arrayListOf())
        val request: Request = Request.Builder()
            .url("https://maps.googleapis.com/maps/api/directions/json" +
                    "?origin=" + start.latitude.toString()+","+start.longitude.toString() +
                    "&destination="+end.latitude.toString()+","+end.longitude.toString() +
                    "&waypoints="+ centerStr +
                    "&region="+language+
                    "&key="+ Const.google_key
            .url(
                "https://maps.googleapis.com/maps/api/directions/json" +
                        "?origin=" + start.latitude.toString() + "," + start.longitude.toString() +
                        "&destination=" + end.latitude.toString() + "," + end.longitude.toString() +
                        "&waypoints=" + centerStr +
                        "&region=" + language +
                        "&key=" + Const.google_key
            )
            .method("GET", body)
            .build()
@@ -384,31 +405,31 @@
        var time = 0 //秒
        var tance = 0 //米
        var allPoint = arrayListOf<LatLng>()
        for (routes in googleBean.routes?: arrayListOf()){
            if (routes.legs.isNullOrEmpty()){
        for (routes in googleBean.routes ?: arrayListOf()) {
            if (routes.legs.isNullOrEmpty()) {
                Log.i(TAG, "initRouteLine: 无路线")
                return
            }
            time = routes.legs[0].duration?.value?:0
            tance= routes.legs[0].distance?.value?:0
            if (routes.legs.isNullOrEmpty()){
            time = routes.legs[0].duration?.value ?: 0
            tance = routes.legs[0].distance?.value ?: 0
            if (routes.legs.isNullOrEmpty()) {
                Log.i(TAG, "initRouteLine: 无途径点")
                return
            }
            for (item in routes.legs[0].steps?: arrayListOf()){
                allPoint.add(LatLng(item.end_location?.lat?:0.0, item.end_location?.lng?:0.0))
            for (item in routes.legs[0].steps ?: arrayListOf()) {
                allPoint.add(LatLng(item.end_location?.lat ?: 0.0, item.end_location?.lng ?: 0.0))
            }
        }
        onClick(allPoint, tance.toFloat(), time.toLong()/60)
        onClick(allPoint, tance.toFloat(), time.toLong() / 60)
    }
    private fun getPointStr(centerPoint: List<LatLng>): String {
        var s = ""
        for (item in centerPoint){
            if (s.isEmpty()){
                s+=item.latitude.toString()+","+item.longitude.toString()
            }else{
                s+="|"+item.latitude.toString()+","+item.longitude.toString()
        for (item in centerPoint) {
            if (s.isEmpty()) {
                s += item.latitude.toString() + "," + item.longitude.toString()
            } else {
                s += "|" + item.latitude.toString() + "," + item.longitude.toString()
            }
        }
        return s
@@ -427,26 +448,31 @@
        return false
    }
    fun getClient(url:String,function: (String) -> Unit){
    fun getClient(url: String, function: (String) -> Unit) {
        val client = OkHttpClient().newBuilder().build()
        val mediaType = MediaType.parse("text/plain")
        val body = RequestBody.create(mediaType, "")
        val request: Request = Request.Builder()
            .url(url)
            .method("GET",null)
            .method("GET", null)
            .build()
        Thread{
        Thread {
            try {
                val response = client.newCall(request).execute()
                Handler(Looper.getMainLooper()).post {
                    function(response.body()?.string()?:"")
                    try {
                        function(response.body()?.string() ?: "")
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }
            }catch (e:Exception){
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }.start()
    }
    /***
     * 周边检索
     * @param lat
@@ -456,19 +482,19 @@
        context: Context,
        lat: Double,
        lng: Double,
       function: ( List<GoogleNearBean2.ResultsBean>) -> Unit
        function: (List<GoogleNearBean2.ResultsBean>) -> Unit
    ) {
        var language = LanguageUtil.getLanguage()
        var url = "https://maps.googleapis.com/maps/api/place/nearbysearch/json" +
                "?location="+ lat.toString()+","+lng.toString() +
                "?location=" + lat.toString() + "," + lng.toString() +
                "&radius=1500" +
//                "&type=restaurant" +
                "&language="+language +
                "&key="+Const.google_key
        getClient(url){
            var near = Gson().fromJson<GoogleNearBean2>(it,GoogleNearBean2::class.java)
            if (near.results!!.isNotEmpty() && near.results!!.size > 1){
                function(near.results?: arrayListOf())
                "&language=" + language +
                "&key=" + Const.google_key
        getClient(url) {
            var near = Gson().fromJson<GoogleNearBean2>(it, GoogleNearBean2::class.java)
            if (near.results!!.isNotEmpty() && near.results!!.size > 1) {
                function(near.results ?: arrayListOf())
            }
        }
    }
@@ -478,15 +504,21 @@
     * @param str
     * @param var1
     */
    fun searchSite(context: Context, content: String?, cityName: String, function: (List<AutocompletePrediction>) -> Unit) {
    fun searchSite(
        context: Context,
        content: String?,
        cityName: String,
        function: (List<AutocompletePrediction>) -> Unit
    ) {
        val placesClient = Places.createClient(context)
        var language = LanguageUtil.getLanguage()
        val token = AutocompleteSessionToken.newInstance()
//        val bounds = RectangularBounds.newInstance(
//            LatLng(-33.880490, 151.184363), LatLng(-33.858754, 151.229596))
        val request = FindAutocompletePredictionsRequest.builder() // Call either setLocationBias() OR setLocationRestriction().
        val request =
            FindAutocompletePredictionsRequest.builder() // Call either setLocationBias() OR setLocationRestriction().
//                .setLocationBias(bounds)
                .setOrigin(LatLng(IGoApplication.lat, IGoApplication.lon))
                .setOrigin(IGoApplication.getCurrentLocation())
                .setCountries(language)
                .setTypeFilter(TypeFilter.ADDRESS)
                .setSessionToken(token)
@@ -504,7 +536,7 @@
    }
    fun getPlanceIdDetail(context: Context,id:String,function: (Place) -> Unit){
    fun getPlanceIdDetail(context: Context, id: String, function: (Place) -> Unit) {
        val placesClient = Places.createClient(context)
        val placeFields = Arrays.asList(Place.Field.ID, Place.Field.NAME)
        val request = FetchPlaceRequest.newInstance(id, placeFields)
@@ -524,29 +556,30 @@
    /***
     * 逆地址编码
     */
    fun getAddress(context: Context,lat:Double,lon:Double,function:(String)->Unit) {
    fun getAddress(context: Context, lat: Double, lon: Double, function: (String) -> Unit) {
        var language = LanguageUtil.getLanguage()
        var url = "https://maps.googleapis.com/maps/api/geocode/json" +
                "?latlng="+ lat.toString() +","+lon.toString() +
                "&language="+language+
                "&result_type=postal_code"+
                "&key="+Const.google_key
        getClient(url){
            var bean = Gson().fromJson<GoogleBackBean>(it,GoogleBackBean::class.java)
                "?latlng=" + lat.toString() + "," + lon.toString() +
                "&language=" + language +
                "&result_type=postal_code" +
                "&key=" + Const.google_key
        getClient(url) {
            var bean = Gson().fromJson<GoogleBackBean>(it, GoogleBackBean::class.java)
            if (!bean.results.isNullOrEmpty() && bean.results!![0].types.isNotEmpty())
                function(bean.results!![0].address_components!![0].short_name!!)
        }
    }
    fun getAddressName(context: Context,lat:Double,lon:Double,function:(String)->Unit) {
    fun getAddressName(context: Context, lat: Double, lon: Double, function: (String) -> Unit) {
        var language = LanguageUtil.getLanguage()
        var url = "https://maps.googleapis.com/maps/api/geocode/json" +
                "?latlng="+ lat.toString() +","+lon.toString() +
                "&language="+language+
                "&result_type=street_address"+
                "&key="+Const.google_key
        getClient(url){
            var bean = Gson().fromJson<GoogleBackBean>(it,GoogleBackBean::class.java)
                "?latlng=" + lat.toString() + "," + lon.toString() +
                "&language=" + language +
                "&result_type=street_address" +
                "&key=" + Const.google_key
        getClient(url) {
            var bean = Gson().fromJson<GoogleBackBean>(it, GoogleBackBean::class.java)
            if (!bean.results.isNullOrEmpty() && bean.results!![0].types.isNotEmpty())
                function(bean.results!![0].address_components!![3].short_name!!)
        }