目前采用LocationManager
的方式获取定位,在部分设备上(比如Redmi K30, MIUI 13.0.6
)授权+开启了GPS的情况下会获取不到定位信息,其他设备都正常,但这导致我小米应用市场无法上架应用。
请问主流的获取GPS定位的方式是怎样的?该如何解决上述部分设备获取不到定位的问题?
我GPS定位的代码如下(核心思路是遍历定位提供者,网络、GPS等受支持的提供者,监听位置变化,间隔2秒获取一次定位信息,获取不到反复5次,之后失败。期间获取到就成功):
@SuppressLint("MissingPermission")
private static CompletableFuture<Location> requestLocation(Activity activity) {
CompletableFuture<Location> future = new CompletableFuture<>();
future.exceptionally(throwable -> {
LogUtil.throwException(throwable, true, activity);
return null;
});
LocationManager locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);
List<String> providers = locationManager.getProviders(true);
AtomicReference<Location> bestLocationAtomic = new AtomicReference<>();
LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(@NonNull Location location) {
Location bestLocation = bestLocationAtomic.get();
// getAccacy - 返回精确度(误差范围,以米为单位,值越小越精确)
if (bestLocation == null || location.getAccuracy() < bestLocation.getAccuracy()) {
// 如果当前位置更准确,则使用当前位置
bestLocationAtomic.set(location);
}
// 当获取到为止变更的时候移除位置监听器
locationManager.removeUpdates(this);
}
/**
* ************************************************
* api level 24 设备需要实现这个方法 否则会报错
* ************************************************
*/
@Deprecated
@Override
@SuppressWarnings("deprecation")
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderDisabled(@NonNull String provider) {
}
@Override
public void onProviderEnabled(@NonNull String provider) {
}
};
for (String provider : providers) {
/*
locationManager.requestLocationUpdates(provider, 0, 0, locationListener)是用于注册位置监听器的方法。它有四个参数:
provider:要注册监听器的位置提供者。可以是LocationManager.GPS_PROVIDER、LocationManager.NETWORK_PROVIDER等。
minTime:位置更新的最小时间间隔(以毫秒为单位)。设置为0表示尽可能频繁地接收位置更新。
minDistance:位置更新的最小距离间隔(以米为单位)。设置为0表示无论移动多远都接收位置更新。
locationListener:位置监听器对象,用于接收位置更新的回调。
*/
locationManager.requestLocationUpdates(provider, 0, 0, locationListener);
}
// 等待两秒
getResult(bestLocationAtomic, future, 0);
return future;
}
private static void getResult(AtomicReference<Location> locationAtomic, CompletableFuture<Location> future, int retryCount) {
ThreadCommon.delay(() -> {
Location location = locationAtomic.get();
if (location == null && retryCount < 10) {
getResult(locationAtomic, future, retryCount + 1);
} else {
ThreadCommon.runOnUiThread(() -> future.complete(location));
}
}, 1000);
}
我将你的代码进行了优化,结合了AGPS和网络定位,并增加了权限检查。以下是修复后的代码:
主要改动
1.权限检查:在请求定位之前,检查并请求必要的权限。
2.使用AGPS和网络定位:在遍历提供者时,增加了网络定位的支持。
3.优化定位参数:增加了定位更新的时间间隔和距离间隔,以减少设备负担并提高定位成功率。