diff --git a/android/manifest b/android/manifest index 41316e6a..93033be0 100644 --- a/android/manifest +++ b/android/manifest @@ -2,7 +2,7 @@ # this is your module manifest and used by Titanium # during compilation, packaging, distribution, etc. # -version: 5.7.0 +version: 5.8.0 apiversion: 4 architectures: arm64-v8a armeabi-v7a x86 x86_64 description: External version of Map module using native Google Maps library diff --git a/android/src/ti/map/TiUIMapView.java b/android/src/ti/map/TiUIMapView.java index f52b68c5..111d3470 100644 --- a/android/src/ti/map/TiUIMapView.java +++ b/android/src/ti/map/TiUIMapView.java @@ -39,6 +39,9 @@ import com.google.maps.android.clustering.ClusterManager; import com.google.maps.android.clustering.view.DefaultClusterRenderer; import com.google.maps.android.collections.MarkerManager; +import com.google.maps.android.data.geojson.GeoJsonLayer; +import com.google.maps.android.data.geojson.GeoJsonPolygonStyle; +import com.google.maps.android.data.kml.KmlLayer; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -50,6 +53,7 @@ import org.appcelerator.titanium.TiApplication; import org.appcelerator.titanium.TiBlob; import org.appcelerator.titanium.TiC; +import org.appcelerator.titanium.io.TiBaseFile; import org.appcelerator.titanium.io.TiFileFactory; import org.appcelerator.titanium.proxy.TiViewProxy; import org.appcelerator.titanium.util.TiConvert; @@ -88,6 +92,8 @@ public class TiUIMapView extends TiUIFragment private DefaultClusterRenderer clusterRender; private MarkerManager mMarkerManager; private MarkerManager.Collection collection; + private KrollDict localGeoJson; + private TiBlob localKml; public TiUIMapView(final TiViewProxy proxy, Activity activity) { @@ -322,6 +328,12 @@ public void processMapProperties(KrollDict d) if (clusterRender != null) clusterRender.setMinClusterSize(d.getInt(MapModule.PROPERTY_MIN_CLUSTER_SIZE)); } + if (d.containsKeyAndNotNull("kml")) { + localKml = TiConvert.toBlob(d.get("kml")); + } + if (d.containsKeyAndNotNull("geoJSON")) { + localGeoJson = d.getKrollDict("geoJSON"); + } } @Override @@ -1416,6 +1428,12 @@ public void onMapLoaded() if (proxy != null) { proxy.fireEvent(TiC.EVENT_COMPLETE, null); } + if (localGeoJson != null) { + loadGeoJSON(localGeoJson); + } + if (localKml != null) { + loadKml(localKml); + } } protected void onViewCreated() @@ -1447,4 +1465,67 @@ public boolean onClusterItemClick(TiMarker tiMarker) { return onMarkerClick(tiMarker.getMarker()); } + + public void loadKml(TiBlob file) + { + if (map != null) { + try { + KmlLayer layer = + new KmlLayer(map, file.getInputStream(), TiApplication.getInstance().getApplicationContext()); + layer.addLayerToMap(); + } catch (Exception ex) { + Log.e(TAG, "Error: " + ex.getMessage()); + } + localKml = null; + } else { + localKml = file; + } + } + + public void loadGeoJSON(KrollDict obj) + { + if (map != null) { + try { + JSONObject jsonObject; + + if (obj.containsKeyAndNotNull("json")) { + String json = obj.getString("json"); + jsonObject = new JSONObject(json); + } else if (obj.containsKeyAndNotNull(TiC.PROPERTY_FILE)) { + String url = proxy.resolveUrl(null, obj.getString(TiC.PROPERTY_FILE)); + TiBaseFile file = TiFileFactory.createTitaniumFile(new String[] { url }, false); + if (file.exists()) { + jsonObject = new JSONObject(file.read().toString()); + } else { + Log.e(TAG, "File not found"); + return; + } + } else { + Log.e(TAG, "To use a geoJSON you'll need to either set the 'file' or 'json' property."); + return; + } + + GeoJsonLayer layer = new GeoJsonLayer(map, jsonObject); + GeoJsonPolygonStyle polygonStyle = layer.getDefaultPolygonStyle(); + + if (obj.containsKeyAndNotNull(TiC.PROPERTY_BORDER_WIDTH)) { + polygonStyle.setStrokeWidth(obj.getInt(TiC.PROPERTY_BORDER_WIDTH)); + } + if (obj.containsKeyAndNotNull(TiC.PROPERTY_BORDER_COLOR)) { + polygonStyle.setStrokeColor(TiConvert.toColor(obj.getString(TiC.PROPERTY_BORDER_COLOR), + TiApplication.getAppRootOrCurrentActivity())); + } + if (obj.containsKeyAndNotNull(TiC.PROPERTY_BACKGROUND_COLOR)) { + polygonStyle.setFillColor(TiConvert.toColor(obj.getString(TiC.PROPERTY_BACKGROUND_COLOR), + TiApplication.getAppRootOrCurrentActivity())); + } + layer.addLayerToMap(); + } catch (Exception ex) { + Log.e(TAG, "Error: " + ex.getMessage()); + } + localGeoJson = null; + } else { + localGeoJson = obj; + } + } } diff --git a/android/src/ti/map/ViewProxy.java b/android/src/ti/map/ViewProxy.java index a09b9faf..21df6184 100644 --- a/android/src/ti/map/ViewProxy.java +++ b/android/src/ti/map/ViewProxy.java @@ -10,9 +10,7 @@ import android.os.Message; import com.google.android.gms.maps.CameraUpdate; import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.MapView; import com.google.android.gms.maps.model.LatLng; -import com.google.android.gms.maps.model.TileOverlay; import com.google.android.gms.maps.model.TileOverlayOptions; import com.google.maps.android.heatmaps.HeatmapTileProvider; import java.util.ArrayList; @@ -27,6 +25,7 @@ import org.appcelerator.kroll.common.Log; import org.appcelerator.kroll.common.TiMessenger; import org.appcelerator.titanium.TiApplication; +import org.appcelerator.titanium.TiBlob; import org.appcelerator.titanium.TiC; import org.appcelerator.titanium.proxy.TiViewProxy; import org.appcelerator.titanium.util.TiConvert; @@ -1514,6 +1513,28 @@ public void setClusterAnnotation() { } + @Kroll.setProperty + public void kml(TiBlob file) + { + TiUIView view = peekView(); + if (view instanceof TiUIMapView) { + ((TiUIMapView) view).loadKml(file); + } else { + Log.e(TAG, "Map is not available"); + } + } + + @Kroll.setProperty + public void geoJSON(KrollDict obj) + { + TiUIView view = peekView(); + if (view instanceof TiUIMapView) { + ((TiUIMapView) view).loadGeoJSON(obj); + } else { + Log.e(TAG, "Map is not available"); + } + } + public String getApiName() { return "Ti.Map.View"; diff --git a/apidoc/Map.yml b/apidoc/Map.yml index 3b980deb..03acf82f 100644 --- a/apidoc/Map.yml +++ b/apidoc/Map.yml @@ -33,7 +33,7 @@ description: | - @@ -438,7 +438,7 @@ properties: since: "6.3.0" - name: FEATURE_TERRITORIES - summary: | + summary: | The option that represents territorial boundaries such as a national border, a state boundary, or a neighborhood. type: Number @@ -448,7 +448,7 @@ properties: since: "12.0.0" - name: FEATURE_PHYSICAL_FEATURES - summary: | + summary: | The option that represents physical map features such as mountain ranges, rivers, and ocean basins. type: Number @@ -484,14 +484,14 @@ properties: osver: {ios: {min: "11.0"} } exclude-platforms: [android] since: "6.3.0" - + - name: SEARCH_RESULT_TYPE_ADDRESS summary: A value that indicates that search results include addresses. type: Number permission: read-only osver: {ios: {min: "13.0"} } since: "12.3.0" - + - name: SEARCH_RESULT_TYPE_POINT_OF_INTEREST summary: A value that indicates that search results include points of interest. type: Number @@ -506,6 +506,23 @@ properties: osver: {ios: {min: "13.0"} } since: "12.3.0" + - name: kml + summary: | + Loads a KML file and displays the content on the map. + description: | + Check [Google Maps KML support](https://developers.google.com/maps/documentation/android-sdk/utility/kml#supported) + for more details. + type: Object + exclude-platforms: [iphone, ipad, macos] + since: "13.1.0" + + - name: geoJSON + summary: | + Loads a geoJSON and displays the content on the map. + type: GeoJsonType + exclude-platforms: [iphone, ipad, macos] + since: "13.1.0" + methods: - name: isGooglePlayServicesAvailable returns: @@ -518,7 +535,7 @@ methods: summary: Returns a code to indicate whether Google Play Services is available on the device. since: "3.1.1" platforms: [android] - + - name: search summary: | Uses the native `MKLocalSearchCompleter` class to search places for @@ -614,7 +631,7 @@ examples: const mapView = Map.createView({ mapType: Map.NORMAL_TYPE, - region: { + region: { latitude: 33.74511, longitude: -84.38993, latitudeDelta: 0.01, @@ -769,7 +786,7 @@ examples: The following example shows the MapKit based search request. The options in `search` (2nd parameter) are optional, but improve the accuracy of the results. - + ```javascript import Map from 'ti.map'; @@ -789,6 +806,26 @@ examples: }); ``` +--- +name: GeoJsonType +summary: An object representing a geoJSON object. +properties: + - name: json + summary: JSON string to render on the map (use either 'json' or 'file'). + type: String + - name: file + summary: filename of the geoJSON file (use either 'json' or 'file'). + type: String + - name: backgroundColor + summary: background color of the area. + type: String + - name: borderColor + summary: border color of the area. + type: String + - name: borderWidth + summary: width of the border. + type: Number + --- name: MapPointType summary: An object representing a point on the map. @@ -817,4 +854,4 @@ properties: - - - - type: Array \ No newline at end of file + type: Array