在Android10 LocationListener的onStatusChanged被废弃,此回调永远不会在Android Q及以上版本上调用,提供商可以被视为始终处于LocationProvider#AVAILABLE状态。
LocationListener | Android Developers
有以下解决方案:
① 使用LocationListenerCompat(设备必须搭载GMS)
② 使用高德sdk、百度sdk或第三方
但是有的项目,这些条件都不满足,这就导致,这个API被废弃,在GPS信号不好的地方,回调不了任何方法来让应用知道GPS信号不佳来进行响应的逻辑处理,本篇文章着重于解决这个问题。
1、创建请求位置的接口
public interface LocationChangeListener {
void onLocationChanged(double latitude, double longitude);
default void onProviderEnabled(String provider) {}
default void onProviderDisabled(String provider) {}
default void onStatusChanged(String provider, int status, Bundle extras) {}
}
2、创建GpsLocationManager
public class GpsLocationManager {
private static final String TAG = GpsLocationManager.class.getSimpleName();
private final LocationManager mLocationManager;
private LocationChangeListener mLocationChangeListener;
private LocationChangedListener mLocationChangedListener;
public static SpUtils mGPSSpUtils = null;
public void setLocationChangeListener(LocationChangeListener listener) {
this.mLocationChangeListener = listener;
}
public GpsLocationManager() {
mLocationManager = (LocationManager) App.get().getSystemService(Context.LOCATION_SERVICE);
mLocationChangedListener = new LocationChangedListener();
mGPSSpUtils = new SpUtils(App.get(), Const.GPS_STATE_SP);
}
/**
* request location.
*
* @param context context
*/
public void requestLocationUpdates(Context context) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// 如果没有位置权限,请求用户授权
ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
} else {
// 如果有位置权限,开始监听位置变化
mLocationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER,mLocationChangedListener, Looper.getMainLooper());
mGPSSpUtils.setBoolean(Const.GPS_STATE_SP, false);
mGPSSpUtils.apply();
}
}
/**
* release LocationManager.
*
*/
public void release() {
if (mLocationManager != null && mLocationChangedListener != null) {
try {
mLocationManager.removeUpdates(mLocationChangedListener);
} catch (SecurityException e) {
Logger.e(TAG, "Error releasing location updates: " + e.getMessage());
}
}
}
public class LocationChangedListener implements LocationListener {
public LocationChangedListener() {
}
@Override
public void onLocationChanged(Location location) {
mGPSSpUtils.setBoolean(Const.GPS_STATE_SP, true);
mGPSSpUtils.apply();
if (mLocationChangeListener != null) {
mLocationChangeListener.onLocationChanged(location.getLatitude(), location.getLongitude());
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
if (mLocationChangeListener != null) {
mLocationChangeListener.onStatusChanged(provider, status, extras);
}
}
@Override
public void onProviderEnabled(String provider) {
mGPSSpUtils.setBoolean(Const.GPS_STATE_SP, true);
mGPSSpUtils.apply();
if (mLocationChangeListener != null) {
mLocationChangeListener.onProviderEnabled(provider);
}
}
@Override
public void onProviderDisabled(String provider) {
mGPSSpUtils.setBoolean(Const.GPS_STATE_SP, false);
mGPSSpUtils.apply();
if (mLocationChangeListener != null) {
mLocationChangeListener.onProviderDisabled(provider);
}
}
}
}
这里面通过SharedPreferences来存储发出位置请求及请求到位置信息等的状态。
3、在项目需求的位置调用manager中的方法去请求数据
private static void requestLocationAndDataUpdates() {
mGpsLocationManager.setLocationChangeListener(new LocationChangeListener() {
@Override
public void onLocationChanged(double latitude, double longitude) {
Logger.d(TAG, "onLocationChanged: latitude:" + latitude + " longitude:"+ longitude);
// 请求到位置信息,进行相应的操作
}
});
// 请求位置更新
mGpsLocationManager.requestLocationUpdates(mContext);
}
在合适的时机,延时获取SharedPreferences的值来判断是否请求到位置信息
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
boolean GpsMsgState = mGPSSpUtils.getBoolean(Const.GPS_STATE_SP,false);
Logger.d(TAG, "checkNetworkAndRequestLocation: GpsMsgState:"+GpsMsgState);
if (!GpsMsgState) {
mWeatherInfo.setGPSState(Const.GPS_INVALID);
// 没有请求到位置信息,进行相应的操作
}
}
}, Const.RQUEST_STATE_DELAYED_TIME);
这里面Const.RQUEST_STATE_DELAYED_TIME我定义的是6秒,一般请求到位置信息的时间大概是几秒到几十秒,可以根据具体项目进行调整。
当然了,如果项目搭载了第三方的sdk更好,这是下下策,有弊端:如果GPS在自定义的delay时间外,那就取不到位置信息了(也可以写一个监听这个经纬度的变化的监听),如果遇到这个问题,可以参考一下。