GetFusedLocationProviderClient 返回用户位置的空纬度和经度值

Posted

技术标签:

【中文标题】GetFusedLocationProviderClient 返回用户位置的空纬度和经度值【英文标题】:GetFusedLocationProviderClient returning null latitude and longitude values for users' location 【发布时间】:2021-12-06 04:22:31 【问题描述】:

对于我正在制作的应用,我需要获取用户的位置,然后将其显示在地图上。

为了实现这一点,我在下面的代码中使用了 LocationServices.getFusedLocationProviderClient()。

当我在 addOnSuccessListener 中获取位置值时,纬度和经度值由于某种原因为空,所以我得到了 NullPointerException:

import android.Manifest
import android.annotation.SuppressLint
import android.location.Location
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.core.app.ActivityCompat
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.android.material.dialog.MaterialAlertDialogBuilder
import com.realtomjoney.mapsapp.databinding.ActivityMainBinding
import java.lang.NullPointerException

class MainActivity : AppCompatActivity(), OnMapReadyCallback 
    private lateinit var binding: ActivityMainBinding

    lateinit var myMap: GoogleMap

    lateinit var fusedLocation: FusedLocationProviderClient

    @SuppressLint("MissingPermission")
    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        ActivityCompat.requestPermissions(this, arrayOf(
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION) , 100)

        val mapFragment = supportFragmentManager
            .findFragmentById(R.id.map) as SupportMapFragment
        mapFragment.getMapAsync(this)

        binding.button2.setOnClickListener 
            fusedLocation = LocationServices.getFusedLocationProviderClient(this)
            fusedLocation.lastLocation.addOnSuccessListener  location: Location? ->
                val latLong = LatLng(location!!.latitude, location.longitude)
                myMap.addMarker(MarkerOptions().position(latLong).title("Found Location"))

                myMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLong, 10f))
            
        
    

    override fun onMapReady(p0: GoogleMap) 
        myMap = p0
    


当我运行应用程序时,出现以下异常:

2021-10-19 16:46:09.859 8556-8556/com.realtomjoney.mapsapp E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.realtomjoney.mapsapp, PID: 8556
    java.lang.NullPointerException
        at com.realtomjoney.mapsapp.MainActivity.onCreate$lambda-1$lambda-0(MainActivity.kt:46)
        at com.realtomjoney.mapsapp.MainActivity.$r8$lambda$wwcxhtPyugLtHLn65vCEt3JY33Q(Unknown Source:0)
        at com.realtomjoney.mapsapp.MainActivity$$ExternalSyntheticLambda1.onSuccess(Unknown Source:4)
        at com.google.android.gms.tasks.zzn.run(com.google.android.gms:play-services-tasks@@17.2.0:4)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7842)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)

是的,当我第一次运行该应用程序时,我已同意所有权限。

如果这个问题写得不好或重复,请告诉我,因为我正在努力创建良好且结构良好的问题。

【问题讨论】:

【参考方案1】:

我也遇到过这个问题,尤其是当我第一次在设备上安装我的应用程序时。您可以尝试以下两件事,我认为会有所帮助:

有人正在尝试打开谷歌地图应用程序并等待它得到修复,然后继续打开您的应用程序。这应该为您的融合位置提供程序客户端提供它可以查找的最后一个位置。检查此answer 以供参考

第二个更进一步,使用提供者请求location updates。如果您只需要一个位置修复,您可以在获得第一个位置后继续并取消注册。我正在为我的应用程序执行此操作,通常最后一个位置只有在我安装后第一次使用该应用程序时才为空。之后它通常可以工作。无论如何,这可能是您应该做的,因为您不能期望您的用户在使用您的应用程序之前打开谷歌地图。

为了安全起见,请注意fusedlocationproviderclient 有时会在您的设备上有待处理的 Google 服务更新时停止工作或行为异常。所以请继续确保您的设备在这方面是最新的。

【讨论】:

谷歌地图成功了,享受你的 +50 声望 :) 酷,谢谢。 :D 用于生产考虑我回答的第二部分。有些人几乎从不使用定位服务,所以他们会遇到与您相同的问题【参考方案2】:

lastLocation 可以为 null 有几个原因。 他们在此处列出https://developer.android.com/training/location/retrieve-current#last-known

【讨论】:

我检查了每个案例,但都没有解决问题。【参考方案3】:

首先,在初始化用户坐标到地图时不为空的正确过程是在 onConnected() 回调而不是在活动或片段中的 onCreate() 上初始化地图,lastLocation 可以为空。

如果不使用location observer,你可以使用REQUEST_CODE_ASK_PERMISSIONS来处理回调,位置观察器基本上看起来像这样

if (location.provider == LocationManager.GPS_PROVIDER) 
                getData()
            

以前我也遇到过同样的情况,我的代码在权限回调中是这样的:

if (isGranted()) 
            try 
                fusedLocationProviderClient.lastLocation.addOnCompleteListener 
                    if (it.isSuccessful) 
                        if (it.result != null) 
                            setLocationData(it.result)
                        
                    
                
             catch (e: Exception) 
            

基本上在授予权限后,它会获取您的位置,您可以选择它是否要使用它来添加标记或其他任何东西。

【讨论】:

【参考方案4】:

我遇到了同样的问题

    检查设备上的gps是否开启 可能是因为您使用的 google maps api 密钥的计费 检查所有这些有时错误日志显示谷歌地图计费问题的问题

【讨论】:

【参考方案5】:

看起来您请求了权限(ActivityCompat.requestPermissions(...)),但从未处理过权限请求(您需要覆盖 onRequestPermissionsResult(...))。更多信息:https://developer.android.com/training/permissions/requesting#manage-request-code-yourself

或者你可以切换到新的方式让系统管理请求码:https://developer.android.com/training/permissions/requesting#allow-system-manage-request-code

最后一件事,在某些情况下 getLastLocation() 可以返回 null,在这种情况下,我调用 getCurrentLocation() 总是返回新的设备位置,更多信息在这里:https://developer.android.com/training/location/retrieve-current#BestEstimate

【讨论】:

以上是关于GetFusedLocationProviderClient 返回用户位置的空纬度和经度值的主要内容,如果未能解决你的问题,请参考以下文章