diff --git a/library/src/main/java/com/google/maps/android/data/kml/KmlLayer.java b/library/src/main/java/com/google/maps/android/data/kml/KmlLayer.java index d8b87faf8..d76f45481 100644 --- a/library/src/main/java/com/google/maps/android/data/kml/KmlLayer.java +++ b/library/src/main/java/com/google/maps/android/data/kml/KmlLayer.java @@ -47,9 +47,12 @@ */ public class KmlLayer extends Layer { + private static final int DEFAULT_MAX_KMZ_ENTRY_COUNT = 200; + private static final long DEFAULT_MAX_KMZ_UNCOMPRESSED_TOTAL_SIZE = 50 * 1024 * 1024; // 50MB + /** * Creates a new KmlLayer object - addLayerToMap() must be called to trigger rendering onto a map. - * + *
* Constructor may be called on a background thread, as I/O and parsing may be long-running. * * @param map GoogleMap object @@ -60,12 +63,30 @@ public class KmlLayer extends Layer { */ public KmlLayer(GoogleMap map, int resourceId, Context context) throws XmlPullParserException, IOException { - this(map, context.getResources().openRawResource(resourceId), context, new MarkerManager(map), new PolygonManager(map), new PolylineManager(map), new GroundOverlayManager(map), null, null); + this(map, context.getResources().openRawResource(resourceId), context, new MarkerManager(map), new PolygonManager(map), new PolylineManager(map), new GroundOverlayManager(map), null, null, DEFAULT_MAX_KMZ_ENTRY_COUNT, DEFAULT_MAX_KMZ_UNCOMPRESSED_TOTAL_SIZE); } /** * Creates a new KmlLayer object - addLayerToMap() must be called to trigger rendering onto a map. + *
+ * Constructor may be called on a background thread, as I/O and parsing may be long-running. * + * @param map GoogleMap object + * @param resourceId Raw resource KML or KMZ file + * @param context The Context + * @param maxKmzEntryCount The maximum number of entries a KMZ file can contain. + * @param maxKmzUncompressedTotalSize The maximum size of the uncompressed KMZ file in bytes. + * @throws XmlPullParserException if file cannot be parsed + * @throws IOException if I/O error + */ + public KmlLayer(GoogleMap map, int resourceId, Context context, int maxKmzEntryCount, long maxKmzUncompressedTotalSize) + throws XmlPullParserException, IOException { + this(map, context.getResources().openRawResource(resourceId), context, new MarkerManager(map), new PolygonManager(map), new PolylineManager(map), new GroundOverlayManager(map), null, null, maxKmzEntryCount, maxKmzUncompressedTotalSize); + } + + /** + * Creates a new KmlLayer object - addLayerToMap() must be called to trigger rendering onto a map. + *
* Constructor may be called on a background thread, as I/O and parsing may be long-running. * * @param map GoogleMap object @@ -76,14 +97,32 @@ public KmlLayer(GoogleMap map, int resourceId, Context context) */ public KmlLayer(GoogleMap map, InputStream stream, Context context) throws XmlPullParserException, IOException { - this(map, stream, context, new MarkerManager(map), new PolygonManager(map), new PolylineManager(map), new GroundOverlayManager(map), null, null); + this(map, stream, context, new MarkerManager(map), new PolygonManager(map), new PolylineManager(map), new GroundOverlayManager(map), null, null, DEFAULT_MAX_KMZ_ENTRY_COUNT, DEFAULT_MAX_KMZ_UNCOMPRESSED_TOTAL_SIZE); } /** * Creates a new KmlLayer object - addLayerToMap() must be called to trigger rendering onto a map. - * + *
* Constructor may be called on a background thread, as I/O and parsing may be long-running. * + * @param map GoogleMap object + * @param stream InputStream containing KML or KMZ file + * @param context The Context + * @param maxKmzEntryCount The maximum number of entries a KMZ file can contain. + * @param maxKmzUncompressedTotalSize The maximum size of the uncompressed KMZ file in bytes. + * @throws XmlPullParserException if file cannot be parsed + * @throws IOException if I/O error + */ + public KmlLayer(GoogleMap map, InputStream stream, Context context, int maxKmzEntryCount, long maxKmzUncompressedTotalSize) + throws XmlPullParserException, IOException { + this(map, stream, context, new MarkerManager(map), new PolygonManager(map), new PolylineManager(map), new GroundOverlayManager(map), null, null, maxKmzEntryCount, maxKmzUncompressedTotalSize); + } + + /** + * Creates a new KmlLayer object - addLayerToMap() must be called to trigger rendering onto a map. + *
+ * Constructor may be called on a background thread, as I/O and parsing may be long-running. + *
* Use this constructor with shared object managers in order to handle multiple layers with * their own event handlers on the map. * @@ -107,14 +146,49 @@ public KmlLayer(GoogleMap map, GroundOverlayManager groundOverlayManager, Renderer.ImagesCache cache) throws XmlPullParserException, IOException { - this(map, context.getResources().openRawResource(resourceId), context, markerManager, polygonManager, polylineManager, groundOverlayManager, cache, null); + this(map, context.getResources().openRawResource(resourceId), context, markerManager, polygonManager, polylineManager, groundOverlayManager, cache, null, DEFAULT_MAX_KMZ_ENTRY_COUNT, DEFAULT_MAX_KMZ_UNCOMPRESSED_TOTAL_SIZE); } /** * Creates a new KmlLayer object - addLayerToMap() must be called to trigger rendering onto a map. - * + *
* Constructor may be called on a background thread, as I/O and parsing may be long-running. + *
+ * Use this constructor with shared object managers in order to handle multiple layers with + * their own event handlers on the map. * + * @param map GoogleMap object + * @param resourceId Raw resource KML or KMZ file + * @param context The Context + * @param markerManager marker manager to create marker collection from + * @param polygonManager polygon manager to create polygon collection from + * @param polylineManager polyline manager to create polyline collection from + * @param groundOverlayManager ground overlay manager to create ground overlay collection from + * @param cache cache to be used for fetched images + * @param maxKmzEntryCount The maximum number of entries a KMZ file can contain. + * @param maxKmzUncompressedTotalSize The maximum size of the uncompressed KMZ file in bytes. + * @throws XmlPullParserException if file cannot be parsed + * @throws IOException if I/O error + */ + public KmlLayer(GoogleMap map, + @RawRes int resourceId, + Context context, + MarkerManager markerManager, + PolygonManager polygonManager, + PolylineManager polylineManager, + GroundOverlayManager groundOverlayManager, + Renderer.ImagesCache cache, + int maxKmzEntryCount, + long maxKmzUncompressedTotalSize) + throws XmlPullParserException, IOException { + this(map, context.getResources().openRawResource(resourceId), context, markerManager, polygonManager, polylineManager, groundOverlayManager, cache, null, maxKmzEntryCount, maxKmzUncompressedTotalSize); + } + + /** + * Creates a new KmlLayer object - addLayerToMap() must be called to trigger rendering onto a map. + *
+ * Constructor may be called on a background thread, as I/O and parsing may be long-running. + *
* Use this constructor with shared object managers in order to handle multiple layers with * their own event handlers on the map. * @@ -138,14 +212,49 @@ public KmlLayer(GoogleMap map, GroundOverlayManager groundOverlayManager, Renderer.ImagesCache cache) throws XmlPullParserException, IOException { - this(map, stream, context, markerManager, polygonManager, polylineManager, groundOverlayManager, cache, null); + this(map, stream, context, markerManager, polygonManager, polylineManager, groundOverlayManager, cache, null, DEFAULT_MAX_KMZ_ENTRY_COUNT, DEFAULT_MAX_KMZ_UNCOMPRESSED_TOTAL_SIZE); } /** * Creates a new KmlLayer object - addLayerToMap() must be called to trigger rendering onto a map. - * + *
* Constructor may be called on a background thread, as I/O and parsing may be long-running. + *
+ * Use this constructor with shared object managers in order to handle multiple layers with + * their own event handlers on the map. * + * @param map GoogleMap object + * @param stream InputStream containing KML or KMZ file + * @param context The Context + * @param markerManager marker manager to create marker collection from + * @param polygonManager polygon manager to create polygon collection from + * @param polylineManager polyline manager to create polyline collection from + * @param groundOverlayManager ground overlay manager to create ground overlay collection from + * @param cache cache to be used for fetched images + * @param maxKmzEntryCount The maximum number of entries a KMZ file can contain. + * @param maxKmzUncompressedTotalSize The maximum size of the uncompressed KMZ file in bytes. + * @throws XmlPullParserException if file cannot be parsed + * @throws IOException if I/O error + */ + public KmlLayer(GoogleMap map, + InputStream stream, + Context context, + MarkerManager markerManager, + PolygonManager polygonManager, + PolylineManager polylineManager, + GroundOverlayManager groundOverlayManager, + Renderer.ImagesCache cache, + int maxKmzEntryCount, + long maxKmzUncompressedTotalSize) + throws XmlPullParserException, IOException { + this(map, stream, context, markerManager, polygonManager, polylineManager, groundOverlayManager, cache, null, maxKmzEntryCount, maxKmzUncompressedTotalSize); + } + + /** + * Creates a new KmlLayer object - addLayerToMap() must be called to trigger rendering onto a map. + *
+ * Constructor may be called on a background thread, as I/O and parsing may be long-running. + *
* Use this constructor with shared object managers in order to handle multiple layers with * their own event handlers on the map. * @@ -171,6 +280,43 @@ public KmlLayer(GoogleMap map, Renderer.ImagesCache cache, @Nullable KmlUrlSanitizer urlSanitizer) throws XmlPullParserException, IOException { + this(map, stream, context, markerManager, polygonManager, polylineManager, groundOverlayManager, cache, urlSanitizer, DEFAULT_MAX_KMZ_ENTRY_COUNT, DEFAULT_MAX_KMZ_UNCOMPRESSED_TOTAL_SIZE); + } + + /** + * Creates a new KmlLayer object - addLayerToMap() must be called to trigger rendering onto a map. + *
+ * Constructor may be called on a background thread, as I/O and parsing may be long-running. + *
+ * Use this constructor with shared object managers in order to handle multiple layers with
+ * their own event handlers on the map.
+ *
+ * @param map GoogleMap object
+ * @param stream InputStream containing KML or KMZ file
+ * @param context The Context
+ * @param markerManager marker manager to create marker collection from
+ * @param polygonManager polygon manager to create polygon collection from
+ * @param polylineManager polyline manager to create polyline collection from
+ * @param groundOverlayManager ground overlay manager to create ground overlay collection from
+ * @param cache cache to be used for fetched images
+ * @param urlSanitizer sanitizer to be used for external URLs
+ * @param maxKmzEntryCount The maximum number of entries a KMZ file can contain.
+ * @param maxKmzUncompressedTotalSize The maximum size of the uncompressed KMZ file in bytes.
+ * @throws XmlPullParserException if file cannot be parsed
+ * @throws IOException if I/O error
+ */
+ public KmlLayer(GoogleMap map,
+ InputStream stream,
+ Context context,
+ MarkerManager markerManager,
+ PolygonManager polygonManager,
+ PolylineManager polylineManager,
+ GroundOverlayManager groundOverlayManager,
+ Renderer.ImagesCache cache,
+ @Nullable KmlUrlSanitizer urlSanitizer,
+ int maxKmzEntryCount,
+ long maxKmzUncompressedTotalSize)
+ throws XmlPullParserException, IOException {
if (stream == null) {
throw new IllegalArgumentException("KML InputStream cannot be null");
}
@@ -179,16 +325,22 @@ public KmlLayer(GoogleMap map,
BufferedInputStream bis = new BufferedInputStream(stream);
bis.mark(1024);
ZipInputStream zip = new ZipInputStream(bis);
+ CountingInputStream countingStream = new CountingInputStream(zip, maxKmzUncompressedTotalSize);
try {
KmlParser parser = null;
ZipEntry entry = zip.getNextEntry();
if (entry != null) { // is a KMZ zip file
+ int entryCount = 0;
HashMap