Android LocationServices.checkLocationSettings假阴性结果



目前受影响的设备:

  • Xperia 1 II
  • 小米红米note7

使用:为了请求位置更新,我检查了位置设置都是足够的。如果没有,我会显示一个小文本,说明服务必须启用我的功能。如果用户单击它,系统对话框将启用将提示位置服务。

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

Redmi:但不管出于什么原因,在小米红米Note 7上,checkLocationSettings总是将返回一个ResolvableApiException,即使服务已启用。对话框不会出现并直接返回一个正结果(当然,因为服务是启用的)。因此,用户被卡住了,永远点击"启用"。

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

示例代码片段

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。很抱歉。我只能发布"示例代码片段",因为这是与工作相关的。

使用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 

你好,我使用不同的代码来检查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后,您可以在resume中再次运行该方法

如果有帮助请告诉我

在做了大量的研究之后,我得到了一个解决方案…

问题基本上是,如果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()
)
}

最新更新