无法在 android 工作室获取位置
can't get location in android studio
它给了我这个错误(空对象引用上的双 android.location.Location.getLatitude()')
我尝试了很多不同的解决方案,但都是一样的,我知道 fusedLocationClient.lastLocation 它只是给出了来自其他应用程序的最后位置,但我不想那样,我想获取当前位置没有它,因为它给空?那么如何解决这个问题并获取当前位置???
import android.Manifest
import android.content.ContentValues.TAG
import android.content.Context
import android.content.pm.PackageManager
import android.location.LocationManager
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import com.firebase.geofire.GeoFire
import com.firebase.geofire.GeoLocation
import com.firebase.geofire.GeoQueryEventListener
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.FirebaseDatabase
import com.moapp.guardaroundd.R
import com.moapp.guardaroundd.databinding.FragmentMapBinding
import com.moapp.guardaroundd.utils.Constants.DEFAULT_ZOOM
import com.moapp.guardaroundd.utils.Constants.LOCATION_PERMISSION_REQUEST_CODE
import com.moapp.guardaroundd.utils.createAlertEnableLocation
class MapFragment : Fragment(), OnMapReadyCallback {
private lateinit var mMap: GoogleMap
private lateinit var binding: FragmentMapBinding
private lateinit var fusedLocationClient: FusedLocationProviderClient
private var mLocationPermissionsGranted = false
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout for this fragment
binding = FragmentMapBinding.inflate(layoutInflater)
val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireActivity())
return binding.root
}
override fun onMapReady(googleMap: GoogleMap) {
mMap = googleMap
getLocationPermission()
}
private fun isLocationEnabled(): Boolean {
val locationManager =
activity?.getSystemService(Context.LOCATION_SERVICE) as LocationManager?
return locationManager!!.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(
LocationManager.NETWORK_PROVIDER
)
}
private fun moveCamera(latLng: LatLng) {
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, DEFAULT_ZOOM))
}
private fun getLocation() {
if (isLocationEnabled()) {
try {
fusedLocationClient.lastLocation.addOnSuccessListener {
moveCamera(LatLng(it.latitude, it.longitude))
mMap.isMyLocationEnabled = true
}
} catch (ex: SecurityException) {
}
} else {
//Custom alert
createAlertEnableLocation(requireContext())
}
}
private fun getLocationPermission() {
if (ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION
)
== PackageManager.PERMISSION_GRANTED
) {
mLocationPermissionsGranted = true
getLocation()
} else {
ActivityCompat.requestPermissions(
requireActivity(), arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
LOCATION_PERMISSION_REQUEST_CODE
)
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
mLocationPermissionsGranted = false
when (requestCode) {
LOCATION_PERMISSION_REQUEST_CODE -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty() &&
grantResults[0] == PackageManager.PERMISSION_GRANTED
) {
mLocationPermissionsGranted = true
}
}
}
}
避免 null location
的最简单方法是启动 Google 地图应用程序 并按我的位置按钮。然后您返回您的应用,fusedLocationClient.lastLocation
这次将为您提供非空设备的最后位置。
既然您显然不喜欢这个,那么您需要使用 Location Updates。
为此,我会稍微调整一下您的 getLocation()
代码。
private fun getLocation() {
// last known location from fusedLocationProviderClient returned as a task
fusedLocationProviderClient.lastLocation
//check if the last location is null
.addOnSuccessListener { lastLoc ->
if (lastLoc != null) {
// initialize lastKnownLocation from fusedLocationProviderClient
lastKnownLocation = lastLoc
moveCamera(LatLng(lastLoc.latitude, lastLoc.longitude))
} else {
//if null trigger location update to get location
fusedLocationProviderClient.requestLocationUpdates(
locationRequest, locationCallback, Looper.getMainLooper()
)
}
// in case of error Toast the error in a short Toast message
}
.addOnFailureListener {
Toast.makeText(requireActivity(), "${it.message}", Toast.LENGTH_SHORT).show()
}
}
我还需要将 LocationRequest
和 Location Callback
引入游戏中。
class MapFragment : Fragment(), OnMapReadyCallback { .......
// LOCATION COMPONENTS
private lateinit var lastKnownLocation: Location
private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
private val locationRequest =
LocationRequest().apply {
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
interval = TimeUnit.SECONDS.toMillis(10)
fastestInterval = TimeUnit.SECONDS.toMillis(1)
}
private val locationCallback =
object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
super.onLocationResult(locationResult)
if (locationResult != null) {
lastKnownLocation = locationResult.lastLocation
//call the above getLocation() again to move camera
getLocation()
}
}
}
因此,只要来自 fusedClient 的最后一个已知位置为空,就会触发更新并移动相机位置。
它给了我这个错误(空对象引用上的双 android.location.Location.getLatitude()')
我尝试了很多不同的解决方案,但都是一样的,我知道 fusedLocationClient.lastLocation 它只是给出了来自其他应用程序的最后位置,但我不想那样,我想获取当前位置没有它,因为它给空?那么如何解决这个问题并获取当前位置???
import android.Manifest
import android.content.ContentValues.TAG
import android.content.Context
import android.content.pm.PackageManager
import android.location.LocationManager
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import com.firebase.geofire.GeoFire
import com.firebase.geofire.GeoLocation
import com.firebase.geofire.GeoQueryEventListener
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.FirebaseDatabase
import com.moapp.guardaroundd.R
import com.moapp.guardaroundd.databinding.FragmentMapBinding
import com.moapp.guardaroundd.utils.Constants.DEFAULT_ZOOM
import com.moapp.guardaroundd.utils.Constants.LOCATION_PERMISSION_REQUEST_CODE
import com.moapp.guardaroundd.utils.createAlertEnableLocation
class MapFragment : Fragment(), OnMapReadyCallback {
private lateinit var mMap: GoogleMap
private lateinit var binding: FragmentMapBinding
private lateinit var fusedLocationClient: FusedLocationProviderClient
private var mLocationPermissionsGranted = false
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout for this fragment
binding = FragmentMapBinding.inflate(layoutInflater)
val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireActivity())
return binding.root
}
override fun onMapReady(googleMap: GoogleMap) {
mMap = googleMap
getLocationPermission()
}
private fun isLocationEnabled(): Boolean {
val locationManager =
activity?.getSystemService(Context.LOCATION_SERVICE) as LocationManager?
return locationManager!!.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(
LocationManager.NETWORK_PROVIDER
)
}
private fun moveCamera(latLng: LatLng) {
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, DEFAULT_ZOOM))
}
private fun getLocation() {
if (isLocationEnabled()) {
try {
fusedLocationClient.lastLocation.addOnSuccessListener {
moveCamera(LatLng(it.latitude, it.longitude))
mMap.isMyLocationEnabled = true
}
} catch (ex: SecurityException) {
}
} else {
//Custom alert
createAlertEnableLocation(requireContext())
}
}
private fun getLocationPermission() {
if (ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION
)
== PackageManager.PERMISSION_GRANTED
) {
mLocationPermissionsGranted = true
getLocation()
} else {
ActivityCompat.requestPermissions(
requireActivity(), arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
LOCATION_PERMISSION_REQUEST_CODE
)
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
mLocationPermissionsGranted = false
when (requestCode) {
LOCATION_PERMISSION_REQUEST_CODE -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty() &&
grantResults[0] == PackageManager.PERMISSION_GRANTED
) {
mLocationPermissionsGranted = true
}
}
}
}
避免 null location
的最简单方法是启动 Google 地图应用程序 并按我的位置按钮。然后您返回您的应用,fusedLocationClient.lastLocation
这次将为您提供非空设备的最后位置。
既然您显然不喜欢这个,那么您需要使用 Location Updates。
为此,我会稍微调整一下您的 getLocation()
代码。
private fun getLocation() {
// last known location from fusedLocationProviderClient returned as a task
fusedLocationProviderClient.lastLocation
//check if the last location is null
.addOnSuccessListener { lastLoc ->
if (lastLoc != null) {
// initialize lastKnownLocation from fusedLocationProviderClient
lastKnownLocation = lastLoc
moveCamera(LatLng(lastLoc.latitude, lastLoc.longitude))
} else {
//if null trigger location update to get location
fusedLocationProviderClient.requestLocationUpdates(
locationRequest, locationCallback, Looper.getMainLooper()
)
}
// in case of error Toast the error in a short Toast message
}
.addOnFailureListener {
Toast.makeText(requireActivity(), "${it.message}", Toast.LENGTH_SHORT).show()
}
}
我还需要将 LocationRequest
和 Location Callback
引入游戏中。
class MapFragment : Fragment(), OnMapReadyCallback { .......
// LOCATION COMPONENTS
private lateinit var lastKnownLocation: Location
private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
private val locationRequest =
LocationRequest().apply {
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
interval = TimeUnit.SECONDS.toMillis(10)
fastestInterval = TimeUnit.SECONDS.toMillis(1)
}
private val locationCallback =
object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
super.onLocationResult(locationResult)
if (locationResult != null) {
lastKnownLocation = locationResult.lastLocation
//call the above getLocation() again to move camera
getLocation()
}
}
}
因此,只要来自 fusedClient 的最后一个已知位置为空,就会触发更新并移动相机位置。