位置打开/关闭时,FusedLocationProviderClient 无法正常工作

Posted

技术标签:

【中文标题】位置打开/关闭时,FusedLocationProviderClient 无法正常工作【英文标题】:FusedLocationProviderClient not working correctly when Location turned on/off 【发布时间】:2021-08-09 19:05:24 【问题描述】:

我正在使用位置来实现地理围栏功能(将应用程序使用限制在一个国家/地区)在应用程序的第一个活动中,我使用 FusedLocationProviderClient 来获取位置,如下所示:

初始化部分

fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

和位置部分

fusedLocationClient.getLastLocation().addOnSuccessListener(this, location -> 
                if (location != null) 
                    //geofencing logic
                
            );

如果设备上始终启用位置,则此代码可以正常工作。如果用户在手机顶部的快捷菜单或设置中禁用位置并尝试进入应用程序,则会收到位置被禁用并退出的消息。之后,如果用户尝试打开位置并进入应用程序 FusedLocationClient 会卡住并且根本不返回位置。之后,它只有在我重新安装应用程序时才会起作用。有没有人遇到过这个问题并试图解决它,而不是一直使用后台位置并定期更新?

PS 如果我尝试直接使用 LocationService 访问最后一个已知位置,也会发生同样的情况。

【问题讨论】:

【参考方案1】:

您可以在特定的时间间隔内获取位置更新,而不是获取最后一个已知位置。这是代码。

声明这些融合的位置提供者类和位置回调类

private var mFusedLocationProviderClient: FusedLocationProviderClient? = null
private var mLocationRequest: LocationRequest? = null
private var mLocationCallback: LocationCallback? = null  
private const val LOCATION_REQUEST_INTERVAL: Long = 5000

`

这是定位请求的必要方法

private fun createLocationRequest() 
    mLocationRequest = LocationRequest.create()
    mLocationRequest!!.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
    mLocationRequest!!.setInterval(LOCATION_REQUEST_INTERVAL).fastestInterval =
    LOCATION_REQUEST_INTERVAL
    requestLocationUpdate()


private fun requestLocationUpdate() 
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
        != PackageManager.PERMISSION_GRANTED ) 

        Log.e("permission", "denied");


        // TODO: Consider calling
        //    ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.
        return
    

    mFusedLocationProviderClient!!.requestLocationUpdates(
        mLocationRequest,
        mLocationCallback,
        Looper.myLooper()
    )

然后在onCreate()中调用这些“createLocationRequest”方法和位置回调类。

    mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(requireContext())

 createLocationRequest()
 mLocationCallback = object : LocationCallback() 

        override fun onLocationResult(locationResult: LocationResult) 
            super.onLocationResult(locationResult)
             val lat  = locationResult.lastLocation.latitude
             val lng = locationResult.lastLocation.longitude
                                
     
        
    

并根据您的要求删除 onPause() 或 onDestory() 中的位置更新侦听器。

    mFusedLocationProviderClient!!.removeLocationUpdates(mLocationCallback)

【讨论】:

即使使用此解决方案,它也会冻结。我能够解决这个问题的唯一方法是使用 3rd 方库(即 Locus),但它一直使用位置,我试图避免这种情况。 看来您的解决方案结合删除 onPause 和 onDestroy 中的侦听器并使用主线程请求位置确实解决了问题。我会将您的答案标记为解决方案。 我忘了在 onDestory 中删除位置更新。我已经添加了这个。无论如何谢谢!【参考方案2】:

场景 1:在收到位置已禁用并退出的消息后。从最近的应用程序托盘中杀死应用程序现在启用位置。然后从主页打开应用程序作为新活动现在它应该更新位置。如果它工作正常,则 App.App 没有任何问题。

场景 2:如果你在 onCreate() 方法中有 fusedLocation.getLastLocation(),则将该代码移动到 onResume() 方法中。因为当你从最近的应用程序托盘打开应用程序时,onStart()方法将首先调用,然后调用 onResume() 而不是 onCreate()。现在启用位置,从最近的应用托盘打开应用,检查位置是否更新。

   @Override
protected void onResume() 
    super.onResume();
    if (isLocationServiceEnabled) 
        startLocationUpdates();
    

【讨论】:

位置获取是在 onResume 之后不久启动的,我已经在做方案 1。即使在检查成功后我仍然打开位置,位置获取冻结。

以上是关于位置打开/关闭时,FusedLocationProviderClient 无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

位置服务关闭和打开时地理定位不起作用

谷歌浏览器默认打开位置和大小[关闭]

Android地理围栏不会触发一次位置关闭和再次打开[重复]

当用户打开iOS 7及更高版本的位置服务时收到通知

搜狗浏览器每次打开的窗口太小,请问怎样保存打开浏览器时的窗口大小是上次关闭时的位置和大小?

如何设置word每次打开都在上次关闭时的页面?