空对象引用上的虚拟方法 'double android.location.Location.getLatitude()'

virtual method 'double android.location.Location.getLatitude()' on a null object reference

我正在 Activity 中调用 GeoLocationHelper Class 来获取当前位置更新。我正在尝试获取 ParseGeoPoint 的纬度和经度。

这是我的GeoLocationHelper.class

/**
 * Helper class for retrieving location from multiple providers and determining
 * the current
 * location.
 */
public class GeoLocationHelper {
    private Context mContext;

    public GeoLocationHelper(Context context){
        mContext = context;
    }
    /**
     * Two minutes in milliseconds.
     */
    private static final int TWO_MINUTES_IN_MILLISECONDS = 1000 * 60 * 2;

    /**
     * The location accuracy in meters that remains acceptable.
     */
    private static final int LOCATION_ACCURACY = 200;

    /**
     * The refresh rate for the location provider, in milliseconds.
     */
    private static final long LOCATION_PROVIDER_UPDATE_RATE = 5000;

    /**
     * The distance delta after which the location provider should send a
     * new location.
     */
    private static final float LOCATION_PROVIDER_UPDATE_DISTANCE = 100;

    /**
     * Log output.
     */
    private Logger log = Logger.getLogger(GeoLocationHelper.class.getName());

    /**
     * The current best known location for the user.
     */
    private Location currentBestLocation = null;

    /**
     * Listener that responds to location updates.
     */
    private LocationListener locationListener = new LocationListener() {
        @Override
        public void onLocationChanged(final Location location) {
            // Called when a new location is found by a location provider.
            if (isBetterLocation(location)) {
                currentBestLocation = location;
            }
        }

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

        @Override
        public void onProviderEnabled(final String provider) {
        }

        @Override
        public void onProviderDisabled(final String provider) {
        }
    };

    /**
     * The location manager to retrieve the user location.
     */
    private LocationManager locationManager;

    /**
     * Determines whether a new location is "better" that then current best
     * location, taking into account when the location was retrieved and its
     * accuracy.
     * @param location a candidate location
     * @return boolean indicating whether the new location is better than the
     * * current best one or not
     */
    private boolean isBetterLocation(final Location location) {
        if (location == null) {
            return false;
        }

        if (currentBestLocation == null) {
            // A new location is always better than no location
            return true;
        }

        // Check whether the new location fix is newer or older
        long timeDelta = location.getTime() - currentBestLocation.getTime();
        boolean isNewer = timeDelta > 0;

        // If the current location fix has been taken more than two minutes
        // prior to the new location fix then use the new location because
        // the user has likely moved.
        if (timeDelta > TWO_MINUTES_IN_MILLISECONDS) {
            return true;
        }

        // If the "new" location fix is more than two minutes older, we assume
        // it is worse
        if (timeDelta < -TWO_MINUTES_IN_MILLISECONDS) {
            return false;
        }

        // Check whether the new location fix is more or less accurate
        // The accuracy returned by Location.getAccuracy() is expressed in
        // meters and the lower the value the more accurate the location is.
        int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation
                .getAccuracy());
        boolean isMoreAccurate = accuracyDelta < 0;
        boolean isEquallyAccurate = accuracyDelta == 0;
        boolean isSlightlyLessAccurate = (accuracyDelta > 0) && (accuracyDelta
                <= LOCATION_ACCURACY);

        // Check if the old and new location are from the same provider
        boolean isFromSameProvider =
                isSameProvider(location.getProvider(),
                        currentBestLocation.getProvider());

        // Determine location quality using a combination of timeliness and
        // accuracy
        return (isMoreAccurate
                || (isNewer && (isEquallyAccurate || (isFromSameProvider
                && isSlightlyLessAccurate))));
    }

    /**
     * *
     * @param provider1 the first provider
     * @param provider2 the second provider
     * @return bollean indicating whether two providers are the same
     */
    private boolean isSameProvider(final String provider1,
                                   final String provider2) {
        if (provider1 == null) {
            return provider2 == null;
        }
        return provider1.equals(provider2);
    }

    /**
     * Starts retrieving location updates.
     *
     * @param context Activity context
     */
    public void startRetrievingLocation(final Context context) {
        // Acquire a reference to the system Location Manager
        locationManager = (LocationManager) context
                .getSystemService(Context.LOCATION_SERVICE);

        try {
            currentBestLocation = locationManager
                    .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

            Location gpsLocation = locationManager
                    .getLastKnownLocation(LocationManager.GPS_PROVIDER);
            if (isBetterLocation(gpsLocation)) {
                currentBestLocation = gpsLocation;
            }
        } catch (SecurityException e) {
            log.warning(
                    "SecurityException when retrieving the last known "
                            + "location: "
                            + e.getMessage());
        } catch (IllegalArgumentException e) {
            log.warning(
                    "IllegalArgumentException when retrieving the last known "
                            + "location: "
                            + e
                            .getMessage());
        }

        // Register the listener with the Location Manager to receive
        // location updates as often as every 5 seconds and every 100 meters
        if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        locationManager.requestLocationUpdates(
                LocationManager.GPS_PROVIDER, LOCATION_PROVIDER_UPDATE_RATE,
                LOCATION_PROVIDER_UPDATE_DISTANCE, locationListener);
        locationManager.requestLocationUpdates(
                LocationManager.NETWORK_PROVIDER,
                LOCATION_PROVIDER_UPDATE_RATE,
                LOCATION_PROVIDER_UPDATE_DISTANCE, locationListener);
    }

    /**
     * Stops retrieving location updates.
     */
    public void stopRetrievingLocation() {
        if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        locationManager.removeUpdates(locationListener);
    }

    /**
     * Returns the current location.
     * @return the current location
     */
    public Location getCurrentLocation() {
        return currentBestLocation;
    }
}

这是我的 Activity class 调用 GeoLocationHelper

  private GeoLocationHelper geoLocationHelper = new GeoLocationHelper(this);

   /**
     * Stops retrieving geo-location updates when the activity is no longer
     * visible.
     */
    @Override
    protected final void onStop() {
        super.onStop();
        geoLocationHelper.stopRetrievingLocation();
    }

    /**
     * Resumes retrieving geo-location updates when the activity is restarted.
     */
    @Override
    protected final void onRestart() {
        super.onRestart();
        geoLocationHelper.startRetrievingLocation(this);
    }

        private ParseGeoPoint geoPointFromLocation(Location loc) {
            return new ParseGeoPoint(loc.getLatitude(), loc.getLongitude());
        }



        private void setupPhotoFilters() {
            FiltersQueryAdapter mainAdapter = new FiltersQueryAdapter(this, PhotoFiltersAdapter.class
                    ,new ParseRecyclerQueryAdapter.QueryFactory() {
                public ParseQuery create() {
                    Location myLoc = geoLocationHelper.getCurrentLocation();
                    ParseQuery query = ParseQuery.getQuery("Places");
                    //query.include("user");
                    query.orderByAscending("GeoArea");
                    query.whereWithinKilometers("GeoArea", geoPointFromLocation(myLoc), radius);
                    query.setLimit(6);
                    return query;
                }
            });

这是Logcat

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'double android.location.Location.getLatitude()' on a null object reference
                                                       at com.google.peep.activity.TakePhotoActivity.geoPointFromLocation(TakePhotoActivity.java:151)
                                                       at com.google.peep.activity.TakePhotoActivity.access0(TakePhotoActivity.java:54)
                                                       at com.google.peep.activity.TakePhotoActivity.create(TakePhotoActivity.java:163)
                                                       at com.javon.parserecyclerviewadapter.ParseRecyclerQueryAdapter.loadParseData(ParseRecyclerQueryAdapter.java:96)
                                                       at com.javon.parserecyclerviewadapter.ParseRecyclerQueryAdapter.registerAdapterDataObserver(ParseRecyclerQueryAdapter.java:176)
                                                       at android.support.v7.widget.RecyclerView.setAdapterInternal(RecyclerView.java:886)
                                                       at android.support.v7.widget.RecyclerView.setAdapter(RecyclerView.java:847)
                                                       at com.google.peep.activity.TakePhotoActivity.setupPhotoFilters(TakePhotoActivity.java:169)
                                                       at com.google.peep.activity.TakePhotoActivity.onCreate(TakePhotoActivity.java:107)
                                                       at android.app.Activity.performCreate(Activity.java:5958)
                                                       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1129)
                                                       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)
                                                       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2474) 
                                                       at android.app.ActivityThread.access0(ActivityThread.java:144) 
                                                       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1359) 
                                                       at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                       at android.os.Looper.loop(Looper.java:155) 
                                                       at android.app.ActivityThread.main(ActivityThread.java:5696) 
                                                       at java.lang.reflect.Method.invoke(Native Method) 
                                                       at java.lang.reflect.Method.invoke(Method.java:372) 
                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028) 
                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)

GeoLocationHelper 中的当前位置初始化为 null,您似乎没有开始侦听位置更新。这就是为什么您调用 geoLocationHelper.getCurrentLocation(); returns null.

的结果

根据您提供的代码显示,您应该先调用 geoLocationHelper.startRetrievingLocation(),然后再调用 geoLocationHelper.getCurrentLocation();

当您不再需要位置更新时,请不要忘记取消注册以避免泄露您的上下文。