【问题标题】:Android LocationServices.checkLocationSettings false negative resultAndroid LocationServices.checkLocationSettings 假阴性结果
【发布时间】:2021-10-20 16:20:44
【问题描述】:

目前受影响的设备:

  • Xperia 1 II
  • 小米红米 Note 7

用途: 为了请求位置更新,我检查了位置设置 事先就足够了。如果没有,我显示一个小文本,服务必须 为我的功能启用。如果用户点击它,系统对话框启用 会提示定位服务。

我如何运行检查: 我通过LocationSettingsRequestLocationServices 运行检查和 处理ResolvableApiException。如果该服务被用户禁用, 然后在我所有的设备上,这将显示系统对话框,要求用户启用 服务(并启用它,如果单击确定)。

在 Redmi 上会发生什么: 但无论出于何种原因,在小米红米 Note 7 上,checkLocationSettings总是返回 ResolvableApiException,即使服务 已启用。对话框不会出现并直接返回肯定结果 (当然,因为该服务已启用)。 因此,用户被卡住并永远点击“启用”。

有人知道为什么LocationSettingsRequest 不工作吗 在这些设备上正常运行并且知道如何修复它?

示例代码 sn-p

void enableLocationSettings(onLocationServiceRequiredCallback: ICallback) {
   LocationRequest locationRequest = LocationRequest.create()
         .setInterval(LOCATION_UPDATE_INTERVAL)
         .setExpirationDuration(LOCATION_UPDATE_EXPIRATION_DURATION)
         .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
            .addLocationRequest(locationRequest);

    LocationServices
            .getSettingsClient(this)
            .checkLocationSettings(builder.build())
            .addOnSuccessListener(this, (LocationSettingsResponse response) -> {
                // update location as usual
            })
            .addOnFailureListener(this, error -> {
                if (error instanceOf ApiException) {
                    int statusCode = error.statusCode;
                    if(statusCode == LocationSettingsStatusCodes.RESOLUTION_REQUIRED) {
                        if(error instanceOf ResolvableApiException) {
                            PendingIntent resolution = error.resolution 
             // This will trigger the system dialog, see below
                            onLocationServiceRequiredCallback(resolution);
                        }
                    }
                }
                // error callback
            });  

 

不幸的是,回调的代码现在将是 kotlin。对此感到抱歉。我只能发布“示例代码 sn-ps”,因为这是与工作相关的。

它使用ActivityResultContracts.StartIntentSenderForResult 启动 系统对话框。

resolution 是上面的 PendingIntent。

合同:

private val locationServiceContract = registerForActivityResult(
    ActivityResultContracts.StartIntentSenderForResult()
) { activityResult ->
    lifecycleScope.launchWhenResumed {
        val result = if (activityResult.resultCode == Activity.RESULT_OK) {
            // This will retrigger the location fetch (looping)
            enableLocationSettings(...) 
        } else {
            // Do nothing
        }
    }
}

调用上面的回调后,这将被执行:

        locationServiceContract.launch(
            IntentSenderRequest.Builder(
                resolution
            ).build()
        )

LocationSettingsStates 的转储,使用已弃用的 LocationSettings API(使用 GoogleApiClient)获取:

isGpsPresent: true, 
isGpsUsable: false, 
isLocationPresent: true, 
isLocationUsable: true, 
isNetworkLocationPresent: true, 
isNetworkLocationUsable: true 

【问题讨论】:

    标签: android location google-play-services


    【解决方案1】:

    您好,我使用不同的代码来检查设备上是否启用了 GPS。也许值得您尝试一下,看看它是否能解决您的问题。

     private boolean isLocationEnabled(Context context) {
            LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
            return LocationManagerCompat.isLocationEnabled(locationManager);
        }
    

    然后我通过对话框将用户发送到设置

    Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
    context.startActivity(intent);
    

    我打赌你也在做同样的事情。发送用户启用 GPS 后,您可以在恢复时再次运行该方法

    如果有帮助请告诉我

    【讨论】:

    • 谢谢!我也知道这种方法。但不幸的是,这涉及到用户手动启用设置,而相比之下,使用 ResolvableApiException 可用于打开系统对话框,这将(如果用户允许)直接启用位置服务。我真的很想知道为什么我的工作流程(也由谷歌自己宣传)在这里失败。
    • 我明白。你能不能为你的红米记录 resolvableApiException 并发布它
    • 您能否也分享您获取用户交互结果的代码。我仍然不明白它会永远在启用对话框上循环
    • 我更新了问题。不幸的是,我不能 100% 复制我的工作相关代码。但是 sn-p 希望足以了解正在发生的事情。我还更新了 fetch 的示例代码。 PendingIntent 将在 ResolvableApiException 内,用于错误状态代码 RESOLUTION_REQUIRED(代码 6)。
    • 我还注意到 Xperia 1 II 设备也发生了同样的情况。
    【解决方案2】:

    经过大量研究,我找到了解决方案...

    问题基本上是,如果LocationSettingsStatusCodes.RESOLUTION_REQUIRED == true 那么你下一个连续的调用总是会产生相同的输出

    也就是说,如果您递归调用此函数,您将始终得到 RESOLUTION_REQUIRED,因此您可以做的就是将您的合约修改为类似的内容

    private val locationServiceContract = registerForActivityResult(
        ActivityResultContracts.StartIntentSenderForResult()
    ) { activityResult ->
        lifecycleScope.launchWhenResumed {
            val result = if (activityResult.resultCode == Activity.RESULT_OK) {
                // Dont call this as it will retrigger the location fetch (looping)
               // enableLocationSettings(...) 
                   requestForLocationUpdates() // create this method see method body below
                  
            } else {
                // Do nothing
            }
        }
    }
    

    requestForLocationUpdates()

     private fun requestForLocationUpdates() {
    
              locationCallback = object : LocationCallback() {
                   override fun onLocationResult(locationResult: LocationResult) {
                        if (locationResult.locations.size > 0) {
                              // update location as usual using locationResult.locations[0] or other item
                             fusedLocationClient.removeLocationUpdates(locationCallback)
                        }
                   }
              }
    
              fusedLocationClient.requestLocationUpdates(
                   locationRequest,
                   locationCallback,
                   Looper.getMainLooper()
              )
         }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-03
      • 1970-01-01
      • 2017-10-11
      • 2015-09-28
      • 1970-01-01
      相关资源
      最近更新 更多