Java 在旧设备上显示NPE的Google地图对象
我正在使用这段代码初始化google map对象:Java 在旧设备上显示NPE的Google地图对象,java,android,eclipse,google-maps,google-maps-api-2,Java,Android,Eclipse,Google Maps,Google Maps Api 2,我正在使用这段代码初始化google map对象: googleMap = ( (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap(); 它在较新的设备上工作正常,但在较旧的设备上显示NPE。请帮助 这就是我解决谷歌地图NPE的方法 public class WBMapFragment extends LogoBaseFragment implements GooglePlayS
googleMap = ( (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
它在较新的设备上工作正常,但在较旧的设备上显示NPE。请帮助 这就是我解决谷歌地图NPE的方法
public class WBMapFragment extends LogoBaseFragment implements GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener {
private GoogleMap map;
private MapView mapView;
@Inject
private MapManager mapManager;
/*
* Define a request code to send to Google Play services This code is
* returned in Activity.onActivityResult
*/
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
private LocationClient mLocationClient;
@Inject
private IUserLocationProvider userLocation;
private BitmapDescriptor mapPin;
private BitmapDescriptor mapPinUsed;
private SupportMapFragment supportMapFragment;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true); //< -- very important line
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//I needed this for when I return to the fragment that contained the map
getChildFragmentManager().putFragment(outState, "supportFragment", supportMapFragment);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_map, null);
if (savedInstanceState == null) {
if (supportMapFragment == null) {
supportMapFragment = SupportMapFragment.newInstance();
getChildFragmentManager().beginTransaction().add(R.id.mapCont, supportMapFragment,SupportMapFragment.class.getSimpleName()).commit();
}
}
return v;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState !=null){
supportMapFragment = (SupportMapFragment) getChildFragmentManager().getFragment(savedInstanceState, "supportFragment");
map = null; //<very important to nullify the map, because the new instance of the map will not be the same
}
mLocationClient = new LocationClient(getActivity(), this, this);
}
/*
* Called when the Activity becomes visible.
*/
@Override
public void onStart() {
super.onStart();
// Connect the client.
if (isGooglePlayServicesAvailable()) {
mLocationClient.connect();
initMap();
}
}
public void initMap() {
if (map == null) {
map = (GoogleMap) supportMapFragment.getMap();
if (map == null) {
//this call is made several times, and on first tried map can be null
return;
}
}
map.getUiSettings().setCompassEnabled(false);
map.getUiSettings().setZoomControlsEnabled(false);
map.setOnMyLocationChangeListener(new OnMyLocationChangeListener() {
@Override
public void onMyLocationChange(Location location) {
if (location != null) {
userLocation.saveLocation(location);
}
}
});
}
@Override
public void onResume() {
super.onResume();
initMap();
updateAnnotations();
}
/*
* Called when the Activity is no longer visible.
*/
@Override
public void onStop() {
// Disconnecting the client invalidates it.
mLocationClient.disconnect();
super.onStop();
}
/*
* Handle results returned to the FragmentActivity by Google Play services
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// Decide what to do based on the original request code
switch (requestCode) {
case CONNECTION_FAILURE_RESOLUTION_REQUEST:
/*
* If the result code is Activity.RESULT_OK, try to connect again
*/
switch (resultCode) {
case Activity.RESULT_OK:
mLocationClient.connect();
break;
}
}
}
private boolean isGooglePlayServicesAvailable() {
// Check that Google Play services is available
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity());
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
// In debug mode, log the status
Log.d("Location Updates", "Google Play services is available.");
MapsInitializer.initialize(getActivity().getApplicationContext());
mapPin = BitmapDescriptorFactory.fromResource(R.drawable.envelope);
mapPinUsed = BitmapDescriptorFactory.fromResource(R.drawable.envelope_open);
return true;
} else {
//here google suggests to display an error dialog, but i found that this only cause problems , better show a toast instead
// Get the error dialog from Google Play services
// Dialog errorDialog =
// GooglePlayServicesUtil.getErrorDialog(resultCode, getActivity(),
// CONNECTION_FAILURE_RESOLUTION_REQUEST);
// If Google Play services can provide an error dialog
// if (errorDialog != null) {
// Create a new DialogFragment for the error dialog
// ErrorDialogFragment errorFragment = new ErrorDialogFragment();
// errorFragment.setDialog(errorDialog);
// errorFragment.show(getActivity().getSupportFragmentManager(),
// "Location Updates");
// }
return false;
}
}
/*
* Called by Location Services when the request to connect the client
* finishes successfully. At this point, you can request the current
* location or start periodic updates
*/
@Override
public void onConnected(Bundle dataBundle) {
// Display the connection status
Location location = mLocationClient.getLastLocation();
if (location != null) {
updateAnnotations();
} else {
// makeText( "Current location was null, enable GPS on emulator!",
// Toast.LENGTH_SHORT);
}
}
private Marker addMarker(GoogleMap map, double lat, double lon, String title, String snippet, boolean isWon) {
MarkerOptions options = new MarkerOptions().position(new LatLng(lat, lon)).title(title).snippet(snippet);
if (isWon) {
options.icon(mapPinUsed);
} else {
options.icon(mapPin);
}
Marker marker = map.addMarker(options);
return marker;
}
private void addMarkerToMap(GoogleMap map, WBMarker beacon) {
addMarker(map, beacon.location.Lat, beacon.location.Lng, beacon.name, beacon.address, beacon.isWon);
}
private void updateAnnotations() {
mapManager.getBeaconData(new IBeaconDataReceivedListener() {
@Override
public void onBeaconDataReceived(List<WBMarker> data) {
if (data.size() > 0) {
map.clear();
}
Location loc = userLocation.getLocation();
LatLng userTarget = new LatLng(loc.getLatitude(), loc.getLongitude());
LatLngBounds.Builder builder = new LatLngBounds.Builder();
List<WBMarker> ret = closeAnnotations(data);
for (WBMarker beacon : data) {
addMarkerToMap(map, beacon);
}
builder.include(userTarget);
CameraUpdate update;
if (ret.size() == 0) {
update = CameraUpdateFactory.newCameraPosition(new CameraPosition(userTarget, 17, 0, loc.getBearing()));
} else {
for (WBMarker beacon : ret) {
builder.include(new LatLng(beacon.location.Lat, beacon.location.Lng));
}
update = CameraUpdateFactory.newLatLngBounds(builder.build(), 50);
}
map.animateCamera(update);
}
});
}
private List<WBMarker> closeAnnotations(List<WBMarker> data) {
Location userLoc = userLocation.getLocation();
List<WBMarker> ret = new ArrayList<WBMarker>();
for (WBMarker beacon : data) {
Location loc = beacon.location.getLocation();
float dist = loc.distanceTo(userLoc);
if (dist < 50000.0f) {
ret.add(beacon);
}
}
return ret;
}
/*
* Called by Location Services if the connection to the location client
* drops because of an error.
*/
@Override
public void onDisconnected() {
// Display the connection status
Toast.makeText(getActivity(),"Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
}
/*
* Called by Location Services if the attempt to Location Services fails.
*/
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
/*
* Google Play services can resolve some errors it detects. If the error
* has a resolution, try sending an Intent to start a Google Play
* services activity that can resolve error.
*/
if (connectionResult.hasResolution()) {
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(getActivity(), CONNECTION_FAILURE_RESOLUTION_REQUEST);
/*
* Thrown if Google Play services canceled the original
* PendingIntent
*/
} catch (IntentSender.SendIntentException e) {
// Log the error
e.printStackTrace();
}
} else {
Toast.makeText(getActivity(), "Sorry. Location services not available to you", Toast.LENGTH_LONG).show();
}
}
及
GooglePlayUtils.isGooglePlayServicesAvailable(上下文)
在调用映射之前,NPE是否发生在这一行,或者当您尝试使用
googleMap
时?是的,NPE发生在上面一行,而不是使用googleMap。标准过程:分解复合语句,以便您可以识别空值。空值是googleMap对象。这与您之前的语句相矛盾。如果googleMap
为空,那么可能的解释将在SupportMapFragment
的文档中清楚解释。您如何将support map fragment添加到应用程序中?通过xml?是的,我将它添加为xml中的一个片段,属性为:android:name=“com.google.android.gms.maps.SupportMapFragment”你看,这也是我的问题。Android文档警告添加嵌入XML的片段,它们会导致很多问题。在过去的几天里,我所做的就是想办法解决它。我将向您发布我的解决方案。如果这是一个问题,那么它不应该是所有设备上的问题吗?该应用程序在较新的设备上运行良好,但在较旧的设备上运行不正常。这看起来需要对我的代码进行很多更改。是否有更简单的方法使我不会在我的google map对象上获得NPE。
MapsInitializer.initialize(getActivity().getApplicationContext());