I am creating a customised implementation of the MarkerDemo provided for GoogleMaps V2. I have a strange error whereby I am providing LatLng values to a LatLngBounds.Builder instance and then passing it as a variable with .build. When I run the app in Debug mode through Eclipse, the Map loads. When I run it normally through Eclipse, there is an IllegalStateException thrown with "no included points" as a message. Can anyone help?
Here is some code to assist.
public class MyActivity extends android.support.v4.app.FragmentActivity
implements OnMarkerClickListener, OnInfoWindowClickListener,
OnMarkerDragListener {
private HashMap<DataItem, ArrayList<DataItem>> mUserLocations = new
HashMap<DataItem, ArrayList<DataItem>>();
private ArrayList<DataItem> mFeedData;
private NetworkingHandler mHandler = new NetworkingHandler("tag");
private GoogleMap mMap;
private final String DOWNLOAD_USER_LOCATIONS_URL =
"http://www.myfeedurllocation.com/page.php";
@Override
public void onCreate(Bundle savedBundleInstance) {
super.onCreate(savedBundleInstance);
setContentView(R.layout.activity_myactivitylayout);
downloadUserLocations();
setUpMapIfNeeded();
}
@Override
protected void onResume() {
super.onResume();
setUpMapIfNeeded();
}
private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the
// map.
if (mMap == null) {
// Try to obtain the map from the SupportMapFragment.
mMap = ((SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map)).getMap();
// Check if we were successful in obtaining the map.
if (mMap != null) {
setUpMap();
}
}
}
private void setUpMap() {
// Hide the zoom controls as the button panel will cover it.
mMap.getUiSettings().setZoomControlsEnabled(false);
mMap.getUiSettings().setRotateGesturesEnabled(true);
mMap.getUiSettings().setCompassEnabled(true);
// Add lots of markers to the map.
addMarkersToMap();
// Setting an info window adapter allows us to change the both the
// contents and look of the
// info window.
mMap.setInfoWindowAdapter(new CustomInfoWindowAdapter());
// Set listeners for marker events. See the bottom of this class for
// their behavior.
mMap.setOnMarkerClickListener(this);
mMap.setOnInfoWindowClickListener(this);
mMap.setOnMarkerDragListener(this);
// Pan to see all markers in view.
// Cannot zoom to bounds until the map has a size.
final View mapView = getSupportFragmentManager().findFragmentById(
R.id.map).getView();
if (mapView.getViewTreeObserver().isAlive()) {
mapView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
@SuppressLint("NewApi")
// We check which build version we are using.
@Override
public void onGlobalLayout() {
LatLngBounds.Builder bounds = new LatLngBounds.Builder();
for (DataItem location : mUserLocations.keySet()) {
bounds.include(new LatLng(
Double.parseDouble(location.mData
.get("latitude")), Double
.parseDouble(location.mData
.get("longitude"))));
}
mapView.getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(
bounds.build(), 80));
}
});
}
}
private void addMarkersToMap() {
for (DataItem location : mUserLocations.keySet()) {
StringBuilder stringBuilder = new StringBuilder();
for (DataItem user : mUserLocations.get(location)) {
stringBuilder.append("\n" + user.mData.get("textToAdd"));
}
mMap.addMarker(new MarkerOptions()
.position(
new LatLng(Double.parseDouble(location.mData
.get("latitude")), Double
.parseDouble(location.mData.get("longitude"))))
.title(location.mData.get("textToAdd"))
.snippet(stringBuilder.toString())
.icon(
BitmapDescriptorFactory
.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
}
}
private void downloadUserLocations() {
Runnable r = new Runnable() {
@Override
public void run() {
try {
mFeedData = mHandler
.returnDataArrayList(DOWNLOAD_USER_LOCATIONS_URL);
for (DataItem item : mFeedData) {
// create location
DataItem location = new DataItem();
location.mTags.add("locationText1");
location.mTags.add("latitude");
location.mTags.add("longitude");
location.mData.put("locationText1",
item.mData.get("locationText1"));
location.mData.put("latitude",
item.mData.get("latitude"));
location.mData.put("longitude",
item.mData.get("longitude"));
// create user
DataItem user = new DataItem();
user.mTags.add("userText1");
user.mTags.add("userText2");
user.mData
.put("userText1", item.mData.get("userText1"));
user.mData
.put("userText2", item.mData.get("userText2"));
if (mUserLocations.keySet().contains(location)) {
mUserLocations.get(location).add(user);
} else {
mUserLocations.put(location,
new ArrayList<DataItem>());
mUserLocations.get(location).add(user);
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
new Thread(r).start();
}
@Override
public void onMarkerDrag(Marker arg0) {}
@Override
public void onMarkerDragEnd(Marker arg0) {}
@Override
public void onMarkerDragStart(Marker arg0) {}
@Override
public void onInfoWindowClick(Marker arg0) {}
@Override
public boolean onMarkerClick(Marker arg0) {
return false;
}
class CustomInfoWindowAdapter implements InfoWindowAdapter {
private final RadioGroup mOptions;
// These a both viewgroups containing an ImageView with id "badge" and
// two TextViews with id
// "title" and "snippet".
private final View mWindow;
private final View mContents;
CustomInfoWindowAdapter() {
mWindow = getLayoutInflater().inflate(R.layout.custom_info_window,
null);
mContents = getLayoutInflater().inflate(
R.layout.custom_info_contents, null);
mOptions = (RadioGroup) findViewById(R.id.custom_info_window_options);
}
@Override
public View getInfoWindow(Marker marker) {
if (mOptions.getCheckedRadioButtonId() != R.id.custom_info_window) {
// This means that getInfoContents will be called.
return null;
}
render(marker, mWindow);
return mWindow;
}
@Override
public View getInfoContents(Marker marker) {
if (mOptions.getCheckedRadioButtonId() != R.id.custom_info_contents) {
// This means that the default info contents will be used.
return null;
}
render(marker, mContents);
return mContents;
}
private void render(Marker marker, View view) {
int badge = R.drawable.map_pin;
// Use the equals() method on a Marker to check for equals. Do not
// use ==.
((ImageView) view.findViewById(R.id.badge)).setImageResource(badge);
String title = marker.getTitle();
TextView titleUi = ((TextView) view.findViewById(R.id.title));
if (title != null) {
// Spannable string allows us to edit the formatting of the
// text.
SpannableString titleText = new SpannableString(title);
titleText.setSpan(new ForegroundColorSpan(Color.RED), 0,
titleText.length(), 0);
titleUi.setText(titleText);
} else {
titleUi.setText("");
}
String snippet = marker.getSnippet();
TextView snippetUi = ((TextView) view.findViewById(R.id.snippet));
if (snippet != null) {
SpannableString snippetText = new SpannableString(snippet);
snippetText.setSpan(new ForegroundColorSpan(Color.MAGENTA), 0,
10, 0);
snippetText.setSpan(new ForegroundColorSpan(Color.BLUE), 12,
21, 0);
snippetUi.setText(snippetText);
} else {
snippetUi.setText("");
}
}
}
}
Here is my stack trace.
02-14 15:23:50.219: E/AndroidRuntime(8952): FATAL EXCEPTION: main
02-14 15:23:50.219: E/AndroidRuntime(8952): java.lang.IllegalStateException: no included points
02-14 15:23:50.219: E/AndroidRuntime(8952): at com.google.android.gms.internal.at.a(Unknown Source)
02-14 15:23:50.219: E/AndroidRuntime(8952): at com.google.android.gms.maps.model.LatLngBounds$Builder.build(Unknown Source)
02-14 15:23:50.219: E/AndroidRuntime(8952): at com.mypackage.MyActivity$1.onGlobalLayout(MyActivity.java:109)
02-14 15:23:50.219: E/AndroidRuntime(8952): at android.view.ViewTreeObserver.dispatchOnGlobalLayout(ViewTreeObserver.java:682)
02-14 15:23:50.219: E/AndroidRuntime(8952): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1850)
02-14 15:23:50.219: E/AndroidRuntime(8952): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1112)
02-14 15:23:50.219: E/AndroidRuntime(8952): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4472)
02-14 15:23:50.219: E/AndroidRuntime(8952): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
02-14 15:23:50.219: E/AndroidRuntime(8952): at android.view.Choreographer.doCallbacks(Choreographer.java:555)
02-14 15:23:50.219: E/AndroidRuntime(8952): at android.view.Choreographer.doFrame(Choreographer.java:525)
02-14 15:23:50.219: E/AndroidRuntime(8952): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
02-14 15:23:50.219: E/AndroidRuntime(8952): at android.os.Handler.handleCallback(Handler.java:615)
02-14 15:23:50.219: E/AndroidRuntime(8952): at android.os.Handler.dispatchMessage(Handler.java:92)
02-14 15:23:50.219: E/AndroidRuntime(8952): at android.os.Looper.loop(Looper.java:137)
02-14 15:23:50.219: E/AndroidRuntime(8952): at android.app.ActivityThread.main(ActivityThread.java:4898)
02-14 15:23:50.219: E/AndroidRuntime(8952): at java.lang.reflect.Method.invokeNative(Native Method)
02-14 15:23:50.219: E/AndroidRuntime(8952): at java.lang.reflect.Method.invoke(Method.java:511)
02-14 15:23:50.219: E/AndroidRuntime(8952): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
02-14 15:23:50.219: E/AndroidRuntime(8952): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
02-14 15:23:50.219: E/AndroidRuntime(8952): at dalvik.system.NativeStart.main(Native Method)
Don't bother with the builder just do.
I get the same error.
In the Api, it is explained this:
With the following code, the exception is launched when the list to compute the bounds is empty: