Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 使用kotlin中的MapView检索片段中的当前位置?_Android_Kotlin_Fragment_Android Mapview_Google Api Client - Fatal编程技术网

Android 使用kotlin中的MapView检索片段中的当前位置?

Android 使用kotlin中的MapView检索片段中的当前位置?,android,kotlin,fragment,android-mapview,google-api-client,Android,Kotlin,Fragment,Android Mapview,Google Api Client,我想检索当前位置,并在用户移动时更新其位置。 在创建地图时,我有一个地图视图。现在我的问题是如何重新设置用户的当前位置,以及如果用户移动位置,该位置是否会更新?由于ApiLevel,我使用GoogleAppliclient和Mapview。 我可以检索权限,但遗憾的是,我不知道如何检索用户位置并更新它。此外,还欢迎对代码进行改进 class MapFragment : Fragment(), OnMapReadyCallback, GoogleApiClient.ConnectionCallba

我想检索当前位置,并在用户移动时更新其位置。 在创建地图时,我有一个地图视图。现在我的问题是如何重新设置用户的当前位置,以及如果用户移动位置,该位置是否会更新?由于ApiLevel,我使用GoogleAppliclient和Mapview。 我可以检索权限,但遗憾的是,我不知道如何检索用户位置并更新它。此外,还欢迎对代码进行改进

class MapFragment : Fragment(), OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener {
    private var mapView: MapView? = null
    private var gMap: GoogleMap? = null
    private val LOCATION_PERMISSION_REQUEST_CODE = 1234


    private lateinit var mapViewModel: MapViewModel

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        mapViewModel =
            ViewModelProvider(this).get(MapViewModel::class.java)
        val root = inflater.inflate(R.layout.fragment_map, container, false)
        mapView = root.findViewById(R.id.mapView) as MapView
        if (mapView != null) {
            mapView!!.onCreate(null);
            mapView!!.onResume();
            mapView!!.getMapAsync(this);
            checkLocationPermission();
        }
        checkLocationPermission();
        return root
    }


    override fun onResume() {
        super.onResume()
        mapView?.onResume()
    }

    override fun onPause() {
        super.onPause()
        mapView?.onPause()
    }

    override fun onStart() {
        super.onStart()
        mapView?.onStart()
    }

    override fun onStop() {
        super.onStop()
        mapView?.onStop()
    }

    override fun onDestroy() {
        super.onDestroy()
        mapView?.onDestroy()
    }

    override fun onLowMemory() {
        super.onLowMemory()
        mapView?.onLowMemory()
    }


    override fun onMapReady(googleMap: GoogleMap) {
        MapsInitializer.initialize(context)
        gMap = googleMap
        val coffeys = LatLng(52.075890, 4.309170)
        gMap!!.addMarker(MarkerOptions().position(coffeys).title("coffeys"))
        gMap!!.moveCamera(CameraUpdateFactory.newLatLngZoom(coffeys, 12f))

    }

    fun checkLocationPermission(): Boolean {
        return if (ContextCompat.checkSelfPermission(
                requireActivity(),
                Manifest.permission.ACCESS_FINE_LOCATION
            )
            != PackageManager.PERMISSION_GRANTED
        ) {


            // Asking user if explanation is needed
            if (ActivityCompat.shouldShowRequestPermissionRationale(
                    requireActivity(),
                    Manifest.permission.ACCESS_FINE_LOCATION
                )
            ) {
                //Prompt the user once explanation has been shown
                requestPermissions(
                    arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
                    LOCATION_PERMISSION_REQUEST_CODE
                )
            } else {
                // No explanation needed, we can request the permission.
                requestPermissions(
                    arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
                    LOCATION_PERMISSION_REQUEST_CODE
                )
            }
            false
        } else {
            true
        }
    }

    override fun onConnected(p0: Bundle?) {

    }

    override fun onConnectionSuspended(p0: Int) {
        TODO("Not yet implemented")
    }

    override fun onConnectionFailed(p0: ConnectionResult) {
        TODO("Not yet implemented")
    }


}

使用融合位置提供程序检索设备的最后一个已知位置

private lateinit var fusedLocationClient: FusedLocationProviderClient

override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

    // ...

    fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
}
要请求最后一个已知位置并处理响应,请执行以下操作:

fusedLocationClient.lastLocation
        .addOnSuccessListener { location : Location? ->
            // Got last known location. In some rare situations this can be null.
        }
这将返回一个任务,您可以使用该任务获取具有地理位置的纬度和经度坐标的Location对象

private lateinit var fusedLocationClient: FusedLocationProviderClient

override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

    // ...

    fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
}
有关详细信息:

更新: 全面实施

@SuppressLint("MissingPermission")
    private fun getDeviceLocation() {
        /*
         * Get the best and most recent location of the device, which may be null in rare
         * cases when a location is not available.
         */
        try {
            if (locationPermissionGranted) {
                val locationResult = fusedLocationProviderClient.lastLocation
                locationResult.addOnCompleteListener(requireActivity()) { task ->

                    if (task.isSuccessful) {

                        // Set the map's camera position to the current location of the device.
                        lastKnownLocation = task.result
                        if (lastKnownLocation != null) {
                            Timber.d("last  known location $lastKnownLocation")

                            map.moveCamera(
                                CameraUpdateFactory.newLatLngZoom(
                                    LatLng(
                                        lastKnownLocation!!.latitude,
                                        lastKnownLocation!!.longitude
                                    ), DEFAULT_ZOOM.toFloat()
                                )
                            )
                        } else {
                            Timber.e( "Exception: %s", task.exception)
                            map.moveCamera(
                                CameraUpdateFactory
                                    .newLatLngZoom(defaultLocation, DEFAULT_ZOOM.toFloat())
                            )
                            map.uiSettings?.isMyLocationButtonEnabled = false
                        }
                    }
                }
            }
        } catch (e: SecurityException) {
            Timber.e("Exception: %s", e.message)
        }
    }
更新2:位置更新

此代码来自官方文档,为活动实现。应该可以很好地处理片段。注意:我没有测试过这个

调用
requestLocationUpdates()
,将
locationRequest
对象的实例和
locationCallback
传递给它。定义
startLocationUpdates()
方法,如以下代码示例所示:

override fun onResume() {
    super.onResume()
    if (requestingLocationUpdates) startLocationUpdates()
}

private fun startLocationUpdates() {
    fusedLocationClient.requestLocationUpdates(locationRequest,
            locationCallback,
            Looper.getMainLooper())
}
override fun onPause() {
    super.onPause()
    stopLocationUpdates()
}

private fun stopLocationUpdates() {
    fusedLocationClient.removeLocationUpdates(locationCallback)
}
override fun onCreate(savedInstanceState: Bundle?) {
    // ...
    updateValuesFromBundle(savedInstanceState)
}

private fun updateValuesFromBundle(savedInstanceState: Bundle?) {
    savedInstanceState ?: return

    // Update the value of requestingLocationUpdates from the Bundle.
    if (savedInstanceState.keySet().contains(REQUESTING_LOCATION_UPDATES_KEY)) {
        requestingLocationUpdates = savedInstanceState.getBoolean(
                REQUESTING_LOCATION_UPDATES_KEY)
    }

    // ...

    // Update UI to match restored state
    updateUI()
}
融合位置提供程序调用
LocationCallback.onLocationResult()
callback方法。传入参数包含一个列表位置对象,该对象包含位置的纬度和经度。以下代码片段显示了如何实现
LocationCallback
接口并定义方法,然后获取位置更新的时间戳,并在应用程序的用户界面上显示纬度、经度和时间戳:

private lateinit var locationCallback: LocationCallback

// ...

override fun onCreate(savedInstanceState: Bundle?) {
    // ...

    locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult?) {
            locationResult ?: return
            for (location in locationResult.locations){
                // Update UI with location data
                // ...
            }
        }
    }
}
要停止位置更新,请调用
removeLocationUpdates()
,向其传递
locationCallback
,如以下代码示例所示:

override fun onResume() {
    super.onResume()
    if (requestingLocationUpdates) startLocationUpdates()
}

private fun startLocationUpdates() {
    fusedLocationClient.requestLocationUpdates(locationRequest,
            locationCallback,
            Looper.getMainLooper())
}
override fun onPause() {
    super.onPause()
    stopLocationUpdates()
}

private fun stopLocationUpdates() {
    fusedLocationClient.removeLocationUpdates(locationCallback)
}
override fun onCreate(savedInstanceState: Bundle?) {
    // ...
    updateValuesFromBundle(savedInstanceState)
}

private fun updateValuesFromBundle(savedInstanceState: Bundle?) {
    savedInstanceState ?: return

    // Update the value of requestingLocationUpdates from the Bundle.
    if (savedInstanceState.keySet().contains(REQUESTING_LOCATION_UPDATES_KEY)) {
        requestingLocationUpdates = savedInstanceState.getBoolean(
                REQUESTING_LOCATION_UPDATES_KEY)
    }

    // ...

    // Update UI to match restored state
    updateUI()
}
设备配置的更改(如屏幕方向或语言的更改)可能会导致当前活动被破坏。因此,您的应用程序必须存储重新创建活动所需的任何信息。实现这一点的一种方法是通过Bundle对象中存储的实例状态

以下代码示例显示如何使用活动的
onSaveInstanceState()
回调来保存实例状态:

override fun onSaveInstanceState(outState: Bundle?) {
    outState?.putBoolean(REQUESTING_LOCATION_UPDATES_KEY, requestingLocationUpdates)
    super.onSaveInstanceState(outState)
}
定义一个
updateValuesFromBundle()
方法,从活动的上一个实例还原保存的值(如果可用)。从活动的
onCreate()
方法调用该方法,如以下代码示例所示:

override fun onResume() {
    super.onResume()
    if (requestingLocationUpdates) startLocationUpdates()
}

private fun startLocationUpdates() {
    fusedLocationClient.requestLocationUpdates(locationRequest,
            locationCallback,
            Looper.getMainLooper())
}
override fun onPause() {
    super.onPause()
    stopLocationUpdates()
}

private fun stopLocationUpdates() {
    fusedLocationClient.removeLocationUpdates(locationCallback)
}
override fun onCreate(savedInstanceState: Bundle?) {
    // ...
    updateValuesFromBundle(savedInstanceState)
}

private fun updateValuesFromBundle(savedInstanceState: Bundle?) {
    savedInstanceState ?: return

    // Update the value of requestingLocationUpdates from the Bundle.
    if (savedInstanceState.keySet().contains(REQUESTING_LOCATION_UPDATES_KEY)) {
        requestingLocationUpdates = savedInstanceState.getBoolean(
                REQUESTING_LOCATION_UPDATES_KEY)
    }

    // ...

    // Update UI to match restored state
    updateUI()
}

为了获得更持久的存储,您可以将用户的首选项存储在应用程序的
SharedReferences
中。在活动的
onPause()
方法中设置共享首选项,并在
onResume()

中检索首选项谢谢您的帮助性评论,我应该在addonSuccessListener中输入什么?请检查更新的答案。希望这能有所帮助。我发现我的defaultpositionnull returns没有得到这个!你说的defaultposition是指defaultLocation吗?它是可以设置为任何位置(纬度、经度)的初始位置。在我的例子中,我将其作为defaultLocation=LatLng(-33.8523341151.2106085)再次检查更新的答案:)