无法在 android studio 中获取位置

Posted

技术标签:

【中文标题】无法在 android studio 中获取位置【英文标题】:can't get location in android studio 【发布时间】:2021-12-13 05:16:03 【问题描述】:

它给了我这个错误(空对象引用上的双 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
               
           
       
   

【问题讨论】:

【参考方案1】:

避免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()
            
    

我还需要将LocationRequestLocation 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 studio 中获取位置的主要内容,如果未能解决你的问题,请参考以下文章

在 Android Studio 中使用动画更新标记位置

Android Studio GeoDataClient无法解析

Android Studio 错误:无法找到 adb 位置

如何解决 JSONArray 问题,无法获取数据,Android Studio

错误:在 Android Studio 3.1.4 中无法获取 KotlinTargetPreset 的未知属性“iosX64”?

Android在服务中使用Geocoder获取位置地址