【问题标题】:getLastKnownLocation null - how to get data?getLastKnownLocation null - 如何获取数据?
【发布时间】:2019-08-13 11:05:01
【问题描述】:

我正在尝试使用 getLastKnownLocation 获取位置信息,但我经常得到 null

这是我的工作:

  1. 在“设置”中关闭定位
  2. 运行我的应用程序 - getLastKnownLocation 返回 null - 这是预期的
  3. 在“设置”中开启定位功能
  4. 再次运行我的应用 - getLastKnownLocation 返回 null !?
  5. 运行 Google 地图
  6. 再次运行我的应用 - getLastKnownLocation 返回有效位置!?

我发现了这个问题,其中接受的答案建议首先启动地图以获取位置: FusedLocationApi.getLastLocation always null

问题是:Google 地图如何获取位置?我怎样才能在我的代码中做同样的事情?

谢谢!

【问题讨论】:

  • 您需要在某个时候请求位置更新,以便设备实际上具有 lastKnownLocation
  • 使用 requestLocationUpdates。不要依赖 getLastKnownLocation,它是最好的优化。忘记它的存在几乎更好,它的工作频率很低。
  • “Google 地图在做什么来获取位置?” 它请求位置更新。除非某些应用程序请求确定位置,否则 Android 设备不会尝试确定其位置。这就解释了为什么打开谷歌地图会突然让你的应用收到一个有效的位置,也解释了为什么这么多人想知道getLastKnownLocation()返回null

标签: android


【解决方案1】:

感谢大家的帮助!

我的清单中缺少 uses-features 声明 - 感谢@CommonsWare 提供链接:https://developer.android.com/guide/topics/location/strategies.html#java

<!-- Needed only if your app targets Android 5.0 (API level 21) or higher. -->
<uses-feature android:name="android.hardware.location.gps" />
<uses-feature android:name="android.hardware.location.network" />

此外,还需要像这样请求更新:

locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);

在我的情况下,GPS 提供商需要几分钟来连接并开始发送数据 - 网络提供商似乎更快,但并不总是有效 - 所以我将同时使用它们。

更新:几个关键点

  1. 这不是很直观,但是为了从 getLastKnownLocation 获取数据,设备上的某些应用程序(无论是 Google 地图还是我们自己的应用程序)需要调用 requestLocationUpdates
  2. 某些提供程序可能未在特定设备上启用 - 因此最好同时使用 GPS_PROVIDERNETWORK_PROVIDER - 或使用所有已启用的提供程序:locationManager.getProviders(true)

这是我最终使用的代码:

for ( String provider : locationManager.getProviders(true) ) {
    setLocation( locationManager.getLastKnownLocation(provider) );
    locationManager.requestLocationUpdates(provider, Tools.MIN_5, 0, locationListener);
}
// call setLocation again in locationListener.onLocationChanged

【讨论】:

  • 每当你得到别人的帮助时,不要添加自己的答案,接受别人的答案
  • 你是完全正确的@Gourav - 但没有答案可以接受..我从 cmets 中的链接得到这些
  • 好的。然后我鼓励你接受你自己的答案。
【解决方案2】:

这是一个可以帮助你的代码块。

  if (!::mFusedLocationProviderClient.isInitialized) {
        mFusedLocationProviderClient = FusedLocationProviderClient(mContext)
        mLocationRequest = LocationRequest()
        mLocationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY
        mLocationRequest.interval = 10000
        mLocationRequest.fastestInterval = 5000
        mLocationRequest.smallestDisplacement = 1000 * 100f
    }
    if (ActivityCompat.checkSelfPermission(
            AppName.appContext,
            android.Manifest.permission.ACCESS_FINE_LOCATION
        ) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(
            AppName.appContext,
            android.Manifest.permission.ACCESS_COARSE_LOCATION
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        // not enough permission
        return
    }
    mFusedLocationProviderClient.requestLocationUpdates(mLocationRequest, object : LocationCallback() {
        override fun onLocationResult(p0: LocationResult?) {
            super.onLocationResult(p0)
            mFusedLocationProviderClient.removeLocationUpdates(this)
            if (p0 != null) {
             //here is your location
            } else {
              // location is null
            }
        }

        override fun onLocationAvailability(p0: LocationAvailability?) {
            if(p0?.isLocationAvailable!= true){
       //location not available.
            }
        }

    }, Looper.getMainLooper())

【讨论】:

    【解决方案3】:

    确保您授予所有权限,如果您在 6.1 设备以上运行应用程序,则处理权限..

    之后使用此代码..

    将以下依赖项添加到应用级 gradle 文件中..

    //Place API
    implementation 'com.google.android.gms:play-services-places:16.0.0'
    implementation 'com.google.android.gms:play-services-location:16.0.0'
    

    将其定义为类级别作为全局减速。

    private lateinit var fusedLocationClient: FusedLocationProviderClient
    private var context: Context? = null
    private var locationCallback: LocationCallback? = null
    private var locationRequest: LocationRequest? = null
    private var googleApiClient: GoogleApiClient? = null
    

    在 onCreate 方法之后..

            fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
    

    获取位置的方法..

    fun getCurrentLocation() {
        // Get Current location and do reverse geocoding
        ProgressUtils.showOldProgressDialog(this)
    
    
        locationCallback = object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult?) {
                locationResult ?: return
                ProgressUtils.closeOldProgressDialog()
                for (location in locationResult.locations) {
                    // here you get current lat ,long,etc value.. 
                            stopLocationUpdates()
                        }
                    } catch (e: Exception) {
                        e.message.loggerError()
                        stopLocationUpdates()
                    }
                }
            }
        }
    
        locationRequest = LocationRequest().apply {
            interval = 10000
            fastestInterval = 5000
            priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        }
    
    
        startLocationUpdates()
    
    
    }
    

    进行位置更新..

     fun startLocationUpdates() {
    
        googleApiClient = GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .build()
    
        googleApiClient!!.connect()
    
    
        val builder = LocationSettingsRequest.Builder().addLocationRequest(locationRequest!!)
        builder.setAlwaysShow(true)
    
        val result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build())
        result.setResultCallback { result ->
            val status = result.status
            when (status.statusCode) {
                LocationSettingsStatusCodes.SUCCESS -> {
                    Log.i(TAG, "All location settings are satisfied.")
                    fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null)
                }
                LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> {
                    Log.i(TAG, "Location settings are not satisfied. Show the user a dialog to upgrade location settings ")
    
                    try {
                        // Show the dialog by calling startResolutionForResult(), and check the result
                        // in onActivityResult().
                        status.startResolutionForResult(this, LOCATION_SETTING_REQUEST_CODE)
                    } catch (e: IntentSender.SendIntentException) {
                        Log.i(TAG, "PendingIntent unable to execute request.")
                    }
    
                }
                LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> Log.i(TAG, "Location settings are inadequate, and cannot be fixed here. Dialog not created.")
            }
        }
    
    }
    

    制作停止位置的方法..

    private fun stopLocationUpdates() {
    
        if (locationCallback != null) {
            fusedLocationClient?.removeLocationUpdates(locationCallback)
        }
    }
    
    override fun onStop() {
        super.onStop()
        stopLocationUpdates()
    }
    
    override fun onPause() {
        super.onPause()
        stopLocationUpdates()
    }
    

    如果处理权限比权限被授予,那么回调获取 onActivity Result 方法放下面的代码..

         fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-06
      • 2013-12-24
      • 2012-05-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多