第二次启动后,标记未显示在 Google 地图中

问题描述 投票:0回答:1

`对象常量{

fun buildWelcomeMessage(): String {
    return StringBuilder("Welcome, ")
        .append(currentRider!!.firstName)
        .append(" ")
        .append(currentRider!!.lastName)
        .toString()
}

fun buildName(firstName: String, lastName: String): String {
    return StringBuilder(firstName).append("").append(lastName).toString()
}

var marketList: MutableMap<String, Marker> = HashMap()
var driversFound: MutableSet<DriverGeoModel> = HashSet()
const val DRIVER_INFO_REFERENCE = "DriverInfo"
const val RIDER_INFO_REFERENCE: String = "Riders"
const val CHANNEL_ID = "myChannelRider"
const val DRIVERS_LOCATION_REFERENCES: String = "DriversLocation"
var currentRider: RiderModel? = null
const val TOKEN_REFERENCE: String = "Token"`

class HomeFragment : Fragment(), OnMapReadyCallback, FirebaseDriverInfoListener {
    private var _binding: FragmentHomeBinding? = null
    private val binding get() = _binding!!
    private lateinit var mMap: GoogleMap
    private var _mapFragment: SupportMapFragment? = null

    //location
    private lateinit var locationRequest: LocationRequest
    private lateinit var locationCallback: LocationCallback
    private lateinit var fusedLocationProviderClient: FusedLocationProviderClient

    //Load driver
    private var distance = 1.0
    private val LIMIT_RANGE = 10.0
    private var previousLocation: Location? = null
    private var currentLocation: Location? = null
    private var firstTime = true
    private var cityName = ""

    //listener
    lateinit var iFirebaseDriverLocationListener: FirebaseDriverInfoListener
    lateinit var iFirebaseFailedListener: FirebaseFailedListener

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?,
    ): View {
        _binding = FragmentHomeBinding.inflate(inflater, container, false)
        val root: View = binding.root
        _mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
        _mapFragment!!.getMapAsync(this)

        init()
        return root
    }

    override fun onDestroyView() {
        super.onDestroyView()
        fusedLocationProviderClient.removeLocationUpdates(locationCallback)
        _binding = null
    }

    private fun init() {
        iFirebaseDriverLocationListener = this

        locationRequest = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 3000).apply {
            setWaitForAccurateLocation(false)
            setMinUpdateIntervalMillis(LocationRequest.Builder.IMPLICIT_MIN_UPDATE_INTERVAL)
            setMaxUpdateDelayMillis(5000)
            setMinUpdateDistanceMeters(10f)
        }.build()

        locationCallback = object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult) {
                super.onLocationResult(locationResult)
                //set the location on map
                val newPos = LatLng(
                    locationResult.lastLocation!!.latitude, locationResult.lastLocation!!.longitude
                )
                mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(newPos, 18f))
                //if user has change location, calculate and load driver again
                if (firstTime) {
                    previousLocation = locationResult.lastLocation
                    currentLocation = locationResult.lastLocation
                    firstTime = false
                } else {
                    previousLocation = currentLocation
                    currentLocation = locationResult.lastLocation
                }
                if (previousLocation!!.distanceTo(currentLocation!!) / 1000 <= LIMIT_RANGE) {
                    loadAvailableDrivers()
                }
            }
        }
        fusedLocationProviderClient =
            LocationServices.getFusedLocationProviderClient(requireContext())
        if (ContextCompat.checkSelfPermission(
                requireContext(), Manifest.permission.ACCESS_FINE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED
        ) {
            fusedLocationProviderClient.requestLocationUpdates(
                locationRequest, locationCallback, Looper.myLooper()
            )
        } else {
            ActivityCompat.requestPermissions(
                requireActivity(), arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 12
            )
        }
        fusedLocationProviderClient.requestLocationUpdates(
            locationRequest, locationCallback, Looper.myLooper()
        )
        loadAvailableDrivers()
    }

    private fun loadAvailableDrivers() {
        if (ActivityCompat.checkSelfPermission(
                requireContext(), Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
                requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            Snackbar.make(
                requireView(), getString(R.string.permission_required), Snackbar.LENGTH_SHORT
            ).show()
            return
        }

        fusedLocationProviderClient.lastLocation.addOnFailureListener { e ->
            Snackbar.make(requireView(), e.message!!, Snackbar.LENGTH_SHORT).show()
        }.addOnSuccessListener { location ->
            if (location != null) {
                // Load all drivers in the city based on the obtained location
                val geoCoder = Geocoder(requireContext(), Locale.getDefault())
                val addressList: List<Address>?
                try {
                    @Suppress("DEPRECATION")
                    addressList =
                        geoCoder.getFromLocation(location.latitude, location.longitude, 1)
                    val cityName = addressList!![0].locality

                    //Query
                    val driverLocationRef = FirebaseDatabase.getInstance()
                        .getReference(Constants.DRIVERS_LOCATION_REFERENCES).child(cityName)

                    val gf = GeoFire(driverLocationRef)
                    val geoQuery = gf.queryAtLocation(
                        GeoLocation(location.latitude, location.longitude), distance
                    )
                    geoQuery.removeAllListeners()

                    geoQuery.addGeoQueryEventListener(object : GeoQueryEventListener {
                        override fun onKeyEntered(key: String?, location: GeoLocation?) {
                            Constants.driversFound.add(DriverGeoModel(key, location))
                        }

                        override fun onKeyExited(key: String?) {
                            Constants.driversFound.remove(DriverGeoModel(key))
                        }

                        override fun onKeyMoved(key: String?, location: GeoLocation?) {
                        }

                        override fun onGeoQueryReady() {
                            if (distance <= LIMIT_RANGE) {
                                distance++
                                loadAvailableDrivers()
                            } else {
                                distance = 0.0
                                addDriverMarker()
                            }
                        }

                        override fun onGeoQueryError(error: DatabaseError?) {
                            Snackbar.make(
                                requireView(), error!!.message, Snackbar.LENGTH_SHORT
                            ).show()
                        }
                    })

                    driverLocationRef.addChildEventListener(object : ChildEventListener {
                        override fun onChildAdded(
                            snapshot: DataSnapshot,
                            previousChildName: String?,
                        ) {
                            //Have new Driver
                            val geoQueryModel = snapshot.getValue(GeoQueryModel::class.java)
                            val geoLocation =
                                GeoLocation(geoQueryModel!!.l!![0], geoQueryModel.l!![1])
                            val driverGeoModel = DriverGeoModel(snapshot.key, geoLocation)
                            val newDriverLocation = Location("")
                            newDriverLocation.latitude = geoLocation.latitude
                            newDriverLocation.longitude = geoLocation.longitude
                            val newDistance = location.distanceTo(newDriverLocation) / 1000 //in km
                            if (newDistance <= LIMIT_RANGE) {
                                findDriverByKey(driverGeoModel)
                            }
                        }

                        override fun onChildChanged(
                            snapshot: DataSnapshot,
                            previousChildName: String?,
                        ) {
                        }

                        override fun onChildRemoved(snapshot: DataSnapshot) {
                            val removedDriverKey = snapshot.key
                            Constants.driversFound.removeAll { it.key == removedDriverKey }

                            // Remove the marker from the map
                            if (Constants.marketList.containsKey(removedDriverKey)) {
                                Constants.marketList[removedDriverKey]?.remove()
                                Constants.marketList.remove(removedDriverKey)
                            }
                        }

                        override fun onChildMoved(
                            snapshot: DataSnapshot,
                            previousChildName: String?,
                        ) {
                        }

                        override fun onCancelled(error: DatabaseError) {
                            Snackbar.make(
                                requireView(), error.message, Snackbar.LENGTH_SHORT
                            ).show()
                        }
                    })

                } catch (e: IOException) {
                    Snackbar.make(
                        requireView(),
                        getString(R.string.permission_required),
                        Snackbar.LENGTH_SHORT
                    ).show()
                }
            } else {
                Snackbar.make(
                    requireView(), "Unable to retrieve location information.", Snackbar.LENGTH_SHORT
                ).show()
            }
        }
    }

    private fun addDriverMarker() {
        Log.d("MarkerDebug", "addDriverMarker is called ")

        if (Constants.driversFound.isNotEmpty()) {
            CoroutineScope(Dispatchers.IO).launch {
                val newDriverKeys = Constants.driversFound.map { it.key }
                val existingDriverKeys = Constants.marketList.keys

                // Remove markers for drivers that are no longer in the list
                val removedDriverKeys = existingDriverKeys.subtract(newDriverKeys.toSet())
                for (key in removedDriverKeys) {
                    Constants.marketList[key]?.remove()
                    Constants.marketList.remove(key)
                }

                // Add or update markers for new or existing drivers
                Constants.driversFound.forEach { driverGeoModel ->
                    findDriverByKey(driverGeoModel)
                    Log.d("MarkerDebug", "addDriverMarker is called when found driver: ${driverGeoModel.key}")
                }
            }
            Snackbar.make(
                requireView(), getString(R.string.drivers_are_found), Snackbar.LENGTH_SHORT
            ).show()
        } else {
            // No drivers found, remove all markers from the map
            for (marker in Constants.marketList.values) {
                marker.remove()
            }
            Constants.marketList.clear()
            Snackbar.make(
                requireView(), getString(R.string.drivers_are_not_found), Snackbar.LENGTH_SHORT
            ).show()
        }
    }


    private fun findDriverByKey(driverGeoModel: DriverGeoModel?) {
        FirebaseDatabase.getInstance().getReference(Constants.DRIVER_INFO_REFERENCE)
            .child(driverGeoModel!!.key!!)
            .addListenerForSingleValueEvent(object : ValueEventListener {
                override fun onCancelled(error: DatabaseError) {
                    iFirebaseFailedListener.onFirebaseFailed(error.message)
                }

                override fun onDataChange(snapshot: DataSnapshot) {
                    if (snapshot.hasChildren()) {
                        driverGeoModel.driverInfoModel =
                            (snapshot.getValue(DriverInfoModel::class.java))
                        iFirebaseDriverLocationListener.onDriverInfoLoadSuccess(driverGeoModel)
                    } else {
                        iFirebaseFailedListener.onFirebaseFailed(getString(R.string.key_not_found) + driverGeoModel.key)
                    }
                }

            })
    }

    override fun onMapReady(googleMap: GoogleMap) {
        mMap = googleMap
        //enable zoom
        mMap.uiSettings.isZoomControlsEnabled = true
        //check the permission
        if (ActivityCompat.checkSelfPermission(
                requireContext(), Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
                requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            //if we don't have permission
            ActivityCompat.requestPermissions(
                requireActivity(), arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 12
            )
            return
        }
        //when we have permission
        if (ContextCompat.checkSelfPermission(
                requireContext(), Manifest.permission.ACCESS_FINE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED
        ) { //Enable button first
            mMap.isMyLocationEnabled = true
            mMap.uiSettings.isMyLocationButtonEnabled = true
            //when i click on button
            mMap.setOnMyLocationButtonClickListener {
                Toast.makeText(context, "clicked", Toast.LENGTH_LONG).show()
                //get last location
                fusedLocationProviderClient.lastLocation.addOnFailureListener {
                    Toast.makeText(context, it.message, Toast.LENGTH_LONG).show()
                }.addOnSuccessListener { location ->
                    val userLatLng = LatLng(location.latitude, location.longitude)
                    mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(userLatLng, 18f))
                }
                true
            }
            val locationButton = (_mapFragment!!.requireView()
                .findViewById<View>("1".toInt()).parent!! as View).findViewById<View>("2".toInt())
            val params = locationButton.layoutParams as RelativeLayout.LayoutParams
            params.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0)
            params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE)
            params.addRule(RelativeLayout.ALIGN_PARENT_START, 0)
            params.marginStart = 15
            params.bottomMargin = 250
        }

        //try to set map style
        try {
            val success = mMap.setMapStyle(
                MapStyleOptions.loadRawResourceStyle(requireContext(), R.raw.uber_maps_style)
            )
            if (!success) {
                Log.e("ErrorMap", "Map Style is not parsing")
            }
        } catch (e: Exception) {
            Log.e("ErrorMap", e.message!!)
        }

        addDriverMarker()
    }

    override fun onDriverInfoLoadSuccess(driverGeoModel: DriverGeoModel?) {
        val driverKey = driverGeoModel?.key

        if (driverKey != null) {
            if (!Constants.marketList.containsKey(driverKey)) {
                val marker = mMap.addMarker(
                    MarkerOptions().position(
                        LatLng(
                            driverGeoModel.geoLocation!!.latitude,
                            driverGeoModel.geoLocation!!.longitude
                        )
                    ).flat(true).title(
                        Constants.buildName(
                            driverGeoModel.driverInfoModel?.firstName ?: "",
                            driverGeoModel.driverInfoModel?.lastName ?: ""
                        )
                    ).snippet(driverGeoModel.driverInfoModel?.phoneNumber ?: "")
                        .icon(BitmapDescriptorFactory.fromResource(R.drawable.car))
                )
                Log.d("MarkerDebug", "Adding marker for driver: ${driverGeoModel.key}")

                Constants.marketList[driverKey] = marker!!
            }
        }

        if (!TextUtils.isEmpty(cityName)) {
            val driverLocation =
                FirebaseDatabase.getInstance().getReference(Constants.DRIVERS_LOCATION_REFERENCES)
                    .child(cityName).child(driverKey ?: "")

            driverLocation.addValueEventListener(object : ValueEventListener {
                override fun onCancelled(error: DatabaseError) {
                    Snackbar.make(
                        requireView(), error.message, Snackbar.LENGTH_SHORT
                    ).show()
                }

                override fun onDataChange(snapshot: DataSnapshot) {
                    if (!snapshot.hasChildren() && Constants.marketList.containsKey(driverKey)) {
                        // Remove the marker from the map
                        Constants.marketList[driverKey]?.remove()
                        Constants.marketList.remove(driverKey)
                        driverLocation.removeEventListener(this)
                    }
                }
            })
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        _mapFragment = null
    }
}

这个是骑手应用程序,当骑手打开并等待在线司机时,在司机应用程序中,当司机在线时,它应该在谷歌地图中显示在线司机标记,当应用程序第一次启动时(安装后)并且它按预期工作并显示在地图上,如果驾驶员离线则删除。 当应用程序第二次启动时(安装后)小吃起作用,说找到了驱动程序,并且除了标记之外的所有东西都没有显示在地图上

android kotlin google-maps-markers
1个回答
0
投票

到目前为止我已经修复了 `私人乐趣刷新Map(){ // 删除地图上的所有标记 for (Constants.marketList.values 中的标记) { 标记.remove() } Constants.marketList.clear() // 根据需要重置任何其他与标记相关的对象或数据 Constants.driversFound.clear() distance = 1.0 // 重置查询司机的距离 firstTime = true // 重置firstTime标志 // 再次加载可用的驱动程序 加载可用驱动程序() }

override fun onDestroy() {
    super.onDestroy()
    _mapFragment = null
    refreshMap()
}`
© www.soinside.com 2019 - 2024. All rights reserved.