I'm working on integrating Google Maps into the app I'm working on and I've had a rather unpleasant time doing it thus far. Regardless, I finally got a SupportMapFragment displaying a map and set a location and zoom level.
Here is the functional bits of my code thus far:
@Override
public void onActivityCreated( Bundle savedInstanceState ) {
super.onActivityCreated( savedInstanceState );
Location location = BundleChecker.getExtraOrThrow( KEY_LOCATION, new Bundle[] { savedInstanceState, getArguments() } );
setLocation( location );
if ( checkGooglePlayServicesStatus() == ConnectionResult.SUCCESS ) {
setMapFragment( new SupportMapFragment() );
getActivity().getSupportFragmentManager().beginTransaction().add( R.id.location_detail_mapFrame, getMapFragment() ).commit();
}
populateAddress();
attachButtonListeners();
Runnable initMap = new Runnable() {
@Override
public void run() {
if ( checkGooglePlayServicesStatus() == ConnectionResult.SUCCESS ) {
try {
GoogleMap map = getMapFragment().getMap();
LatLng latLng = getLocation().getAddress().getLatLng( getActivity() );
CameraUpdate update = CameraUpdateFactory.newLatLngZoom( latLng, DEFAULT_MAP_ZOOM );
map.animateCamera( update );
}
catch (IOException e) {
Log.e( TAG, e.getMessage(), e );
Toast.makeText( getActivity(), "Unable to find location", Toast.LENGTH_SHORT ).show();
}
}
}
};
Handler handler = new Handler();
handler.postDelayed( initMap, 200 );
}
Also, I wrote a simple convenience method to get a LatLng from my Address model that you may criticize as well:
/*
* Convenience method to easily check if there is a valid lat & lng in this address
*/
public boolean hasLatLng() {
return getLatitude() != null && getLongitude() != null;
}
/*
* Convenience method for use with Google Maps API
*/
public LatLng getLatLng( Context context ) throws IOException {
LatLng latLng = null;
if ( hasLatLng() ) {
latLng = new LatLng( getLatitude(), getLongitude() );
}
else {
String locationString = getStreet() + ", " + AddressUtil.makeCityStateZipString( this );
Geocoder geoCoder = new Geocoder( context );
try {
List<android.location.Address> matches = geoCoder.getFromLocationName( locationString, 2 );
if ( matches != null && matches.size() > 0 ) {
double lat = matches.get( 0 ).getLatitude();
double lng = matches.get( 0 ).getLongitude();
latLng = new LatLng( lat, lng );
}
}
catch (IOException e) {
throw new IOException( e );
}
}
return latLng;
}
I'm aware that this code is not ideal and needs to be refactored. This is my first time working with Google Maps so please feel free to offer suggestions as to how I might do that as well. I experienced a lot of problems when trying to use the MapFragment as a in my layout XML, so I'm creating it programmatically.
The heart of the matter: I was getting some bogus address data from the staging server and this resulted in the Address#getLatLng method returning null which caused an exception when calling CameraUpdateFactory.newLatLngZoom. After I got this exception, I was no longer able to get map data from Google. The map fragment is blank now and messages are displayed in logcat:
05-21 18:11:42.903: I/Google Maps Android API(15747): Failed to contact Google servers. Another attempt will be made when connectivity is established.
05-21 18:11:43.093: E/Google Maps Android API(15747): Failed to load map. Error contacting Google servers. This is probably an authentication issue (but could be due to network errors).
I have created a new api key and replaced the current one in my manifest with no change. The only changes I had made to the above code were to account for a null LatLng and I have since undone those changes in a pointless attempt to get my code back to a functional state.
Additionally, to make things a bit stranger, I built the sample maps project that is included with the Google Play Services Extras and it works perfectly (has a separate API key, btw).
What might I have done wrong here? Am I overlooking something obvious?