空对象引用上的虚拟方法 '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();
。
当您不再需要位置更新时,请不要忘记取消注册以避免泄露您的上下文。
我正在 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();
。
当您不再需要位置更新时,请不要忘记取消注册以避免泄露您的上下文。