无法使用 FusedLocationProvider 将 Gps 设置升级到高精度在某些设备中

Posted

技术标签:

【中文标题】无法使用 FusedLocationProvider 将 Gps 设置升级到高精度在某些设备中【英文标题】:Not Able To Upgrade Gps settings to high Accuracy using FusedLocationProvider In some devices 【发布时间】:2019-08-28 02:45:30 【问题描述】:

我正在使用 SettingsApiFusedLocationProvider 升级 Gps 设置并获取位置更新,我想要高精度位置更新,我正在显示使用 SettingsApi 打开 gps 对话框以将 GPS 设置升级到高精度,但在某些设备(例如 Mi 和 Gionee)即使用户在打开 Gps 对话框中单击了 OK 按钮,我在 onActivityResult 上收到 RESULT_CANCELED 而在摩托罗拉、联想等其他设备上一切正常

当用户在打开 Gps 对话框中单击时

    如果 Gps 处于关闭状态,则将其打开并设置为仅设备模式(仅 Gps 模式) 如果 Gps 开启,则 Gps 关闭,在这两种情况下,onActivityResult 都会出现 RESULT_CANCELED

这是我的代码

    定位助手
    public class LocationHelper 

        private static final String TAG = LocationHelper.class.getSimpleName();

        private long updateIntervalInMilliseconds = 10000;

        private long fastestUpdateIntervalInMilliseconds = updateIntervalInMilliseconds / 2;

        private FusedLocationProviderClient mFusedLocationClient;

        private SettingsClient mSettingsClient;

        private LocationRequest mLocationRequest;

        private LocationSettingsRequest mLocationSettingsRequest;

        private LocationCallback mLocationCallback;


        private Boolean mRequestingLocationUpdates = false;


        private int requiredGpsPriority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;


        public LocationHelper(Context mContext) 
            mFusedLocationClient = LocationServices.getFusedLocationProviderClient(mContext);
            mSettingsClient = LocationServices.getSettingsClient(mContext);
        

        /**
         * Sets required gps priority
         * <p>
         * Gps Priority can be
         * <ul>
         * <li>LocationRequest.PRIORITY_HIGH_ACCURACY</li>
         * <li>LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY</li>
         * <li>LocationRequest.PRIORITY_NO_POWER</li>
         * <li>LocationRequest.PRIORITY_LOW_POWER</li>
         * </ul>
         * <p>
         * default is LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY
         *
         * @param requiredGpsPriority gps priority
         */
        public void setRequiredGpsPriority(int requiredGpsPriority) 
            this.requiredGpsPriority = requiredGpsPriority;
        

        /**
         * Sets Update Interval also sets fastestUpdateIntervalInMilliseconds to half of updateIntervalInMilliseconds
         * default is 10 seconds
         *
         * @param updateIntervalInMilliseconds update Interval
         */
        public void setUpdateInterval(long updateIntervalInMilliseconds) 
            this.updateIntervalInMilliseconds = updateIntervalInMilliseconds;
            this.fastestUpdateIntervalInMilliseconds = updateIntervalInMilliseconds / 2;
        

        /**
         * Sets fastest Update Interval
         * default is 5 seconds
         *
         * @param fastestUpdateIntervalInMilliseconds fastest update Interval
         */
        public void setFastestUpdateIntervalInMilliseconds(long fastestUpdateIntervalInMilliseconds) 
            this.fastestUpdateIntervalInMilliseconds = fastestUpdateIntervalInMilliseconds;
        


        public void init() 
            createLocationRequest();
            buildLocationSettingsRequest();
        


        public void setLocationCallback(LocationCallback locationCallback) 
            this.mLocationCallback = locationCallback;
        

        private void createLocationRequest() 
            mLocationRequest = new LocationRequest();

            mLocationRequest.setInterval(updateIntervalInMilliseconds);

            mLocationRequest.setFastestInterval(fastestUpdateIntervalInMilliseconds);

            mLocationRequest.setPriority(requiredGpsPriority);
        


        private void buildLocationSettingsRequest() 
            LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
            builder.addLocationRequest(mLocationRequest);
            builder.setAlwaysShow(true);
            mLocationSettingsRequest = builder.build();
        


        public boolean isRequestingForLocation() 
            return mRequestingLocationUpdates;
        


        public void checkForGpsSettings(GpsSettingsCheckCallback callback) 

            if (mLocationSettingsRequest == null) 
                throw new IllegalStateException("must call init() before check for gps settings");
            

            // Begin by checking if the device has the necessary jobLocation settings.
            mSettingsClient.checkLocationSettings(mLocationSettingsRequest)
                    .addOnSuccessListener(locationSettingsResponse -> callback.requiredGpsSettingAreAvailable())
                    .addOnFailureListener(e -> 

                        int statusCode = ((ApiException) e).getStatusCode();
                        switch (statusCode) 
                            case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                                Log.i(TAG, "SuggestedLocation settings are not satisfied. notifying back to the requesting object ");

                                ResolvableApiException rae = (ResolvableApiException) e;
                                callback.requiredGpsSettingAreUnAvailable(rae);

                                break;

                            case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                                Log.i(TAG, "Turn On SuggestedLocation From Settings. ");

                                callback.gpsSettingsNotAvailable();
                                break;
                        

                    );
        


        /**
         * Starts location updates from the FusedLocationApi.
         * <p>
         *     Consider Calling @link #stopLocationUpdates() when you don't want location updates it helps in saving battery
         * </p>
         */
        public void startLocationUpdates() 

            if (mLocationRequest == null) 
                throw new IllegalStateException("must call init() before requesting location updates");
            

            if (mLocationCallback == null) 
                throw new IllegalStateException("no callback provided for delivering location updates,use setLocationCallback() for setting callback");
            

            if (mRequestingLocationUpdates) 
                Log.d(TAG, "startLocationUpdates: already requesting location updates, no-op.");
                return;
            

            Log.d(TAG, "startLocationUpdates: starting updates.");
            mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper())
                    .addOnCompleteListener(task -> mRequestingLocationUpdates = true);

        

        public void stopLocationUpdates() 
            if (!mRequestingLocationUpdates) 
                Log.d(TAG, "stopLocationUpdates: updates never requested, no-op.");
                return;
            

            Log.d(TAG, "stopLocationUpdates: stopping location updates.");
            mFusedLocationClient.removeLocationUpdates(mLocationCallback)
                    .addOnCompleteListener(task -> mRequestingLocationUpdates = false);
        

    GpsSettingsCheckCallback
    public interface GpsSettingsCheckCallback 


        /**
         * We don't have required Gps Settings
         * ex For High Accuracy Locations We Need Gps In High Accuracy Settings
         *
         * How To show "Turn On Gps Dialog" ?
         * 
         * From Activity :
         * <code>status.startResolutionForResult(this , REQUEST_CHECK_SETTINGS);</code>
         * 
         * From Fragment :
         * <code>
         * startIntentSenderForResult(status.getResolution().getIntentSender(), REQUEST_CHECK_SETTINGS, null, 0, 0, 0, null)
         * </code>
         */
        void requiredGpsSettingAreUnAvailable(ResolvableApiException status);


        /**
         * Everything's Good
         */
        void requiredGpsSettingAreAvailable();


        /**
         * Gps Settings Are Unavailable redirect user to settings page to turn on location
         */
        void gpsSettingsNotAvailable();
     
    活动代码
public class CheckGpsActivity extends AppCompatActivity 

    public static final String TAG = CheckGpsActivity.class.getSimpleName();
    public static final int REQUEST_LOCATION_SETTINGS_UPGRADE = 23;

    private Button turnOnLocationUpdatesBtn, turnOffLocationBtn, checkForRequredGpsSettingBtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        LocationHelper locationHelper = new LocationHelper(this);
        locationHelper.setRequiredGpsPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationHelper.init();

        locationHelper.setLocationCallback(new LocationCallback() 

            @Override
            public void onLocationResult(LocationResult locationResult) 
                super.onLocationResult(locationResult);
                Location location = locationResult.getLocations().get(0);

                if (location != null)
                    Log.d(TAG, "Gps Coords" + location.getLatitude() + "," + location.getLongitude());
            

        );

        turnOnLocationUpdatesBtn.setOnClickListener(view -> locationHelper.startLocationUpdates());

        turnOffLocationBtn.setOnClickListener(view -> locationHelper.startLocationUpdates());

        checkForRequredGpsSettingBtn.setOnClickListener(view -> 

            locationHelper.checkForGpsSettings(new GpsSettingsCheckCallback() 
                @Override
                public void requiredGpsSettingAreUnAvailable(ResolvableApiException status) 

                    Log.d(TAG, "require gps settings upgrade");
                    try 
                        status.startResolutionForResult(CheckGpsActivity.this, REQUEST_LOCATION_SETTINGS_UPGRADE);
                     catch (IntentSender.SendIntentException e) 
                        e.printStackTrace();
                    

                

                @Override
                public void requiredGpsSettingAreAvailable() 
                    Log.d(TAG, "Gps Setting are just fine");
                

                @Override
                public void gpsSettingsNotAvailable() 
                    Log.d(TAG, "Gps Setting unavailable, redirect to settings");
                
            );

        );

    

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) 
        super.onActivityResult(requestCode, resultCode, data);

        //Result code I always get is 0 (RESULT_CANCELED) even if user clicked Ok in Turn On Location dialog
    

【问题讨论】:

你有什么解决方案吗,因为我在小米手机中也遇到了同样的问题。在 onActivityResult() 它总是去 Activity.RESULT_CANCELED 查看我的答案 【参考方案1】:

库本身没有问题,问题出在名为 FusedLocationProvider 的应用程序上,转到设置 -> 安装应用程序 -> FusedLocationProvider -> 清除缓存和数据,现在您的应用程序可以正常工作了。

解决方法#1:您可以选择

    LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY - 位置更新速度更快,但位置准确性可能较低 LocationRequest.PRIORITY_LOW_POWER - 位置更新较慢或可能没有位置更新(如果是室内或地下)

解决方法 #2:将用户重定向到设置页面

 Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
 startActivityForResult(intent, REQUEST_UPDATE_GPS_SETTINGS_MANUALLY);

【讨论】:

以上是关于无法使用 FusedLocationProvider 将 Gps 设置升级到高精度在某些设备中的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 2000无法使用

无法访问您试图使用的功能所在的网络位置

无法使用 StorageClass 配置卷 - 无法获取存储帐户的存储密钥

Worklight Studio 和本地开发,有时无法使用 Java 类,有时无法使用 HTML 文件

ADB无法使用解决办法

Ubuntu 80端口无法使用-非root用户无法使用1024以下端口