Google地图对象在旧设备上显示NPE

时间:2014-07-30 06:55:15

标签: java android eclipse google-maps google-maps-api-2

我正在使用这段代码初始化google地图对象:

googleMap = ( (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();

它适用于较新的设备,但在较旧的设备上显示 NPE 。请帮助!!

1 个答案:

答案 0 :(得分:0)

这就是我解决谷歌地图的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();
    }
}

}

旧答案: 我也遇到了这个问题。你应该只在onResume拨打这个电话!因为在此之前地图可能尚未准备好

您还应该致电

MapsInitializer.initialize(getActivity().getApplicationContext());

GooglePlayUtils.isGooglePlayServicesAvailable(context) 在调用地图之前