Android10 LocationListenerのonStatusChangedは破棄される

  LocationListener の OnStatusChanged は Android10 で非推奨となり、Android Q 以降ではこのコールバックが呼び出されることはなく、プロバイダーは常に LocationProvider#AVAILABLE 状態であると見なされます。

ロケーションリスナー | Android 開発者

次の解決策があります。

① LocationListenerCompat を使用する(GMS が搭載されているデバイスである必要があります)

② Amap SDK、Baidu 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. マネージャーのメソッドを呼び出して、プロジェクトで必要なデータを要求します。

    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 がカスタム遅延時間の範囲外にある場合、位置情報を取得できないという欠点があります (また、経度と緯度の変化を監視するプログラム).監視)、この問題が発生した場合は、それを参照してください。

おすすめ

転載: blog.csdn.net/m0_50408097/article/details/133385439