在对话框中启用GPS后,Android位置返回null

时间:2016-05-31 23:48:39

标签: java android gps geolocation android-6.0-marshmallow

当我进入屏幕时,我会检查GPS是否已打开,如果没有,则会显示启用GPS的对话框。当用户单击是时,onActivityResult - > GPS已打开,我尝试获取该位置,但这始终返回null

当我进入已启用GPS的屏幕时,将正确检索位置。我几天来一直在努力解决这个问题,似乎无法找到任何资源。

UserLocationUtilities.java

public class UserLocationUtilities implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener{

    GoogleApiClient googleApiClient;
    Activity activity;
    protected static final int REQUEST_CHECK_SETTINGS = 0x1;

    boolean isGPSEnabled = false;
    // flag for network status
    boolean isNetworkEnabled = false;
    // flag for GPS status
    boolean canGetLocation = false;

    protected LocationManager locationManager;
    protected LocationListener locationListener;
    protected Location location;
    protected double latitude,longitude;
    protected boolean gps_enabled,network_enabled;

    // The minimum distance to change Updates in meters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters
    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 1 * 1000 * 60; // 1 minute

    public UserLocationUtilities(Activity activity){
        this.activity = activity;
    }

    public void settingsRequest()
    {
        if(googleApiClient == null){
            googleApiClient = new GoogleApiClient.Builder(activity)
                    .addApi(LocationServices.API)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this).build();
            googleApiClient.connect();
        }

        LocationRequest locationRequest = LocationRequest.create();
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setInterval(30 * 1000);
        locationRequest.setFastestInterval(5 * 1000);
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                .addLocationRequest(locationRequest);
        builder.setAlwaysShow(true); //this is the key ingredient

        PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
        result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
            @Override
            public void onResult(LocationSettingsResult result) {
                final Status status = result.getStatus();
                final LocationSettingsStates state = result.getLocationSettingsStates();
                switch (status.getStatusCode()) {
                    case LocationSettingsStatusCodes.SUCCESS:
                        // All location settings are satisfied. The client can initialize location
                        // requests here.

                        break;
                    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                        // Location settings are not satisfied. But could be fixed by showing the user
                        // a dialog.
                        try {
                            // Show the dialog by calling startResolutionForResult(),
                            // and check the result in onActivityResult().
                            status.startResolutionForResult(activity, REQUEST_CHECK_SETTINGS);
                        } catch (IntentSender.SendIntentException e) {
                            // Ignore the error.
                        }
                        break;
                    case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                        // Location settings are not satisfied. However, we have no way to fix the
                        // settings so we won't show the dialog.
                        break;
                }
            }
        });
    }

    public Location getLocation() {
        if (ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            try {
                locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);

                isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
                isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

                if (!isGPSEnabled && !isNetworkEnabled) {
                    // no network provider is enabled
                } else {
                    this.canGetLocation = true;
                    if (isNetworkEnabled) {
                        locationManager.requestLocationUpdates(
                                LocationManager.NETWORK_PROVIDER,
                                MIN_TIME_BW_UPDATES,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                        Log.d("Network", "Network");
                        if (locationManager != null) {
                            location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                            if (location != null) {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                            }
                        }
                    }
                    // if GPS Enabled get lat/long using GPS Services
                    if (isGPSEnabled) {
                        if (location == null) {
                            locationManager.requestLocationUpdates(
                                    LocationManager.GPS_PROVIDER,
                                    MIN_TIME_BW_UPDATES,
                                    MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                            Log.d("GPS Enabled", "GPS Enabled");
                            if (locationManager != null) {
                                location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                                if (location != null) {
                                    latitude = location.getLatitude();
                                    longitude = location.getLongitude();
                                }
                            }
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return location;
    }

    public boolean isLocationEnabled() {
        int locationMode = 0;
        String locationProviders;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
            try {
                locationMode = Settings.Secure.getInt(activity.getApplicationContext().getContentResolver(), Settings.Secure.LOCATION_MODE);

            } catch (Settings.SettingNotFoundException e) {
                e.printStackTrace();
            }

            return locationMode != Settings.Secure.LOCATION_MODE_OFF;

        }else{
            locationProviders = Settings.Secure.getString(activity.getApplicationContext().getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
            return !TextUtils.isEmpty(locationProviders);
        }


    }

    @Override
    public void onConnected(Bundle bundle) {


    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {

    }

    @Override
    public void onLocationChanged(Location location) {

    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {

    }

    @Override
    public void onProviderEnabled(String provider) {

    }

    @Override
    public void onProviderDisabled(String provider) {

    }
}

用户在设置对话框,onActivityResult中选择是后,我执行location = userlocationutilities.getLocation();并始终返回null。如果切换屏幕并返回,则检索位置。

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
// Check for the integer request code originally supplied to startResolutionForResult().
            case REQUEST_CHECK_SETTINGS:
                switch (resultCode) {
                    case Activity.RESULT_OK: //location settings dialog, user selected YES to enabling location

                        location = userLocationUtilities.getLocation();
                        if(location != null){
                            //location of user FOUND
                            Toast.makeText(getActivity(), "Lat: "+location.getLatitude()+" Long: "+location.getLongitude(), Toast.LENGTH_LONG).show();
                            getRingsNearMeCall();

                        }else{
                            //location of user NOT FOUND
                            Toast.makeText(getActivity(), "null location", Toast.LENGTH_LONG).show();

                        }

                        break;
                    case Activity.RESULT_CANCELED: //location settings dialog, user selected NO to enabling location
                        userLocationUtilities.settingsRequest(); //ask user again with Location Settings Dialog
                        break;
                }
                break;
        }
    }

编辑:我在片段中创建requestPermission,授予权限

if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(getActivity(), new String[] { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION },
                    PERMISSION_ACCESS_FINE_LOCATION);
        }else{
            checkLocationSettingsGetRings();
        }

3 个答案:

答案 0 :(得分:0)

最后,我找到了一个解决方案: 我创建一个线程并等待我的位置可用。

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode){
        case REQUEST_LOCATION:
            switch (resultCode){
                case Activity.RESULT_OK:
                    mHandler = new Handler();
                    runnable = new Runnable() {
                        @Override
                        public void run() {
                            mHandler.postDelayed(this,1000);
                            checkLocationAvailable();
                        }
                    };
                    mHandler.postDelayed(runnable,1000);
                    break;
                case Activity.RESULT_CANCELED:
                    break;
            }
    }
}

创建一个函数,在我的位置可用时停止线程。

private void checkLocationAvailable(){
  if (mMap.getMyLocation() != null) {
  mHandler.removeCallbacks(runnable);
  // do stuff
  }
}

这不是一个好的解决方案,但希望它会有所帮助。

答案 1 :(得分:0)

为我添加此覆盖方法,其工作正常 -

@Override public void onLocationChanged(Location location) { getLocation("onLocationChanged"); }

答案 2 :(得分:-1)

使用LocationSettingsRequest只需使位置设置充足,例如您希望获得更准确(HIGH_ACCURACY)的位置,然后您需要启用GPS。因此,在这种情况下,LocationSettingsRequest会提示对话框以允许api更改设置。

按OK后,您可以看到GPS已启用。但这并不意味着您已获准提出位置请求。

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case REQUEST_CHECK_SETTINGS:
            switch (resultCode) {
                case Activity.RESULT_OK:
                // Here means required settings are adequate.
                // We can make location request.
                // But are we granted to use request location updates ?
                break;
            }
            break;
        }
    }
}

多数好,但是您正在检查权限,但您从未进行过 requestPermissions 。这是获得null的第一个可能原因。

public Location getLocation() {
    if (ContextCompat.checkSelfPermission(activity, 
        Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
        ...
    }
    return location;
}

甚至您之前已获准进行位置请求

  location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
  location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

getLastKnownLocation()方法可能返回null,这不是意外行为。这是获得null的第二个可能原因

您正在发出位置请求,但在onLocationChanged回调中永远不会分配全局位置变量。

 @Override
public void onLocationChanged(Location location) {
    // global location variable is not assigned ?
    // getLocation() method will return null if getLastKnownLocation()
    // did not return null previously. 
}

这是获得null的第三个可能原因。