diff --git a/README.md b/README.md
index 3f8ff3a3..3ed9ef11 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,7 @@
- [@nativescript/fingerprint-auth](packages/fingerprint-auth/README.md)
- [@nativescript/geolocation](packages/geolocation/README.md)
- [@nativescript/google-maps](packages/google-maps/README.md)
+- [@nativescript/google-maps-utils](packages/google-maps-utils/README.md)
- [@nativescript/google-signin](packages/google-signin/README.md)
- [@nativescript/haptics](packages/haptics/README.md)
- [@nativescript/imagepicker](packages/imagepicker/README.md)
diff --git a/apps/demo-angular/package.json b/apps/demo-angular/package.json
index f79a7b06..3e4ef095 100644
--- a/apps/demo-angular/package.json
+++ b/apps/demo-angular/package.json
@@ -2,6 +2,9 @@
"main": "./src/main.ts",
"dependencies": {
"@nativescript/core": "file:../../node_modules/@nativescript/core",
+ "@nativescript/google-maps": "file:../../dist/packages/google-maps",
+ "@nativescript/google-maps-utils": "file:../../dist/packages/google-maps-utils",
+ "@nativescript/jetpack-compose": "file:../../dist/packages/jetpack-compose",
"@nativescript/animated-circle": "file:../../dist/packages/animated-circle",
"@nativescript/appavailability": "file:../../dist/packages/appavailability",
"@nativescript/apple-sign-in": "file:../../dist/packages/apple-sign-in",
@@ -20,7 +23,6 @@
"@nativescript/facebook": "file:../../dist/packages/facebook",
"@nativescript/fingerprint-auth": "file:../../dist/packages/fingerprint-auth",
"@nativescript/geolocation": "file:../../dist/packages/geolocation",
- "@nativescript/google-maps": "file:../../dist/packages/google-maps",
"@nativescript/google-signin": "file:../../dist/packages/google-signin",
"@nativescript/haptics": "file:../../dist/packages/haptics",
"@nativescript/imagepicker": "file:../../dist/packages/imagepicker",
diff --git a/apps/demo-angular/src/app-routing.module.ts b/apps/demo-angular/src/app-routing.module.ts
index 002b52e3..75c83fa7 100644
--- a/apps/demo-angular/src/app-routing.module.ts
+++ b/apps/demo-angular/src/app-routing.module.ts
@@ -26,6 +26,7 @@ const routes: Routes = [
{ path: 'fingerprint-auth', loadChildren: () => import('./plugin-demos/fingerprint-auth.module').then((m) => m.FingerprintAuthModule) },
{ path: 'geolocation', loadChildren: () => import('./plugin-demos/geolocation.module').then((m) => m.GeolocationModule) },
{ path: 'google-maps', loadChildren: () => import('./plugin-demos/google-maps.module').then((m) => m.GoogleMapsModule) },
+ { path: 'google-maps-utils', loadChildren: () => import('./plugin-demos/google-maps-utils.module').then((m) => m.GoogleMapsUtilsModule) },
{ path: 'google-signin', loadChildren: () => import('./plugin-demos/google-signin.module').then((m) => m.GoogleSigninModule) },
{ path: 'haptics', loadChildren: () => import('./plugin-demos/haptics.module').then((m) => m.HapticsModule) },
{ path: 'imagepicker', loadChildren: () => import('./plugin-demos/imagepicker.module').then((m) => m.ImagepickerModule) },
diff --git a/apps/demo-angular/src/home.component.ts b/apps/demo-angular/src/home.component.ts
index 578d0a68..596d0d4b 100644
--- a/apps/demo-angular/src/home.component.ts
+++ b/apps/demo-angular/src/home.component.ts
@@ -63,6 +63,9 @@ export class HomeComponent {
{
name: 'google-maps',
},
+ {
+ name: 'google-maps-utils',
+ },
{
name: 'google-signin',
},
diff --git a/apps/demo-angular/src/plugin-demos/google-maps-utils.component.html b/apps/demo-angular/src/plugin-demos/google-maps-utils.component.html
new file mode 100644
index 00000000..56634035
--- /dev/null
+++ b/apps/demo-angular/src/plugin-demos/google-maps-utils.component.html
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/apps/demo-angular/src/plugin-demos/google-maps-utils.component.ts b/apps/demo-angular/src/plugin-demos/google-maps-utils.component.ts
new file mode 100644
index 00000000..3ae88b2b
--- /dev/null
+++ b/apps/demo-angular/src/plugin-demos/google-maps-utils.component.ts
@@ -0,0 +1,19 @@
+import { Component, NgZone } from '@angular/core';
+import { DemoSharedGoogleMapsUtils } from '@demo/shared';
+import { } from '@nativescript/google-maps-utils';
+
+@Component({
+ selector: 'demo-google-maps-utils',
+ templateUrl: 'google-maps-utils.component.html',
+})
+export class GoogleMapsUtilsComponent {
+
+ demoShared: DemoSharedGoogleMapsUtils;
+
+ constructor(private _ngZone: NgZone) {}
+
+ ngOnInit() {
+ this.demoShared = new DemoSharedGoogleMapsUtils();
+ }
+
+}
\ No newline at end of file
diff --git a/apps/demo-angular/src/plugin-demos/google-maps-utils.module.ts b/apps/demo-angular/src/plugin-demos/google-maps-utils.module.ts
new file mode 100644
index 00000000..1a219672
--- /dev/null
+++ b/apps/demo-angular/src/plugin-demos/google-maps-utils.module.ts
@@ -0,0 +1,10 @@
+import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
+import { NativeScriptCommonModule, NativeScriptRouterModule } from '@nativescript/angular';
+import { GoogleMapsUtilsComponent } from './google-maps-utils.component';
+
+@NgModule({
+ imports: [NativeScriptCommonModule, NativeScriptRouterModule.forChild([{ path: '', component: GoogleMapsUtilsComponent }])],
+ declarations: [GoogleMapsUtilsComponent],
+ schemas: [ NO_ERRORS_SCHEMA]
+})
+export class GoogleMapsUtilsModule {}
diff --git a/apps/demo/package.json b/apps/demo/package.json
index db61c8e7..e8cd4c9b 100644
--- a/apps/demo/package.json
+++ b/apps/demo/package.json
@@ -5,6 +5,9 @@
"repository": "",
"dependencies": {
"@nativescript/core": "file:../../node_modules/@nativescript/core",
+ "@nativescript/google-maps": "file:../../packages/google-maps",
+ "@nativescript/google-maps-utils": "file:../../packages/google-maps-utils",
+ "@nativescript/jetpack-compose": "file:../../packages/jetpack-compose",
"@nativescript/animated-circle": "file:../../packages/animated-circle",
"@nativescript/appavailability": "file:../../packages/appavailability",
"@nativescript/apple-sign-in": "file:../../packages/apple-sign-in",
@@ -23,7 +26,6 @@
"@nativescript/facebook": "file:../../packages/facebook",
"@nativescript/fingerprint-auth": "file:../../packages/fingerprint-auth",
"@nativescript/geolocation": "file:../../packages/geolocation",
- "@nativescript/google-maps": "file:../../packages/google-maps",
"@nativescript/google-signin": "file:../../packages/google-signin",
"@nativescript/haptics": "file:../../packages/haptics",
"@nativescript/imagepicker": "file:../../packages/imagepicker",
diff --git a/apps/demo/src/main-page.xml b/apps/demo/src/main-page.xml
index 3f2c4c7d..8d5d9938 100644
--- a/apps/demo/src/main-page.xml
+++ b/apps/demo/src/main-page.xml
@@ -24,6 +24,7 @@
+
diff --git a/apps/demo/src/plugin-demos/google-maps-utils.ts b/apps/demo/src/plugin-demos/google-maps-utils.ts
new file mode 100644
index 00000000..b60e6307
--- /dev/null
+++ b/apps/demo/src/plugin-demos/google-maps-utils.ts
@@ -0,0 +1,12 @@
+import { Observable, EventData, Page } from '@nativescript/core';
+import { DemoSharedGoogleMapsUtils } from '@demo/shared';
+import { } from '@nativescript/google-maps-utils';
+
+export function navigatingTo(args: EventData) {
+ const page = args.object;
+ page.bindingContext = new DemoModel();
+}
+
+export class DemoModel extends DemoSharedGoogleMapsUtils {
+
+}
diff --git a/apps/demo/src/plugin-demos/google-maps-utils.xml b/apps/demo/src/plugin-demos/google-maps-utils.xml
new file mode 100644
index 00000000..65a33ef6
--- /dev/null
+++ b/apps/demo/src/plugin-demos/google-maps-utils.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/package.json b/package.json
index 1caf68e0..b32728b1 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
"@nativescript/types": "~8.5.0",
"@nativescript/webpack": "~5.0.5",
"@ngtools/webpack": "^15.0.0",
+ "@types/geojson": "^7946.0.10",
"@types/mkdirp": "^1.0.1",
"@types/sprintf-js": "^1.1.0",
"husky": "^8.0.0",
diff --git a/packages/google-maps-utils/.eslintrc.json b/packages/google-maps-utils/.eslintrc.json
new file mode 100644
index 00000000..53c06c8d
--- /dev/null
+++ b/packages/google-maps-utils/.eslintrc.json
@@ -0,0 +1,18 @@
+{
+ "extends": ["../../.eslintrc.json"],
+ "ignorePatterns": ["!**/*", "node_modules/**/*"],
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.js", "*.jsx"],
+ "rules": {}
+ }
+ ]
+}
diff --git a/packages/google-maps-utils/README.md b/packages/google-maps-utils/README.md
new file mode 100644
index 00000000..0289874d
--- /dev/null
+++ b/packages/google-maps-utils/README.md
@@ -0,0 +1,98 @@
+# @nativescript/google-maps-utils
+
+```javascript
+ns plugin add @nativescript/google-maps-utils
+```
+*Requires google maps plugin [@nativescript/google-maps](packages/google-maps/README.md)*
+
+## Installation
+Install the mixins to the GoogleMaps object
+```javascript
+import { installMixins } from '@nativescript/google-maps-utils';
+installMixins();
+```
+
+## Usage
+You can access the google maps utilities from the GoogleMaps object after the mixins have been installed.
+```javascript
+onMapReady(args: MapReadyEvent) {
+ const map = args.map;
+}
+```
+
+---
+
+## HeatMaps
+```javascript
+import { HeatmapTileProvider, HeatmapOptions } from '@nativescript/google-maps-utils';
+import { GoogleMap, Coordinate } from '@nativescript/google-maps';
+
+addHeatmapOverlay(map: GoogleMap, heatmapOptions: HeatmapOptions) {
+ // Create a new heat map tile provider
+ const heatmapProvider = new HeatmapTileProvider(heatmapOptions);
+ // Pass tile provider to Google Maps
+ const heatmapOverlay = map.addTileOverlay({
+ tileProvider: heatmapProvider,
+ });
+}
+```
+
+### HeatmapOptions
+
+| Property | Type
+|:---------|:-----
+| `coordinates` | `Coordinate[]`;
+| `opacity` | `number`;
+| `radius` | `number`;
+| `maxIntensity` | `number`;
+| `gradient` | ` IGradient[]`;
+
+---
+
+## Clustering
+```javascript
+import { ClusterManager } from '@nativescript/google-maps-utils';
+import { GoogleMap, MarkerOptions } from '@nativescript/google-maps';
+
+addClusteredMarkers(map: GoogleMap, markers: MarkerOptions[]) {
+ const clusterManager: ClusterManager = map.clusterManager(markers);
+}
+```
+
+---
+
+## Experimental Features
+Features that are not yet fully implemented or likely to change.
+### GeoJson Layers
+
+Currently only supports GeoJson Objects.
+
+```javascript
+import { GeoJsonLayer, IGeometryStyle } from '@nativescript/google-maps-utils';
+
+onMapReady(args: MapReadyEvent) {
+ const style: Partial = {
+ fillColor: new Color('blue'),
+ strokeColor: new Color('red'),
+ width: 4,
+ }
+
+ map.addGeoJson({
+ geoJson: geoJson,
+ style: style,
+ });
+}
+```
+
+```javascript
+import { GeoJsonLayer } from '@nativescript/google-maps-utils';
+
+removeGeoJsonLayer(map: GoogleMap, layer: GeoJsonLayer) {
+ map.removeGeoJson(layer);
+}
+```
+
+
+## License
+
+Apache License Version 2.0
diff --git a/packages/google-maps-utils/experimental/datalayer/index.android.ts b/packages/google-maps-utils/experimental/datalayer/index.android.ts
new file mode 100644
index 00000000..1e99bafa
--- /dev/null
+++ b/packages/google-maps-utils/experimental/datalayer/index.android.ts
@@ -0,0 +1,339 @@
+import { Color } from '@nativescript/core';
+import { GoogleMap } from '@nativescript/google-maps';
+import { intoNativeColor } from '../../../google-maps-utils/utils';
+import { IGeometryStyle, IGeoJsonLayer, IFeature, IGeometry } from '.';
+
+export abstract class DataLayer {
+ abstract readonly native: T;
+
+ // setMap(map: com.google.android.gms.maps.GoogleMap) {
+ // this.native.setMap(map);
+ // }
+
+ // getDefaultPolygonStyle() {
+ // return this.native.getDefaultPolygonStyle();
+ // }
+
+ addLayerToMap() {
+ this.native.addLayerToMap();
+ }
+
+ // isLayerOnMap(): boolean {
+ // return this.native.isLayerOnMap();
+ // }
+
+ removeLayerFromMap() {
+ this.native.removeLayerFromMap();
+ }
+
+ // hasFeatures(): boolean {
+ // return this.native.hasFeatures();
+ // }
+
+ // getFeature(feature: any) {
+ // return this.native.getFeature(feature);
+ // }
+
+ // getFeatures(): any {
+ // return this.native.getFeatures();
+ // }
+
+ // addFeature(feature: com.google.maps.android.data.geojson.GeoJsonFeature) {
+ // return this.native.addFeature(feature);
+ // }
+
+ // removeFeature(feature: com.google.maps.android.data.geojson.GeoJsonFeature) {
+ // this.native.removeFeature(feature);
+ // }
+
+ get android() {
+ return this.native;
+ }
+
+ // public hasContainers(): boolean;
+ // public addKMLToMap(): void;
+ // public getDefaultPointStyle(): com.google.maps.android.data.geojson.GeoJsonPointStyle;
+ // public setOnFeatureClickListener(param0: com.google.maps.android.data.Layer.OnFeatureClickListener): void;
+ // public removeFeature(param0: com.google.maps.android.data.Feature): void;
+ // public getMap(): com.google.android.gms.maps.GoogleMap;
+ // public addGeoJsonToMap(): void;
+ // public getDefaultLineStringStyle(): com.google.maps.android.data.geojson.GeoJsonLineStringStyle;
+ // public storeRenderer(param0: com.google.maps.android.data.Renderer): void;
+ // public getContainers(): java.lang.Iterable;
+ // public getContainerFeature(param0: any): com.google.maps.android.data.Feature;
+ // public getGroundOverlays(): java.lang.Iterable;
+}
+
+export class KmlGeometryStyle implements IGeometryStyle {
+ constructor(public getPolygonOptions: com.google.android.gms.maps.model.PolygonOptions, public getPolylineOptions: com.google.android.gms.maps.model.PolylineOptions, public kerOptions: com.google.android.gms.maps.model.MarkerOptions) {}
+
+ get strokeColor(): Color {
+ return intoNativeColor(this.getPolygonOptions.getStrokeColor().toString());
+ }
+ fillColor: Color;
+ width: number;
+ scale: number;
+ heading: number;
+ anchor: [number, number];
+ iconUrl: string;
+ title: string;
+}
+export class GeoJsonGeometryStyle implements Partial {
+ constructor(private polygonStyle: com.google.maps.android.data.geojson.GeoJsonPolygonStyle, private lineStyle: com.google.maps.android.data.geojson.GeoJsonLineStringStyle, private pointStyle: com.google.maps.android.data.geojson.GeoJsonPointStyle) {}
+
+ get strokeColor() {
+ return new Color(this.polygonStyle.getStrokeColor());
+ }
+ set strokeColor(color: Color) {
+ this.polygonStyle.setStrokeColor(color.android);
+ this.lineStyle.setColor(color.android);
+ }
+
+ get fillColor() {
+ return new Color(this.polygonStyle.getFillColor());
+ }
+ set fillColor(color: Color) {
+ this.polygonStyle.setFillColor(color.android);
+ }
+
+ get width(): number {
+ return this.lineStyle.getWidth();
+ }
+ set width(width: number) {
+ this.lineStyle.setWidth(width);
+ this.polygonStyle.setStrokeWidth(width);
+ }
+
+ get title() {
+ return this.pointStyle.getTitle();
+ }
+ set title(title: string) {
+ this.pointStyle.setTitle(title);
+ }
+
+ get heading(): number {
+ return this.pointStyle.getRotation();
+ }
+ set heading(rotation: number) {
+ // Marker roation or rotation???
+ this.pointStyle.setRotation(rotation);
+ // this.pointStyle.setMarkerRotation(rotation);
+ }
+}
+
+export class GeoJsonLayer extends DataLayer implements IGeoJsonLayer {
+ #native: com.google.maps.android.data.geojson.GeoJsonLayer;
+ style: GeoJsonGeometryStyle;
+
+ constructor(map: GoogleMap, geoJson: any, geometryStyle?: IGeometryStyle) {
+ super();
+ if (map && geoJson) {
+ try {
+ const geoJsonData = new org.json.JSONObject(JSON.stringify(geoJson));
+ this.#native = new com.google.maps.android.data.geojson.GeoJsonLayer(map.native, geoJsonData);
+ this.style = new GeoJsonGeometryStyle(this.#native.getDefaultPolygonStyle(), this.#native.getDefaultLineStringStyle(), this.#native.getDefaultPointStyle());
+
+ if (geometryStyle) {
+ for (const key of Object.keys(geometryStyle)) {
+ if (geometryStyle?.[key]) {
+ this.style[key] = geometryStyle?.[key];
+ }
+ }
+ }
+ } catch (error) {
+ console.error(error);
+ }
+ }
+ }
+
+ static fromNative(nativeGeoJsonLayer: com.google.maps.android.data.geojson.GeoJsonLayer) {
+ if (nativeGeoJsonLayer instanceof com.google.maps.android.data.geojson.GeoJsonLayer) {
+ const geoJsonLayer = new GeoJsonLayer(null, null);
+ geoJsonLayer.#native = nativeGeoJsonLayer;
+ return geoJsonLayer;
+ }
+ return null;
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ get features() {
+ const features: GeoJsonFeature[] = [];
+ const nativeFeatures: java.lang.Iterable = this.native.getFeatures();
+
+ const iter = nativeFeatures.iterator();
+ while (iter.hasNext()) {
+ const feature = iter.next();
+ features.push(GeoJsonFeature.fromNative(feature));
+ }
+
+ return features;
+ }
+
+ // get bounds(): CoordinateBounds {
+ // const bounds = this.#native.getBoundingBox();
+ // if (bounds) {
+ // return {
+ // southwest: {
+ // lat: bounds?.southwest?.latitude,
+ // lng: bounds?.southwest?.longitude,
+ // },
+ // northeast: {
+ // lat: bounds?.northeast?.latitude,
+ // lng: bounds?.northeast?.longitude,
+ // },
+ // };
+ // }
+ // }
+
+ // toString() {
+ // return this.native.toString();
+ // }
+}
+
+export class KmlLayer extends DataLayer {
+ #native: com.google.maps.android.data.kml.KmlLayer;
+
+ constructor(mapView: com.google.android.gms.maps.GoogleMap, kml: org.json.JSONObject) {
+ super();
+ if (mapView && kml) {
+ this.#native = new com.google.maps.android.data.kml.KmlLayer();
+ this.#native.addLayerToMap();
+ this.#native.addKMLToMap();
+ }
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ hasPlacemarks(): boolean {
+ return this.native.hasPlacemarks();
+ }
+
+ getPlacemarks(): java.lang.Iterable {
+ return this.native.getPlacemarks();
+ }
+
+ getGroundOverlays(): java.lang.Iterable {
+ return this.native.getGroundOverlays();
+ }
+}
+abstract class BaseFeature implements IFeature {
+ abstract style: any;
+ abstract readonly native: T;
+
+ get android() {
+ return this.native;
+ }
+
+ get geometry() {
+ return Geometry.fromNative(this.native.getGeometry());
+ }
+
+ get id() {
+ return this.native.getId();
+ }
+
+ get properties() {
+ const props = {};
+
+ const iter = this.native.getPropertyKeys().iterator();
+ while (iter.hasNext()) {
+ const key = iter.next();
+ props[key] = this.native.getProperty(key);
+ }
+
+ return props;
+ }
+ set properties(value: any) {
+ Object.entries(value).forEach(([key, value]: [string, string]) => {
+ this.native.setProperty(key, value);
+ });
+ }
+}
+
+export class GeoJsonFeature extends BaseFeature {
+ #native: com.google.maps.android.data.geojson.GeoJsonFeature;
+ #style: GeoJsonGeometryStyle;
+
+ constructor() {
+ super();
+ }
+
+ static fromNative(nativeFeature: com.google.maps.android.data.geojson.GeoJsonFeature) {
+ if (nativeFeature instanceof com.google.maps.android.data.geojson.GeoJsonFeature) {
+ const feature = new GeoJsonFeature();
+ feature.#native = nativeFeature;
+ return feature;
+ }
+ return null;
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ get style() {
+ this.#style = new GeoJsonGeometryStyle(this.native.getPolygonStyle(), this.native.getLineStringStyle(), this.native.getPointStyle());
+ return this.#style;
+ }
+}
+
+export class KMLPlacemarkFeature extends BaseFeature {
+ #native: com.google.maps.android.data.kml.KmlPlacemark;
+ #style: GeoJsonGeometryStyle;
+
+ constructor() {
+ super();
+ }
+
+ static fromNative(nativeFeature: com.google.maps.android.data.kml.KmlPlacemark) {
+ if (nativeFeature instanceof com.google.maps.android.data.kml.KmlPlacemark) {
+ const feature = new KMLPlacemarkFeature();
+ feature.#native = nativeFeature;
+ return feature;
+ }
+ return null;
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ get style() {
+ // this.#style = new KmlGeometryStyle(this.native.getPolygonOptions(), this.native.getPolylineOptions(), this.native.getMarkerOptions());
+ return this.#style;
+ }
+}
+
+export class Geometry implements IGeometry {
+ #native: com.google.maps.android.data.Geometry;
+
+ static fromNative(nativeGeometry: com.google.maps.android.data.Geometry) {
+ if (nativeGeometry instanceof com.google.maps.android.data.Geometry) {
+ const geometry = new Geometry();
+ geometry.#native = nativeGeometry;
+ return geometry;
+ }
+ return null;
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ get android() {
+ return this.native;
+ }
+
+ get type() {
+ return this.native.getGeometryType();
+ }
+
+ get geometries() {
+ return this.native.getGeometryObject();
+ }
+}
diff --git a/packages/google-maps-utils/experimental/datalayer/index.d.ts b/packages/google-maps-utils/experimental/datalayer/index.d.ts
new file mode 100644
index 00000000..d3baafda
--- /dev/null
+++ b/packages/google-maps-utils/experimental/datalayer/index.d.ts
@@ -0,0 +1,71 @@
+export interface IGeoJsonLayer {
+ style: GeometryStyle;
+ addLayerToMap: () => void;
+ removeLayerFromMap: () => void;
+}
+
+export class GeoJsonLayer implements IGeoJsonLayer {
+ ios: any;
+ android: any;
+ native: any;
+ style: GeometryStyle;
+ features: GeoJsonFeature[];
+ constructor(map: GoogleMap, geojson: any, styles?: Partial);
+ addLayerToMap: () => void;
+ removeLayerFromMap: () => void;
+}
+
+export interface IGeometryStyle {
+ /**
+ * The color for the stroke of a LineString or Polygon.
+ */
+ strokeColor: Color;
+
+ /**
+ * The color for the fill of a Polygon.
+ */
+ fillColor: Color;
+
+ /**
+ * The width of a LineString
+ */
+ width: number;
+
+ /**
+ * The scale that a Point's icon should be rendered at.
+ */
+ scale: number;
+
+ /**
+ * The direction, in degrees, that a Point's icon should be rendered at.
+ */
+ heading: number;
+
+ /**
+ * The position within an icon that is anchored to the Point.
+ */
+ anchor: [number, number];
+
+ /**
+ * Icon Url
+ */
+ iconUrl: string | null;
+
+ /**
+ * The title of the point
+ */
+ title: string | null;
+ // hasFill: boolean;
+ // hasStroke: boolean;
+}
+
+export interface IGeometry {
+ type: string;
+ geometries: any;
+}
+
+export interface IFeature {
+ geometry: any;
+ properties: any;
+ id: any;
+}
diff --git a/packages/google-maps-utils/experimental/datalayer/index.ios.ts b/packages/google-maps-utils/experimental/datalayer/index.ios.ts
new file mode 100644
index 00000000..cd8dd7c5
--- /dev/null
+++ b/packages/google-maps-utils/experimental/datalayer/index.ios.ts
@@ -0,0 +1,167 @@
+import { Color, encoding } from '@nativescript/core';
+import { GoogleMap } from '@nativescript/google-maps';
+import { IGeometryStyle, IGeoJsonLayer, IFeature, IGeometry } from '.';
+
+let UNIQUE_STYLE_ID = 0;
+
+export class GeometryStyle implements IGeometryStyle {
+ #native: GMUStyle;
+
+ constructor(public geometryStyles: Partial) {
+ Object.assign(this, geometryStyles);
+
+ this.#native = new GMUStyle({
+ styleID: `google-maps-utils-style-${UNIQUE_STYLE_ID++}`,
+ strokeColor: this.strokeColor?.ios ?? null,
+ fillColor: this.fillColor?.ios ?? null,
+ width: this.width ?? 1,
+ scale: this.scale ?? 0,
+ heading: this.heading ?? 0,
+ anchor: CGPointMake(this.anchor?.[0] ?? 0, this.anchor?.[1] ?? 0),
+ iconUrl: this.iconUrl ?? null,
+ title: this.title ?? null,
+ hasFill: !!this.fillColor,
+ hasStroke: !!this.strokeColor,
+ } as any);
+ }
+
+ strokeColor: Color;
+ fillColor: Color;
+ width: number;
+ scale: number;
+ heading: number;
+ anchor: [number, number];
+ iconUrl: string;
+ title: string;
+
+ get native() {
+ return this.#native;
+ }
+}
+
+export class GeoJsonLayer implements IGeoJsonLayer {
+ #native: GMUGeometryRenderer;
+ #parser: GMUGeoJSONParser;
+ style: GeometryStyle;
+
+ constructor(private map: GoogleMap, private geometries: any, private styles?: Partial) {
+ this.style = new GeometryStyle(styles);
+
+ const jsonString = new NSString({ UTF8String: JSON.stringify(geometries) });
+ this.#parser = new GMUGeoJSONParser({ data: jsonString.dataUsingEncoding(encoding.UTF_8) });
+ this.#parser.parse();
+
+ const features = this.#parser.features;
+ for (const feature of features) {
+ feature.style = this.style.native;
+ }
+
+ this.#native = new GMUGeometryRenderer({ map: this.map.native, geometries: features });
+ }
+
+ static fromNative(nativeGeoJsonLayer: GMUGeometryRenderer) {
+ if (nativeGeoJsonLayer instanceof GMUGeometryRenderer) {
+ const geoJsonLayer = new GeoJsonLayer(null, null, null);
+ geoJsonLayer.#native = nativeGeoJsonLayer;
+ return geoJsonLayer;
+ }
+ return null;
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ get ios() {
+ return this.native;
+ }
+
+ get features() {
+ // const features = [];
+ // for (const feature of this.#parser.features) {
+ // const f = feature as GMUGeometryContainer;
+
+ // GeoJsonFeature.fromNative(f);
+ // f.geometry;
+ // f.style;
+ // }
+ return null;
+ }
+
+ addLayerToMap() {
+ this.native.render();
+ }
+
+ removeLayerFromMap() {
+ this.native.clear();
+ }
+}
+
+export class GeoJsonFeature implements IFeature {
+ #native: GMUGeometryCollection;
+
+ static fromNative(nativeGeometryContainer: GMUGeometryCollection) {
+ if (nativeGeometryContainer instanceof GMUGeometryCollection) {
+ const geoJsonFeature = new GeoJsonFeature();
+ geoJsonFeature.#native = nativeGeometryContainer;
+ return geoJsonFeature;
+ }
+ return null;
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ get ios() {
+ return this.#native;
+ }
+
+ get geometry() {
+ const geometries = [];
+
+ for (const geometry of this.native.geometries) {
+ geometries.push(Geometry.fromNative(geometry));
+ }
+
+ return geometries;
+ }
+
+ get properties() {
+ return;
+ }
+
+ get id() {
+ return this.native.description;
+ }
+}
+
+export class Geometry implements IGeometry {
+ #native: GMUGeometry;
+
+ static fromNative(nativeGeometry: GMUGeometry) {
+ if (nativeGeometry) {
+ console.log(nativeGeometry.class().name);
+ const geometry = new Geometry();
+ geometry.#native = nativeGeometry;
+ return geometry;
+ }
+ return null;
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ get ios() {
+ return this.#native;
+ }
+
+ get type() {
+ return this.#native.type;
+ }
+
+ get geometries() {
+ return this.native;
+ }
+}
diff --git a/packages/google-maps-utils/experimental/iconfactory/index.android.ts b/packages/google-maps-utils/experimental/iconfactory/index.android.ts
new file mode 100644
index 00000000..9d8c6f41
--- /dev/null
+++ b/packages/google-maps-utils/experimental/iconfactory/index.android.ts
@@ -0,0 +1,56 @@
+import { Color, Utils } from '@nativescript/core';
+import { IIconFactory } from '.';
+
+export enum ICON_STYLE {
+ STYLE_DEFAULT = 1,
+ STYLE_WHITE = 2,
+ STYLE_RED = 3,
+ STYLE_BLUE = 4,
+ STYLE_GREEN = 5,
+ STYLE_ORANGE = 7,
+ STYLE_PURPLE = 6,
+}
+
+export class IconFactory implements IIconFactory {
+ #native: com.google.maps.android.ui.IconGenerator;
+
+ constructor() {
+ this.#native = new com.google.maps.android.ui.IconGenerator(Utils.ad.getApplicationContext());
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ get android() {
+ return this.native;
+ }
+
+ set backgroundAsset(value: globalAndroid.graphics.drawable.Drawable) {
+ this.native.setBackground(value);
+ }
+
+ set color(color: Color) {
+ this.#native.setColor(color.android);
+ }
+
+ set rotation(rotation: number) {
+ this.#native.setRotation(rotation);
+ }
+
+ set contentRotation(rotation: number) {
+ this.#native.setContentRotation(rotation);
+ }
+
+ setStyle(style: ICON_STYLE) {
+ this.#native.setStyle(style);
+ }
+
+ setTextAppearance(appearance: number) {
+ this.#native.setTextAppearance(appearance);
+ }
+
+ makeIcon(text: string): globalAndroid.graphics.Bitmap {
+ return this.#native.makeIcon(text);
+ }
+}
diff --git a/packages/google-maps-utils/experimental/iconfactory/index.d.ts b/packages/google-maps-utils/experimental/iconfactory/index.d.ts
new file mode 100644
index 00000000..2a38d425
--- /dev/null
+++ b/packages/google-maps-utils/experimental/iconfactory/index.d.ts
@@ -0,0 +1,25 @@
+import { Color } from '@nativescript/core';
+
+export interface IIconFactory {
+ setStyle(style: number);
+ setTextAppearance(style: number);
+ makeIcon(text: string);
+ color: Color;
+ backgroundAsset: any;
+ rotation: number;
+ contentRotation: number;
+ native: any;
+}
+
+export class IconFactory implements IIconFactory {
+ setStyle(style: number);
+ setTextAppearance(style: number);
+ makeIcon(text: string);
+ color: Color;
+ backgroundAsset: any;
+ rotation: number;
+ contentRotation: number;
+ android?: any;
+ ios?: any;
+ native?: any;
+}
diff --git a/packages/google-maps-utils/experimental/iconfactory/index.ios.ts b/packages/google-maps-utils/experimental/iconfactory/index.ios.ts
new file mode 100644
index 00000000..e0d61d82
--- /dev/null
+++ b/packages/google-maps-utils/experimental/iconfactory/index.ios.ts
@@ -0,0 +1,33 @@
+import { Color } from '@nativescript/core';
+import { IIconFactory } from '.';
+
+export enum ICON_STYLE {
+ STYLE_DEFAULT = 1,
+ STYLE_WHITE = 2,
+ STYLE_RED = 3,
+ STYLE_BLUE = 4,
+ STYLE_GREEN = 5,
+ STYLE_ORANGE = 7,
+ STYLE_PURPLE = 6,
+}
+
+export class IconFactory implements IIconFactory {
+ // Not provided in iOS google-maps-util library. Need to roll our own impl.
+ setStyle(style: number) {
+ console.error('Method not implemented.');
+ }
+ makeIcon(text: string) {
+ console.error('Method not implemented.');
+ return GMSMarker.markerImageWithColor(new Color('red').ios);
+ }
+ setTextAppearance(style: number) {
+ console.error('Method not implemented.');
+ }
+
+ color: Color;
+ backgroundAsset: any;
+ rotation: number;
+ contentRotation: number;
+ ios: any;
+ native: any;
+}
diff --git a/packages/google-maps-utils/index.android.ts b/packages/google-maps-utils/index.android.ts
new file mode 100644
index 00000000..51ef11ef
--- /dev/null
+++ b/packages/google-maps-utils/index.android.ts
@@ -0,0 +1,510 @@
+import { Color, ImageSource, Utils } from '@nativescript/core';
+import { GeoJSON } from 'geojson';
+import { Coordinate, GoogleMap, ITileProvider, MarkerOptions, hueFromColor } from '@nativescript/google-maps';
+import { HeatmapOptions, IClusterManager, IFeature, IGeoJsonLayer, IGeometry, IGeometryStyle, IGradient, IHeatmapTileProvider } from '.';
+import { applyMixins } from './utils/common';
+import { intoNativeClusterManager, intoNativeColor, intoNativeHeatmapGradient, intoNativeHeatmapProvider } from './utils';
+
+// export * from './experimental/datalayer';
+// export * from './experimental/iconfactory';
+export * from './utils';
+
+let mixinInstalled = false;
+export function overrideGoogleMap() {
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
+ const GMap = require('@nativescript/google-maps').GoogleMap;
+ applyMixins(GMap, [GoogleMapUtils], { after: true });
+}
+
+export function installMixins() {
+ if (!mixinInstalled) {
+ mixinInstalled = true;
+ overrideGoogleMap();
+ }
+}
+
+export class GoogleMapUtils {
+ clusterManager(markers: MarkerOptions[]) {
+ const GMap = this as unknown as GoogleMap;
+ const clusterManager = ClusterManager.fromNative(intoNativeClusterManager(GMap));
+ const renderer = new ClusterRenderer(GMap, clusterManager);
+ clusterManager.setRenderer(renderer);
+
+ const clusters = markers.map((marker) => new ClusterItem(marker));
+ clusterManager.addItems(clusters);
+
+ clusterManager.cluster();
+
+ return clusterManager;
+ }
+
+ addGeoJson(geoJson: GeoJSON, styleOptions: IGeometryStyle) {
+ if ((this as unknown as GoogleMap) && geoJson) {
+ const geoJsonData = new org.json.JSONObject(JSON.stringify(geoJson));
+ const native = new com.google.maps.android.data.geojson.GeoJsonLayer((this as unknown as GoogleMap).native, geoJsonData);
+ const style = new GeoJsonGeometryStyle(native.getDefaultPolygonStyle(), native.getDefaultLineStringStyle(), native.getDefaultPointStyle());
+
+ if (styleOptions) {
+ for (const key of Object.keys(styleOptions)) {
+ if (styleOptions?.[key]) {
+ style[key] = styleOptions?.[key];
+ }
+ }
+ }
+
+ native.addLayerToMap();
+
+ return GeoJsonLayer.fromNative(native);
+ }
+ return null;
+ }
+
+ removeGeoJson(geoJson: GeoJsonLayer) {
+ if (geoJson) {
+ geoJson.removeLayerFromMap();
+ }
+ }
+}
+
+export class HeatmapTileProvider implements ITileProvider, IHeatmapTileProvider {
+ #native: com.google.maps.android.heatmaps.HeatmapTileProvider;
+
+ constructor(options?: HeatmapOptions) {
+ if (options) {
+ this.#native = intoNativeHeatmapProvider(options);
+ }
+ }
+
+ static fromNative(nativeHeatmap: com.google.maps.android.heatmaps.HeatmapTileProvider) {
+ if (nativeHeatmap instanceof com.google.maps.android.heatmaps.HeatmapTileProvider) {
+ const heatmap = new HeatmapTileProvider();
+ heatmap.#native = nativeHeatmap;
+ return heatmap;
+ }
+ return null;
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ set opacity(opacity: number) {
+ this.native.setOpacity(opacity);
+ }
+
+ setGradient(gradients: IGradient[]): void {
+ this.native.setGradient(intoNativeHeatmapGradient(gradients));
+ }
+
+ set radius(radius: number) {
+ this.native.setRadius(radius);
+ }
+
+ set maxIntensity(maxIntensity: number) {
+ this.native.setMaxIntensity(maxIntensity);
+ }
+
+ setData(coordinates: Coordinate[]): void {
+ const data = new java.util.ArrayList();
+
+ coordinates.forEach((coordinate) => {
+ data.add(new com.google.android.gms.maps.model.LatLng(coordinate.lat, coordinate.lng));
+ });
+
+ this.native.setData(data);
+ }
+
+ getTile(x: number, y: number, z: number): com.google.android.gms.maps.model.Tile {
+ return this.native.getTile(x, y, z);
+ }
+}
+
+export class ClusterItem extends com.google.maps.android.clustering.ClusterItem {
+ constructor(public options: MarkerOptions) {
+ super({
+ getPosition: (): com.google.android.gms.maps.model.LatLng => {
+ return new com.google.android.gms.maps.model.LatLng(options?.position?.lat ?? 0, options?.position?.lng ?? 0);
+ },
+ getSnippet: (): string => {
+ return this.options?.snippet ?? '';
+ },
+ getTitle: (): string => {
+ return this.options?.title ?? '';
+ },
+ getZIndex: (): any => {
+ return java.lang.Float.valueOf(this.options?.zIndex ?? 0);
+ },
+ });
+ }
+}
+
+export class ClusterRenderer extends com.google.maps.android.clustering.view.DefaultClusterRenderer {
+ constructor(map: GoogleMap, clusterManager: ClusterManager) {
+ super(Utils.ad.getApplicationContext(), map.native, clusterManager.native);
+ }
+
+ override onBeforeClusterItemRendered(item: ClusterItem, opts: com.google.android.gms.maps.model.MarkerOptions): void {
+ super.onBeforeClusterItemRendered(item, opts);
+
+ if (typeof item.options?.draggable === 'boolean') {
+ opts.draggable(item.options.draggable);
+ }
+
+ if (typeof item.options?.anchorU === 'number' || typeof item.options?.anchorV === 'number') {
+ const anchorU = item.options?.anchorU ?? opts.getAnchorU();
+ const anchorV = item.options?.anchorV ?? opts?.getAnchorV();
+ opts.anchor(anchorU, anchorV);
+ }
+
+ if (item.options?.position) {
+ opts.position(new com.google.android.gms.maps.model.LatLng(item.options.position.lat, item.options.position.lng));
+ }
+
+ if (item.options?.title) {
+ opts.title(item.options.title);
+ }
+
+ if (item.options?.snippet) {
+ opts.snippet(item.options.snippet);
+ }
+
+ if (item.options?.icon) {
+ if (item.options?.icon instanceof android.graphics.Bitmap) {
+ const desc = com.google.android.gms.maps.model.BitmapDescriptorFactory.fromBitmap(item.options.icon);
+ opts.icon(desc);
+ } else if (item.options?.icon instanceof ImageSource) {
+ const desc = com.google.android.gms.maps.model.BitmapDescriptorFactory.fromBitmap(item.options.icon.android);
+ opts.icon(desc);
+ }
+ }
+
+ const color = intoNativeColor(item.options.color);
+
+ if (color !== null) {
+ opts.icon(com.google.android.gms.maps.model.BitmapDescriptorFactory.defaultMarker(hueFromColor(color)));
+ }
+
+ if (typeof item.options?.rotation === 'number') {
+ opts.rotation(item.options.rotation);
+ }
+
+ if (typeof item.options?.flat === 'boolean') {
+ opts.flat(item.options.flat);
+ }
+
+ if (typeof item.options?.zIndex === 'number') {
+ opts.zIndex(item.options.zIndex);
+ }
+ }
+}
+
+export class ClusterManager implements IClusterManager {
+ #native: com.google.maps.android.clustering.ClusterManager;
+
+ static fromNative(nativeClusterManager: com.google.maps.android.clustering.ClusterManager) {
+ if (nativeClusterManager instanceof com.google.maps.android.clustering.ClusterManager) {
+ const clusterManager = new ClusterManager();
+ clusterManager.#native = nativeClusterManager;
+ return clusterManager;
+ }
+ return null;
+ }
+
+ private setListeners() {
+ this.#native.setOnClusterClickListener(
+ new com.google.maps.android.clustering.ClusterManager.OnClusterClickListener({
+ onClusterClick: (cluster: com.google.maps.android.clustering.Cluster): boolean => {
+ return false;
+ },
+ })
+ );
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ get android() {
+ return this.native;
+ }
+
+ setRenderer(renderer: ClusterRenderer) {
+ this.native.setRenderer(renderer);
+ }
+
+ addItem(clusterItem: ClusterItem) {
+ this.native.addItem(clusterItem);
+ }
+
+ addItems(clusterItems: ClusterItem[]) {
+ const clusterItemArray = new java.util.ArrayList();
+ for (const clusterItem of clusterItems) {
+ clusterItemArray.add(clusterItem);
+ }
+ this.native.addItems(clusterItemArray);
+ }
+
+ removeItem(clusterItem: ClusterItem) {
+ this.native.removeItem(clusterItem);
+ }
+
+ removeItems(clusterItems: ClusterItem[]) {
+ this.native.removeItems(clusterItems as any);
+ }
+
+ clearItems() {
+ this.native.clearItems();
+ }
+
+ cluster() {
+ this.native.cluster();
+ }
+}
+
+/**
+ * EXPERIMENTAL - DO NOT USE
+ */
+export abstract class DataLayer {
+ abstract readonly native: T;
+
+ // setMap(map: com.google.android.gms.maps.GoogleMap) {
+ // this.native.setMap(map);
+ // }
+
+ // getDefaultPolygonStyle() {
+ // return this.native.getDefaultPolygonStyle();
+ // }
+
+ addLayerToMap() {
+ this.native.addLayerToMap();
+ }
+
+ // isLayerOnMap(): boolean {
+ // return this.native.isLayerOnMap();
+ // }
+
+ removeLayerFromMap() {
+ this.native.removeLayerFromMap();
+ }
+
+ // hasFeatures(): boolean {
+ // return this.native.hasFeatures();
+ // }
+
+ // getFeature(feature: any) {
+ // return this.native.getFeature(feature);
+ // }
+
+ // getFeatures(): any {
+ // return this.native.getFeatures();
+ // }
+
+ // addFeature(feature: com.google.maps.android.data.geojson.GeoJsonFeature) {
+ // return this.native.addFeature(feature);
+ // }
+
+ // removeFeature(feature: com.google.maps.android.data.geojson.GeoJsonFeature) {
+ // this.native.removeFeature(feature);
+ // }
+
+ get android() {
+ return this.native;
+ }
+
+ // public hasContainers(): boolean;
+ // public addKMLToMap(): void;
+ // public getDefaultPointStyle(): com.google.maps.android.data.geojson.GeoJsonPointStyle;
+ // public setOnFeatureClickListener(param0: com.google.maps.android.data.Layer.OnFeatureClickListener): void;
+ // public removeFeature(param0: com.google.maps.android.data.Feature): void;
+ // public getMap(): com.google.android.gms.maps.GoogleMap;
+ // public addGeoJsonToMap(): void;
+ // public getDefaultLineStringStyle(): com.google.maps.android.data.geojson.GeoJsonLineStringStyle;
+ // public storeRenderer(param0: com.google.maps.android.data.Renderer): void;
+ // public getContainers(): java.lang.Iterable;
+ // public getContainerFeature(param0: any): com.google.maps.android.data.Feature;
+ // public getGroundOverlays(): java.lang.Iterable;
+}
+
+export class GeoJsonGeometryStyle implements Partial {
+ constructor(private polygonStyle: com.google.maps.android.data.geojson.GeoJsonPolygonStyle, private lineStyle: com.google.maps.android.data.geojson.GeoJsonLineStringStyle, private pointStyle: com.google.maps.android.data.geojson.GeoJsonPointStyle) {}
+
+ get strokeColor() {
+ return new Color(this.polygonStyle.getStrokeColor());
+ }
+ set strokeColor(color: Color) {
+ this.polygonStyle.setStrokeColor(color.android);
+ this.lineStyle.setColor(color.android);
+ }
+
+ get fillColor() {
+ return new Color(this.polygonStyle.getFillColor());
+ }
+ set fillColor(color: Color) {
+ this.polygonStyle.setFillColor(color.android);
+ }
+
+ get width(): number {
+ return this.lineStyle.getWidth();
+ }
+ set width(width: number) {
+ this.lineStyle.setWidth(width);
+ this.polygonStyle.setStrokeWidth(width);
+ }
+
+ get title() {
+ return this.pointStyle.getTitle();
+ }
+ set title(title: string) {
+ this.pointStyle.setTitle(title);
+ }
+
+ get heading(): number {
+ return this.pointStyle.getRotation();
+ }
+ set heading(rotation: number) {
+ // Marker roation or rotation???
+ this.pointStyle.setRotation(rotation);
+ // this.pointStyle.setMarkerRotation(rotation);
+ }
+}
+
+abstract class BaseFeature implements IFeature {
+ abstract style: any;
+ abstract readonly native: T;
+
+ get android() {
+ return this.native;
+ }
+
+ get geometry() {
+ return Geometry.fromNative(this.native.getGeometry());
+ }
+
+ get id() {
+ return this.native.getId();
+ }
+
+ get properties() {
+ const props = {};
+
+ const iter = this.native.getPropertyKeys().iterator();
+ while (iter.hasNext()) {
+ const key = iter.next();
+ props[key] = this.native.getProperty(key);
+ }
+
+ return props;
+ }
+ set properties(value: any) {
+ Object.entries(value).forEach(([key, value]: [string, string]) => {
+ this.native.setProperty(key, value);
+ });
+ }
+}
+
+export class GeoJsonFeature extends BaseFeature {
+ #native: com.google.maps.android.data.geojson.GeoJsonFeature;
+ #style: GeoJsonGeometryStyle;
+
+ constructor() {
+ super();
+ }
+
+ static fromNative(nativeFeature: com.google.maps.android.data.geojson.GeoJsonFeature) {
+ if (nativeFeature instanceof com.google.maps.android.data.geojson.GeoJsonFeature) {
+ const feature = new GeoJsonFeature();
+ feature.#native = nativeFeature;
+ return feature;
+ }
+ return null;
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ get style() {
+ this.#style = new GeoJsonGeometryStyle(this.native.getPolygonStyle(), this.native.getLineStringStyle(), this.native.getPointStyle());
+ return this.#style;
+ }
+}
+
+export class Geometry implements IGeometry {
+ #native: com.google.maps.android.data.Geometry;
+
+ static fromNative(nativeGeometry: com.google.maps.android.data.Geometry) {
+ if (nativeGeometry instanceof com.google.maps.android.data.Geometry) {
+ const geometry = new Geometry();
+ geometry.#native = nativeGeometry;
+ return geometry;
+ }
+ return null;
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ get android() {
+ return this.native;
+ }
+
+ get type() {
+ return this.native.getGeometryType();
+ }
+
+ get geometries() {
+ return this.native.getGeometryObject();
+ }
+}
+
+export class GeoJsonLayer extends DataLayer implements IGeoJsonLayer {
+ #native: com.google.maps.android.data.geojson.GeoJsonLayer;
+ style: GeoJsonGeometryStyle;
+
+ static fromNative(nativeGeoJsonLayer: com.google.maps.android.data.geojson.GeoJsonLayer) {
+ if (nativeGeoJsonLayer instanceof com.google.maps.android.data.geojson.GeoJsonLayer) {
+ const geoJsonLayer = new GeoJsonLayer();
+ geoJsonLayer.#native = nativeGeoJsonLayer;
+ return geoJsonLayer;
+ }
+ return null;
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ get features() {
+ const features: GeoJsonFeature[] = [];
+ const nativeFeatures: java.lang.Iterable = this.native.getFeatures();
+
+ const iter = nativeFeatures.iterator();
+ while (iter.hasNext()) {
+ const feature = iter.next();
+ features.push(GeoJsonFeature.fromNative(feature));
+ }
+
+ return features;
+ }
+
+ // get bounds(): CoordinateBounds {
+ // const bounds = this.#native.getBoundingBox();
+ // if (bounds) {
+ // return {
+ // southwest: {
+ // lat: bounds?.southwest?.latitude,
+ // lng: bounds?.southwest?.longitude,
+ // },
+ // northeast: {
+ // lat: bounds?.northeast?.latitude,
+ // lng: bounds?.northeast?.longitude,
+ // },
+ // };
+ // }
+ // }
+
+ // toString() {
+ // return this.native.toString();
+ // }
+}
diff --git a/packages/google-maps-utils/index.d.ts b/packages/google-maps-utils/index.d.ts
new file mode 100644
index 00000000..a14f4e67
--- /dev/null
+++ b/packages/google-maps-utils/index.d.ts
@@ -0,0 +1,140 @@
+import { Color } from '@nativescript/core';
+import { GoogleMap } from '@nativescript/google-maps';
+
+// export * from './experimental/datalayer';
+// export * from './experimental/iconfactory';
+export * from './utils';
+
+export function installMixins();
+
+declare module '@nativescript/google-maps' {
+ interface GoogleMap {
+ heatmapProvider(options: HeatmapOptions): HeatmapTileProvider;
+ clusterManager(markers: MarkerOptions[]): ClusterManager;
+
+ addGeoJson(geoJson: GeoJSON, styleOptions: IGeometryStyle): GeoJsonLayer;
+ removeGeoJson(geoJsonLayer: GeoJsonLayer): void;
+ }
+}
+
+export class GoogleMapUtils {
+ heatmapProvider(options: HeatmapOptions): HeatmapTileProvider;
+ clusterManager(markers: MarkerOptions[]): ClusterManager;
+
+ addGeoJson(geoJson: GeoJSON, styleOptions: IGeometryStyle): GeoJsonLayer;
+ removeGeoJson(geoJsonLayer: GeoJsonLayer): void;
+}
+
+export interface IGradient {
+ color: Color | string;
+ stop: number;
+}
+
+export interface HeatmapOptions {
+ coordinates: Coordinate[];
+ opacity?: number;
+ radius?: number;
+ maxIntensity?: number;
+ gradient?: IGradient[];
+}
+
+export interface IHeatmapTileProvider {
+ setData: (coordinates: Coordinate[]) => void;
+ setGradient: (gradient: IGradient[]) => void;
+ opacity: number;
+ radius: number;
+ maxIntensity: number;
+}
+
+export class HeatmapTileProvider implements IHeatmapTileProvider {
+ constructor(options: HeatmapOptions);
+ static fromNative: (nativeHeatmap: any) => HeatmapTileProvider;
+ setData: (coordinates: Coordinate[]) => void;
+ setGradient: (gradient: IGradient[]) => void;
+ opacity: number;
+ radius: number;
+ maxIntensity: number;
+ native: any;
+ android: any /*com.google.maps.android.heatmaps.HeatmapTileProvider*/;
+ ios: any /*GMUHeatmapTileLayer*/;
+}
+
+export class ClusterItem {
+ constructor(options: MarkerOptions);
+}
+
+export class ClusterRenderer {
+ constructor(private map: GoogleMap, private manager: ClusterManager);
+ android?: any;
+ ios?: any;
+ native?: any;
+}
+
+export interface IClusterManager {
+ addItems: (clusterItems: ClusterItem[]) => void;
+ addItem: (clusterItem: ClusterItem) => void;
+ removeItems: (clusterItems: ClusterItem[]) => void;
+ removeItem: (clusterItem: ClusterItem) => void;
+ clearItems: () => void;
+ cluster: () => void;
+ setRenderer: (clusterRenderer: any) => void;
+ android?: any;
+ ios?: any;
+ native?: any;
+}
+
+export class ClusterManager implements Partial {
+ onClusterTap(cluster: any) {
+ throw new Error('Method not implemented.');
+ }
+ static fromNative: (nativeClusterManager) => ClusterManager;
+ addItems: (clusterItems: ClusterItem[]) => void;
+ addItem: (clusterItem: ClusterItem) => void;
+ removeItems: (clusterItems: ClusterItem[]) => void;
+ removeItem: (clusterItem: ClusterItem) => void;
+ clearItems: () => void;
+ cluster: () => void;
+ setRenderer: (clusterRenderer: ClusterRenderer) => void;
+ android?: any;
+ ios?: any;
+ native?: any;
+}
+
+export interface IGeoJsonLayer {
+ style: GeometryStyle;
+ addLayerToMap: () => void;
+ removeLayerFromMap: () => void;
+}
+
+export class GeoJsonLayer implements IGeoJsonLayer {
+ ios: any;
+ android: any;
+ native: any;
+ style: GeometryStyle;
+ features: GeoJsonFeature[];
+ constructor(map: GoogleMap, geojson: any, styles?: Partial);
+ addLayerToMap: () => void;
+ removeLayerFromMap: () => void;
+}
+
+export interface IGeometryStyle {
+ strokeColor?: Color;
+ fillColor?: Color;
+ width?: number;
+ scale?: number;
+ heading?: number;
+ anchor?: [number, number];
+ iconUrl?: string | null;
+ title?: string | null;
+}
+
+export interface IGeometry {
+ type: string;
+ geometries: any;
+}
+
+export interface IFeature {
+ geometry: any;
+ properties: any;
+ id: any;
+}
diff --git a/packages/google-maps-utils/index.ios.ts b/packages/google-maps-utils/index.ios.ts
new file mode 100644
index 00000000..b523a374
--- /dev/null
+++ b/packages/google-maps-utils/index.ios.ts
@@ -0,0 +1,356 @@
+import { Color, encoding } from '@nativescript/core';
+import { GeoJSON } from 'geojson';
+import { Coordinate, GoogleMap, ITileProvider, MarkerOptions, intoNativeMarkerOptions } from '@nativescript/google-maps';
+import { HeatmapOptions, IClusterManager, IFeature, IGeoJsonLayer, IGeometry, IGeometryStyle, IGradient, IHeatmapTileProvider, intoNativeClusterManager, intoNativeHeatmapGradient, intoNativeHeatmapProvider } from '.';
+import { applyMixins } from './utils/common';
+
+// export * from './experimental/datalayer';
+// export * from './experimental/iconfactory';
+export * from './utils';
+
+let UNIQUE_STYLE_ID = 0;
+
+let mixinInstalled = false;
+export function overrideGoogleMap() {
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
+ const GMap = require('@nativescript/google-maps').GoogleMap;
+ applyMixins(GMap, [GoogleMapUtils], { after: true });
+}
+
+export function installMixins() {
+ if (!mixinInstalled) {
+ mixinInstalled = true;
+ overrideGoogleMap();
+ }
+}
+
+export class GoogleMapUtils {
+ clusterManager(markers: MarkerOptions[]) {
+ const clusterManager = ClusterManager.fromNative(intoNativeClusterManager(this as unknown as GoogleMap));
+
+ const clusters = markers.map((marker) => new ClusterItem(marker));
+ clusterManager.addItems(clusters);
+
+ clusterManager.cluster();
+
+ return clusterManager;
+ }
+
+ addGeoJson(geoJson: GeoJSON, styleOptions: IGeometryStyle) {
+ if ((this as unknown as GoogleMap) && geoJson) {
+ const style = new GeometryStyle(styleOptions);
+
+ const jsonString = new NSString({ UTF8String: JSON.stringify(geoJson) });
+ const parser = new GMUGeoJSONParser({ data: jsonString.dataUsingEncoding(encoding.UTF_8) });
+ parser.parse();
+
+ const features = parser.features;
+ for (const feature of features) {
+ feature.style = style.native;
+ }
+
+ const renderer = new GMUGeometryRenderer({ map: (this as unknown as GoogleMap).native, geometries: features });
+
+ const layer = GeoJsonLayer.fromNative(renderer);
+
+ layer.addLayerToMap();
+
+ return layer;
+ }
+ return null;
+ }
+
+ removeGeoJson(geoJson: GeoJsonLayer) {
+ if (geoJson) {
+ geoJson.removeLayerFromMap();
+ }
+ }
+}
+
+export class HeatmapTileProvider implements ITileProvider, IHeatmapTileProvider {
+ #native: GMUHeatmapTileLayer;
+
+ constructor(options?: HeatmapOptions) {
+ this.#native = intoNativeHeatmapProvider(options);
+ }
+
+ static fromNative(nativeHeatmap: GMUHeatmapTileLayer) {
+ if (nativeHeatmap instanceof GMUHeatmapTileLayer) {
+ const heatmapTileProvider = new HeatmapTileProvider();
+ heatmapTileProvider.#native = nativeHeatmap;
+ return heatmapTileProvider;
+ }
+ return null;
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ set opacity(opacity: number) {
+ this.native.opacity = opacity;
+ }
+
+ setGradient(gradients: IGradient[]): void {
+ this.native.gradient = intoNativeHeatmapGradient(gradients);
+ }
+
+ set radius(radius: number) {
+ this.native.radius = radius;
+ }
+
+ set maxIntensity(maxIntensity: number) {
+ this.native.maximumZoomIntensity = maxIntensity;
+ }
+
+ setData(coordinates: Coordinate[]): void {
+ this.native.weightedData = coordinates.map((coordinate) => {
+ return GMUWeightedLatLng.alloc().initWithCoordinateIntensity(CLLocationCoordinate2DMake(coordinate.lat, coordinate.lng), 1.0);
+ }) as any;
+ }
+
+ getTile(x: number, y: number, z: number): UIImage {
+ return this.native.tileForXYZoom(x, y, z);
+ }
+}
+
+export class ClusterItem {
+ #native: GMSMarker;
+
+ constructor(options: MarkerOptions) {
+ this.#native = intoNativeMarkerOptions(options);
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ get ios() {
+ return this.native;
+ }
+}
+
+export class ClusterRenderer {
+ #native: GMUClusterRenderer;
+
+ constructor(map: GoogleMap, clusterManager: ClusterManager) {
+ const iconGenerator = GMUDefaultClusterIconGenerator.alloc().init();
+ this.#native = GMUDefaultClusterRenderer.alloc().initWithMapViewClusterIconGenerator(map.native, iconGenerator);
+ }
+
+ get native() {
+ return this.#native;
+ }
+}
+
+export class ClusterManager implements Partial {
+ #native: GMUClusterManager;
+
+ static fromNative(nativeClusterManager: GMUClusterManager) {
+ if (nativeClusterManager instanceof GMUClusterManager) {
+ const clusterManager = new ClusterManager();
+ clusterManager.#native = nativeClusterManager;
+ return clusterManager;
+ }
+ return null;
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ get ios() {
+ return this.#native;
+ }
+
+ setRenderer(renderer) {
+ // TODO;
+ }
+
+ addItem(clusterItem: ClusterItem) {
+ this.native.addItem(clusterItem.native);
+ }
+
+ addItems(clusterItems: ClusterItem[]) {
+ this.native.addItems(clusterItems.map((item) => item.native));
+ }
+
+ removeItem(clusterItem: ClusterItem) {
+ this.native.removeItem(clusterItem.native);
+ }
+
+ removeItems(clusterItems: ClusterItem[]) {
+ clusterItems.forEach((item) => {
+ this.native.removeItem(item.native);
+ });
+ }
+
+ clearItems() {
+ this.native.clearItems();
+ }
+
+ cluster() {
+ this.native.cluster();
+ }
+}
+
+export class GeometryStyle implements IGeometryStyle {
+ #native: GMUStyle;
+
+ constructor(public geometryStyles: Partial) {
+ Object.assign(this, geometryStyles);
+
+ this.#native = new GMUStyle({
+ styleID: `google-maps-utils-style-${UNIQUE_STYLE_ID++}`,
+ strokeColor: this.strokeColor?.ios ?? null,
+ fillColor: this.fillColor?.ios ?? null,
+ width: this.width ?? 1,
+ scale: this.scale ?? 0,
+ heading: this.heading ?? 0,
+ anchor: CGPointMake(this.anchor?.[0] ?? 0, this.anchor?.[1] ?? 0),
+ iconUrl: this.iconUrl ?? null,
+ title: this.title ?? null,
+ hasFill: !!this.fillColor,
+ hasStroke: !!this.strokeColor,
+ } as any);
+ }
+
+ strokeColor: Color;
+ fillColor: Color;
+ width: number;
+ scale: number;
+ heading: number;
+ anchor: [number, number];
+ iconUrl: string;
+ title: string;
+
+ get native() {
+ return this.#native;
+ }
+}
+
+export class GeoJsonLayer implements IGeoJsonLayer {
+ #native: GMUGeometryRenderer;
+ // #parser: GMUGeoJSONParser;
+ style: GeometryStyle;
+
+ // constructor(private map: GoogleMap, private geometries: any, private styles?: Partial) {
+ // this.style = new GeometryStyle(styles);
+
+ // const jsonString = new NSString({ UTF8String: JSON.stringify(geometries) });
+ // this.#parser = new GMUGeoJSONParser({ data: jsonString.dataUsingEncoding(encoding.UTF_8) });
+ // this.#parser.parse();
+
+ // const features = this.#parser.features;
+ // for (const feature of features) {
+ // feature.style = this.style.native;
+ // }
+
+ // this.#native = new GMUGeometryRenderer({ map: this.map.native, geometries: features });
+ // }
+
+ static fromNative(nativeGeoJsonLayer: GMUGeometryRenderer) {
+ if (nativeGeoJsonLayer instanceof GMUGeometryRenderer) {
+ const geoJsonLayer = new GeoJsonLayer();
+ geoJsonLayer.#native = nativeGeoJsonLayer;
+ return geoJsonLayer;
+ }
+ return null;
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ get ios() {
+ return this.native;
+ }
+
+ get features() {
+ // const features = [];
+ // for (const feature of this.#parser.features) {
+ // const f = feature as GMUGeometryContainer;
+
+ // GeoJsonFeature.fromNative(f);
+ // f.geometry;
+ // f.style;
+ // }
+ return null;
+ }
+
+ addLayerToMap() {
+ this.native.render();
+ }
+
+ removeLayerFromMap() {
+ this.native.clear();
+ }
+}
+
+export class GeoJsonFeature implements IFeature {
+ #native: GMUGeometryCollection;
+
+ static fromNative(nativeGeometryContainer: GMUGeometryCollection) {
+ if (nativeGeometryContainer instanceof GMUGeometryCollection) {
+ const geoJsonFeature = new GeoJsonFeature();
+ geoJsonFeature.#native = nativeGeometryContainer;
+ return geoJsonFeature;
+ }
+ return null;
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ get ios() {
+ return this.#native;
+ }
+
+ get geometry() {
+ const geometries = [];
+
+ for (const geometry of this.native.geometries) {
+ geometries.push(Geometry.fromNative(geometry));
+ }
+
+ return geometries;
+ }
+
+ get properties() {
+ return;
+ }
+
+ get id() {
+ return this.native.description;
+ }
+}
+
+export class Geometry implements IGeometry {
+ #native: GMUGeometry;
+
+ static fromNative(nativeGeometry: GMUGeometry) {
+ if (nativeGeometry) {
+ const geometry = new Geometry();
+ geometry.#native = nativeGeometry;
+ return geometry;
+ }
+ return null;
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ get ios() {
+ return this.#native;
+ }
+
+ get type() {
+ return this.#native.type;
+ }
+
+ get geometries() {
+ return this.native;
+ }
+}
diff --git a/packages/google-maps-utils/package.json b/packages/google-maps-utils/package.json
new file mode 100644
index 00000000..ad0e4708
--- /dev/null
+++ b/packages/google-maps-utils/package.json
@@ -0,0 +1,38 @@
+{
+ "name": "@nativescript/google-maps-utils",
+ "version": "1.0.0",
+ "description": "Add a plugin description",
+ "main": "index",
+ "typings": "index.d.ts",
+ "nativescript": {
+ "platforms": {
+ "ios": "6.0.0",
+ "android": "6.0.0"
+ }
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/NativeScript/plugins.git"
+ },
+ "keywords": [
+ "NativeScript",
+ "JavaScript",
+ "TypeScript",
+ "iOS",
+ "Android"
+ ],
+ "devDependencies": {
+ "@types/geojson": "^7946.0.7"
+ },
+ "author": {
+ "name": "NativeScript",
+ "email": "oss@nativescript.org"
+ },
+ "bugs": {
+ "url": "https://github.com/NativeScript/plugins/issues"
+ },
+ "license": "Apache-2.0",
+ "homepage": "https://github.com/NativeScript/plugins",
+ "readmeFilename": "README.md",
+ "bootstrapper": "@nativescript/plugin-seed"
+}
diff --git a/packages/google-maps-utils/platforms/android/include.gradle b/packages/google-maps-utils/platforms/android/include.gradle
new file mode 100644
index 00000000..60aa0250
--- /dev/null
+++ b/packages/google-maps-utils/platforms/android/include.gradle
@@ -0,0 +1,3 @@
+dependencies {
+ implementation 'com.google.maps.android:android-maps-utils:3.4.0'
+}
diff --git a/packages/google-maps-utils/platforms/ios/Podfile b/packages/google-maps-utils/platforms/ios/Podfile
new file mode 100644
index 00000000..beb91951
--- /dev/null
+++ b/packages/google-maps-utils/platforms/ios/Podfile
@@ -0,0 +1 @@
+pod 'Google-Maps-iOS-Utils', '4.1.0'
diff --git a/packages/google-maps-utils/project.json b/packages/google-maps-utils/project.json
new file mode 100644
index 00000000..a27a83ab
--- /dev/null
+++ b/packages/google-maps-utils/project.json
@@ -0,0 +1,72 @@
+{
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "projectType": "library",
+ "sourceRoot": "packages/google-maps-utils",
+ "targets": {
+ "build": {
+ "executor": "@nrwl/js:tsc",
+ "options": {
+ "outputPath": "dist/packages/google-maps-utils",
+ "tsConfig": "packages/google-maps-utils/tsconfig.json",
+ "packageJson": "packages/google-maps-utils/package.json",
+ "main": "packages/google-maps-utils/index.d.ts",
+ "assets": [
+ "packages/google-maps-utils/*.md",
+ "packages/google-maps-utils/index.d.ts",
+ "LICENSE",
+ {
+ "glob": "**/*",
+ "input": "packages/google-maps-utils/platforms/",
+ "output": "./platforms/"
+ }
+ ],
+ "dependsOn": [
+ {
+ "target": "build.all",
+ "projects": "dependencies"
+ }
+ ]
+ }
+ },
+ "build.all": {
+ "executor": "@nrwl/workspace:run-commands",
+ "options": {
+ "commands": [
+ "node tools/scripts/build-finish.ts google-maps-utils"
+ ],
+ "parallel": false
+ },
+ "outputs": [
+ "dist/packages/google-maps-utils"
+ ],
+ "dependsOn": [
+ {
+ "target": "build.all",
+ "projects": "dependencies"
+ },
+ {
+ "target": "build",
+ "projects": "self"
+ }
+ ]
+ },
+ "focus": {
+ "executor": "@nrwl/workspace:run-commands",
+ "options": {
+ "commands": [
+ "nx g @nativescript/plugin-tools:focus-packages google-maps-utils,google-maps"
+ ],
+ "parallel": false
+ }
+ },
+ "lint": {
+ "executor": "@nrwl/linter:eslint",
+ "options": {
+ "lintFilePatterns": [
+ "packages/google-maps-utils/**/*.ts"
+ ]
+ }
+ }
+ },
+ "tags": []
+}
diff --git a/packages/google-maps-utils/references.d.ts b/packages/google-maps-utils/references.d.ts
new file mode 100644
index 00000000..548604ba
--- /dev/null
+++ b/packages/google-maps-utils/references.d.ts
@@ -0,0 +1,2 @@
+///
+///
diff --git a/packages/google-maps-utils/tsconfig.json b/packages/google-maps-utils/tsconfig.json
new file mode 100644
index 00000000..aed7323d
--- /dev/null
+++ b/packages/google-maps-utils/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc",
+ "rootDir": "."
+ },
+ "exclude": ["**/*.spec.ts", "**/*.test.ts", "angular"],
+ "include": ["**/*.ts", "references.d.ts"]
+}
diff --git a/packages/google-maps-utils/typings/android.d.ts b/packages/google-maps-utils/typings/android.d.ts
new file mode 100644
index 00000000..855fb053
--- /dev/null
+++ b/packages/google-maps-utils/typings/android.d.ts
@@ -0,0 +1,8749 @@
+///
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export class BuildConfig {
+ public static class: java.lang.Class;
+ public static DEBUG: boolean;
+ public static LIBRARY_PACKAGE_NAME: string;
+ public static BUILD_TYPE: string;
+ public static TRAVIS: string;
+ public constructor();
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export class MathUtil {
+ public static class: java.lang.Class;
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export class PolyUtil {
+ public static class: java.lang.Class;
+ public static DEFAULT_TOLERANCE: number;
+ public static distanceToLine(param0: com.google.android.gms.maps.model.LatLng, param1: com.google.android.gms.maps.model.LatLng, param2: com.google.android.gms.maps.model.LatLng): number;
+ public static isLocationOnEdge(param0: com.google.android.gms.maps.model.LatLng, param1: java.util.List, param2: boolean): boolean;
+ public static isLocationOnEdge(param0: com.google.android.gms.maps.model.LatLng, param1: java.util.List, param2: boolean, param3: number): boolean;
+ public static locationIndexOnPath(param0: com.google.android.gms.maps.model.LatLng, param1: java.util.List, param2: boolean, param3: number): number;
+ public static isClosedPolygon(param0: java.util.List): boolean;
+ public static locationIndexOnPath(param0: com.google.android.gms.maps.model.LatLng, param1: java.util.List, param2: boolean): number;
+ public static isLocationOnPath(param0: com.google.android.gms.maps.model.LatLng, param1: java.util.List, param2: boolean): boolean;
+ public static containsLocation(param0: com.google.android.gms.maps.model.LatLng, param1: java.util.List, param2: boolean): boolean;
+ public static isLocationOnPath(param0: com.google.android.gms.maps.model.LatLng, param1: java.util.List, param2: boolean, param3: number): boolean;
+ public static locationIndexOnEdgeOrPath(param0: com.google.android.gms.maps.model.LatLng, param1: java.util.List, param2: boolean, param3: boolean, param4: number): number;
+ public static containsLocation(param0: number, param1: number, param2: java.util.List, param3: boolean): boolean;
+ public static decode(param0: string): java.util.List;
+ public static simplify(param0: java.util.List, param1: number): java.util.List;
+ public static encode(param0: java.util.List): string;
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export class SphericalUtil {
+ public static class: java.lang.Class;
+ public static computeArea(param0: java.util.List): number;
+ public static computeSignedArea(param0: java.util.List): number;
+ public static computeOffset(param0: com.google.android.gms.maps.model.LatLng, param1: number, param2: number): com.google.android.gms.maps.model.LatLng;
+ public static computeLength(param0: java.util.List): number;
+ public static interpolate(param0: com.google.android.gms.maps.model.LatLng, param1: com.google.android.gms.maps.model.LatLng, param2: number): com.google.android.gms.maps.model.LatLng;
+ public static computeHeading(param0: com.google.android.gms.maps.model.LatLng, param1: com.google.android.gms.maps.model.LatLng): number;
+ public static computeDistanceBetween(param0: com.google.android.gms.maps.model.LatLng, param1: com.google.android.gms.maps.model.LatLng): number;
+ public static computeOffsetOrigin(param0: com.google.android.gms.maps.model.LatLng, param1: number, param2: number): com.google.android.gms.maps.model.LatLng;
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export module clustering {
+ export class Cluster extends java.lang.Object {
+ public static class: java.lang.Class>;
+ /**
+ * Constructs a new instance of the com.google.maps.android.clustering.Cluster interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: { getPosition(): com.google.android.gms.maps.model.LatLng; getItems(): java.util.Collection; getSize(): number });
+ public constructor();
+ public getSize(): number;
+ public getPosition(): com.google.android.gms.maps.model.LatLng;
+ public getItems(): java.util.Collection;
+ }
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export module clustering {
+ export class ClusterItem {
+ public static class: java.lang.Class;
+ /**
+ * Constructs a new instance of the com.google.maps.android.clustering.ClusterItem interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: { getPosition(): com.google.android.gms.maps.model.LatLng; getTitle(): string; getSnippet(): string; getZIndex(): java.lang.Float });
+ public constructor();
+ public getZIndex(): java.lang.Float;
+ public getPosition(): com.google.android.gms.maps.model.LatLng;
+ public getSnippet(): string;
+ public getTitle(): string;
+ }
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export module clustering {
+ export class ClusterManager extends java.lang.Object {
+ public static class: java.lang.Class>;
+ public setOnClusterItemInfoWindowClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterItemInfoWindowClickListener): void;
+ public updateItem(param0: T): boolean;
+ public removeItems(param0: java.util.Collection): boolean;
+ public setAlgorithm(param0: com.google.maps.android.clustering.algo.ScreenBasedAlgorithm): void;
+ public setAnimation(param0: boolean): void;
+ public getRenderer(): com.google.maps.android.clustering.view.ClusterRenderer;
+ public getAlgorithm(): com.google.maps.android.clustering.algo.Algorithm;
+ public setOnClusterInfoWindowLongClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterInfoWindowLongClickListener): void;
+ public setAlgorithm(param0: com.google.maps.android.clustering.algo.Algorithm): void;
+ public onInfoWindowClick(param0: com.google.android.gms.maps.model.Marker): void;
+ public getClusterMarkerCollection(): com.google.maps.android.collections.MarkerManager.Collection;
+ public setOnClusterItemClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterItemClickListener): void;
+ public onMarkerClick(param0: com.google.android.gms.maps.model.Marker): boolean;
+ public constructor(param0: globalAndroid.content.Context, param1: com.google.android.gms.maps.GoogleMap);
+ public clearItems(): void;
+ public setOnClusterInfoWindowClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterInfoWindowClickListener): void;
+ public setOnClusterItemInfoWindowLongClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterItemInfoWindowLongClickListener): void;
+ public constructor(param0: globalAndroid.content.Context, param1: com.google.android.gms.maps.GoogleMap, param2: com.google.maps.android.collections.MarkerManager);
+ public setOnClusterClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterClickListener): void;
+ public addItems(param0: java.util.Collection): boolean;
+ public addItem(param0: T): boolean;
+ public onCameraIdle(): void;
+ public cluster(): void;
+ public setRenderer(param0: com.google.maps.android.clustering.view.ClusterRenderer): void;
+ public removeItem(param0: T): boolean;
+ public getMarkerCollection(): com.google.maps.android.collections.MarkerManager.Collection;
+ public getMarkerManager(): com.google.maps.android.collections.MarkerManager;
+ }
+ export module ClusterManager {
+ export class ClusterTask extends globalAndroid.os.AsyncTask> {
+ public static class: java.lang.Class;
+ public doInBackground(param0: androidNative.Array): java.util.Set;
+ public onPostExecute(param0: java.util.Set): void;
+ }
+ export class OnClusterClickListener extends java.lang.Object {
+ public static class: java.lang.Class>;
+ /**
+ * Constructs a new instance of the com.google.maps.android.clustering.ClusterManager$OnClusterClickListener interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: { onClusterClick(param0: com.google.maps.android.clustering.Cluster): boolean });
+ public constructor();
+ public onClusterClick(param0: com.google.maps.android.clustering.Cluster): boolean;
+ }
+ export class OnClusterInfoWindowClickListener extends java.lang.Object {
+ public static class: java.lang.Class>;
+ /**
+ * Constructs a new instance of the com.google.maps.android.clustering.ClusterManager$OnClusterInfoWindowClickListener interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: { onClusterInfoWindowClick(param0: com.google.maps.android.clustering.Cluster): void });
+ public constructor();
+ public onClusterInfoWindowClick(param0: com.google.maps.android.clustering.Cluster): void;
+ }
+ export class OnClusterInfoWindowLongClickListener extends java.lang.Object {
+ public static class: java.lang.Class>;
+ /**
+ * Constructs a new instance of the com.google.maps.android.clustering.ClusterManager$OnClusterInfoWindowLongClickListener interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: { onClusterInfoWindowLongClick(param0: com.google.maps.android.clustering.Cluster): void });
+ public constructor();
+ public onClusterInfoWindowLongClick(param0: com.google.maps.android.clustering.Cluster): void;
+ }
+ export class OnClusterItemClickListener extends java.lang.Object {
+ public static class: java.lang.Class>;
+ /**
+ * Constructs a new instance of the com.google.maps.android.clustering.ClusterManager$OnClusterItemClickListener interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: { onClusterItemClick(param0: T): boolean });
+ public constructor();
+ public onClusterItemClick(param0: T): boolean;
+ }
+ export class OnClusterItemInfoWindowClickListener extends java.lang.Object {
+ public static class: java.lang.Class>;
+ /**
+ * Constructs a new instance of the com.google.maps.android.clustering.ClusterManager$OnClusterItemInfoWindowClickListener interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: { onClusterItemInfoWindowClick(param0: T): void });
+ public constructor();
+ public onClusterItemInfoWindowClick(param0: T): void;
+ }
+ export class OnClusterItemInfoWindowLongClickListener extends java.lang.Object {
+ public static class: java.lang.Class>;
+ /**
+ * Constructs a new instance of the com.google.maps.android.clustering.ClusterManager$OnClusterItemInfoWindowLongClickListener interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: { onClusterItemInfoWindowLongClick(param0: T): void });
+ public constructor();
+ public onClusterItemInfoWindowLongClick(param0: T): void;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export module clustering {
+ export module algo {
+ export abstract class AbstractAlgorithm extends com.google.maps.android.clustering.algo.Algorithm {
+ public static class: java.lang.Class>;
+ public constructor();
+ public addItems(param0: java.util.Collection): boolean;
+ public setMaxDistanceBetweenClusteredItems(param0: number): void;
+ public getClusters(param0: number): java.util.Set;
+ public unlock(): void;
+ public addItem(param0: any): boolean;
+ public removeItem(param0: any): boolean;
+ public getItems(): java.util.Collection;
+ public clearItems(): void;
+ public lock(): void;
+ public updateItem(param0: any): boolean;
+ public getMaxDistanceBetweenClusteredItems(): number;
+ public removeItems(param0: java.util.Collection): boolean;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export module clustering {
+ export module algo {
+ export class Algorithm extends java.lang.Object {
+ public static class: java.lang.Class>;
+ /**
+ * Constructs a new instance of the com.google.maps.android.clustering.algo.Algorithm interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: { addItem(param0: T): boolean; addItems(param0: java.util.Collection): boolean; clearItems(): void; removeItem(param0: T): boolean; updateItem(param0: T): boolean; removeItems(param0: java.util.Collection): boolean; getClusters(param0: number): java.util.Set; getItems(): java.util.Collection; setMaxDistanceBetweenClusteredItems(param0: number): void; getMaxDistanceBetweenClusteredItems(): number; lock(): void; unlock(): void });
+ public constructor();
+ public addItem(param0: T): boolean;
+ public updateItem(param0: T): boolean;
+ public addItems(param0: java.util.Collection): boolean;
+ public clearItems(): void;
+ public setMaxDistanceBetweenClusteredItems(param0: number): void;
+ public lock(): void;
+ public getClusters(param0: number): java.util.Set;
+ public removeItem(param0: T): boolean;
+ public getMaxDistanceBetweenClusteredItems(): number;
+ public unlock(): void;
+ public removeItems(param0: java.util.Collection): boolean;
+ public getItems(): java.util.Collection;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export module clustering {
+ export module algo {
+ export class GridBasedAlgorithm extends com.google.maps.android.clustering.algo.AbstractAlgorithm {
+ public static class: java.lang.Class>;
+ public constructor();
+ public addItems(param0: java.util.Collection): boolean;
+ public setMaxDistanceBetweenClusteredItems(param0: number): void;
+ public getClusters(param0: number): java.util.Set;
+ public addItem(param0: any): boolean;
+ public unlock(): void;
+ public removeItem(param0: any): boolean;
+ public getItems(): java.util.Collection;
+ public clearItems(): void;
+ public lock(): void;
+ public updateItem(param0: any): boolean;
+ public getMaxDistanceBetweenClusteredItems(): number;
+ public removeItems(param0: java.util.Collection): boolean;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export module clustering {
+ export module algo {
+ export class NonHierarchicalDistanceBasedAlgorithm extends com.google.maps.android.clustering.algo.AbstractAlgorithm {
+ public static class: java.lang.Class>;
+ public constructor();
+ public addItems(param0: java.util.Collection): boolean;
+ public getClusteringItems(param0: com.google.maps.android.quadtree.PointQuadTree>, param1: number): java.util.Collection>;
+ public setMaxDistanceBetweenClusteredItems(param0: number): void;
+ public getClusters(param0: number): java.util.Set;
+ public addItem(param0: any): boolean;
+ public unlock(): void;
+ public removeItem(param0: any): boolean;
+ public getItems(): java.util.Collection;
+ public clearItems(): void;
+ public lock(): void;
+ public updateItem(param0: any): boolean;
+ public getMaxDistanceBetweenClusteredItems(): number;
+ public removeItems(param0: java.util.Collection): boolean;
+ }
+ export module NonHierarchicalDistanceBasedAlgorithm {
+ export class QuadItem extends java.lang.Object {
+ public static class: java.lang.Class>;
+ public getItems(): java.util.Set;
+ public equals(param0: any): boolean;
+ public getPoint(): com.google.maps.android.geometry.Point;
+ public getItems(): java.util.Collection;
+ public getSize(): number;
+ public hashCode(): number;
+ public getPosition(): com.google.android.gms.maps.model.LatLng;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export module clustering {
+ export module algo {
+ export class NonHierarchicalViewBasedAlgorithm extends com.google.maps.android.clustering.algo.NonHierarchicalDistanceBasedAlgorithm implements com.google.maps.android.clustering.algo.ScreenBasedAlgorithm {
+ public static class: java.lang.Class>;
+ public constructor();
+ public addItems(param0: java.util.Collection): boolean;
+ public constructor(param0: number, param1: number);
+ public getClusteringItems(param0: com.google.maps.android.quadtree.PointQuadTree>, param1: number): java.util.Collection>;
+ public setMaxDistanceBetweenClusteredItems(param0: number): void;
+ public getClusters(param0: number): java.util.Set;
+ public onCameraChange(param0: com.google.android.gms.maps.model.CameraPosition): void;
+ public addItem(param0: any): boolean;
+ public unlock(): void;
+ public updateViewSize(param0: number, param1: number): void;
+ public removeItem(param0: any): boolean;
+ public getItems(): java.util.Collection;
+ public clearItems(): void;
+ public lock(): void;
+ public shouldReclusterOnMapMovement(): boolean;
+ public updateItem(param0: any): boolean;
+ public getMaxDistanceBetweenClusteredItems(): number;
+ public removeItems(param0: java.util.Collection): boolean;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export module clustering {
+ export module algo {
+ export class PreCachingAlgorithmDecorator extends com.google.maps.android.clustering.algo.AbstractAlgorithm {
+ public static class: java.lang.Class>;
+ public constructor();
+ public addItems(param0: java.util.Collection): boolean;
+ public setMaxDistanceBetweenClusteredItems(param0: number): void;
+ public constructor(param0: com.google.maps.android.clustering.algo.Algorithm);
+ public getClusters(param0: number): java.util.Set;
+ public addItem(param0: any): boolean;
+ public unlock(): void;
+ public removeItem(param0: any): boolean;
+ public getItems(): java.util.Collection;
+ public clearItems(): void;
+ public lock(): void;
+ public updateItem(param0: any): boolean;
+ public getMaxDistanceBetweenClusteredItems(): number;
+ public removeItems(param0: java.util.Collection): boolean;
+ }
+ export module PreCachingAlgorithmDecorator {
+ export class PrecacheRunnable {
+ public static class: java.lang.Class;
+ public constructor(param0: com.google.maps.android.clustering.algo.PreCachingAlgorithmDecorator, param1: number);
+ public run(): void;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export module clustering {
+ export module algo {
+ export class ScreenBasedAlgorithm extends com.google.maps.android.clustering.algo.Algorithm {
+ public static class: java.lang.Class>;
+ /**
+ * Constructs a new instance of the com.google.maps.android.clustering.algo.ScreenBasedAlgorithm interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: {
+ shouldReclusterOnMapMovement(): boolean;
+ onCameraChange(param0: com.google.android.gms.maps.model.CameraPosition): void;
+ addItem(param0: any): boolean;
+ addItems(param0: java.util.Collection): boolean;
+ clearItems(): void;
+ removeItem(param0: any): boolean;
+ updateItem(param0: any): boolean;
+ removeItems(param0: java.util.Collection): boolean;
+ getClusters(param0: number): java.util.Set;
+ getItems(): java.util.Collection;
+ setMaxDistanceBetweenClusteredItems(param0: number): void;
+ getMaxDistanceBetweenClusteredItems(): number;
+ lock(): void;
+ unlock(): void;
+ });
+ public constructor();
+ public addItems(param0: java.util.Collection): boolean;
+ public setMaxDistanceBetweenClusteredItems(param0: number): void;
+ public getClusters(param0: number): java.util.Set;
+ public onCameraChange(param0: com.google.android.gms.maps.model.CameraPosition): void;
+ public addItem(param0: any): boolean;
+ public unlock(): void;
+ public removeItem(param0: any): boolean;
+ public getItems(): java.util.Collection;
+ public clearItems(): void;
+ public lock(): void;
+ public shouldReclusterOnMapMovement(): boolean;
+ public updateItem(param0: any): boolean;
+ public getMaxDistanceBetweenClusteredItems(): number;
+ public removeItems(param0: java.util.Collection): boolean;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export module clustering {
+ export module algo {
+ export class ScreenBasedAlgorithmAdapter extends com.google.maps.android.clustering.algo.AbstractAlgorithm implements com.google.maps.android.clustering.algo.ScreenBasedAlgorithm {
+ public static class: java.lang.Class>;
+ public constructor();
+ public addItems(param0: java.util.Collection): boolean;
+ public setMaxDistanceBetweenClusteredItems(param0: number): void;
+ public constructor(param0: com.google.maps.android.clustering.algo.Algorithm);
+ public getClusters(param0: number): java.util.Set;
+ public addItem(param0: any): boolean;
+ public onCameraChange(param0: com.google.android.gms.maps.model.CameraPosition): void;
+ public unlock(): void;
+ public removeItem(param0: any): boolean;
+ public getItems(): java.util.Collection;
+ public clearItems(): void;
+ public lock(): void;
+ public shouldReclusterOnMapMovement(): boolean;
+ public updateItem(param0: any): boolean;
+ public getMaxDistanceBetweenClusteredItems(): number;
+ public removeItems(param0: java.util.Collection): boolean;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export module clustering {
+ export module algo {
+ export class StaticCluster extends com.google.maps.android.clustering.Cluster {
+ public static class: java.lang.Class>;
+ public add(param0: any): boolean;
+ public getSize(): number;
+ public hashCode(): number;
+ public remove(param0: any): boolean;
+ public constructor(param0: com.google.android.gms.maps.model.LatLng);
+ public getPosition(): com.google.android.gms.maps.model.LatLng;
+ public toString(): string;
+ public equals(param0: any): boolean;
+ public getItems(): java.util.Collection;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export module clustering {
+ export module view {
+ export class ClusterRenderer extends java.lang.Object {
+ public static class: java.lang.Class>;
+ /**
+ * Constructs a new instance of the com.google.maps.android.clustering.view.ClusterRenderer interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: {
+ onClustersChanged(param0: java.util.Set): void;
+ setOnClusterClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterClickListener): void;
+ setOnClusterInfoWindowClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterInfoWindowClickListener): void;
+ setOnClusterInfoWindowLongClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterInfoWindowLongClickListener): void;
+ setOnClusterItemClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterItemClickListener): void;
+ setOnClusterItemInfoWindowClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterItemInfoWindowClickListener): void;
+ setOnClusterItemInfoWindowLongClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterItemInfoWindowLongClickListener): void;
+ setAnimation(param0: boolean): void;
+ setAnimationDuration(param0: number): void;
+ onAdd(): void;
+ onRemove(): void;
+ getColor(param0: number): number;
+ getClusterTextAppearance(param0: number): number;
+ });
+ public constructor();
+ public setOnClusterItemInfoWindowLongClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterItemInfoWindowLongClickListener): void;
+ public onClustersChanged(param0: java.util.Set): void;
+ public setOnClusterInfoWindowLongClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterInfoWindowLongClickListener): void;
+ public setOnClusterItemInfoWindowClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterItemInfoWindowClickListener): void;
+ public setOnClusterInfoWindowClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterInfoWindowClickListener): void;
+ public setOnClusterItemClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterItemClickListener): void;
+ public onAdd(): void;
+ public setOnClusterClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterClickListener): void;
+ public getColor(param0: number): number;
+ public onRemove(): void;
+ public setAnimation(param0: boolean): void;
+ public setAnimationDuration(param0: number): void;
+ public getClusterTextAppearance(param0: number): number;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export module clustering {
+ export module view {
+ export class DefaultClusterRenderer extends com.google.maps.android.clustering.view.ClusterRenderer {
+ public static class: java.lang.Class>;
+ public onClusterItemUpdated(param0: any, param1: com.google.android.gms.maps.model.Marker): void;
+ public getClusterText(param0: number): string;
+ public getBucket(param0: com.google.maps.android.clustering.Cluster): number;
+ public onClustersChanged(param0: java.util.Set): void;
+ public setOnClusterItemInfoWindowLongClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterItemInfoWindowLongClickListener): void;
+ public onClusterRendered(param0: com.google.maps.android.clustering.Cluster, param1: com.google.android.gms.maps.model.Marker): void;
+ public onClusterUpdated(param0: com.google.maps.android.clustering.Cluster, param1: com.google.android.gms.maps.model.Marker): void;
+ public setMinClusterSize(param0: number): void;
+ public setOnClusterItemClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterItemClickListener): void;
+ public getClusterItem(param0: com.google.android.gms.maps.model.Marker): any;
+ public shouldRender(param0: java.util.Set, param1: java.util.Set): boolean;
+ public getColor(param0: number): number;
+ public onBeforeClusterRendered(param0: com.google.maps.android.clustering.Cluster, param1: com.google.android.gms.maps.model.MarkerOptions): void;
+ public onRemove(): void;
+ public setAnimation(param0: boolean): void;
+ public getMarker(param0: com.google.maps.android.clustering.Cluster): com.google.android.gms.maps.model.Marker;
+ public getDescriptorForCluster(param0: com.google.maps.android.clustering.Cluster): com.google.android.gms.maps.model.BitmapDescriptor;
+ public getMinClusterSize(): number;
+ public constructor(param0: globalAndroid.content.Context, param1: com.google.android.gms.maps.GoogleMap, param2: com.google.maps.android.clustering.ClusterManager);
+ public getClusterTextAppearance(param0: number): number;
+ public setOnClusterInfoWindowClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterInfoWindowClickListener): void;
+ public setOnClusterClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterClickListener): void;
+ public onBeforeClusterItemRendered(param0: any, param1: com.google.android.gms.maps.model.MarkerOptions): void;
+ public setOnClusterInfoWindowLongClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterInfoWindowLongClickListener): void;
+ public onAdd(): void;
+ public setOnClusterItemInfoWindowClickListener(param0: com.google.maps.android.clustering.ClusterManager.OnClusterItemInfoWindowClickListener): void;
+ public getCluster(param0: com.google.android.gms.maps.model.Marker): com.google.maps.android.clustering.Cluster;
+ public shouldRenderAsCluster(param0: com.google.maps.android.clustering.Cluster): boolean;
+ public onClusterItemRendered(param0: any, param1: com.google.android.gms.maps.model.Marker): void;
+ public getMarker(param0: any): com.google.android.gms.maps.model.Marker;
+ public setAnimationDuration(param0: number): void;
+ }
+ export module DefaultClusterRenderer {
+ export class AnimationTask {
+ public static class: java.lang.Class;
+ public onAnimationEnd(param0: globalAndroid.animation.Animator): void;
+ public onAnimationUpdate(param0: globalAndroid.animation.ValueAnimator): void;
+ public removeOnAnimationComplete(param0: com.google.maps.android.collections.MarkerManager): void;
+ public perform(): void;
+ }
+ export class CreateMarkerTask {
+ public static class: java.lang.Class;
+ public constructor(param0: com.google.maps.android.clustering.Cluster, param1: java.util.Set, param2: com.google.android.gms.maps.model.LatLng);
+ }
+ export class MarkerCache extends java.lang.Object {
+ public static class: java.lang.Class>;
+ public put(param0: T, param1: com.google.android.gms.maps.model.Marker): void;
+ public remove(param0: com.google.android.gms.maps.model.Marker): void;
+ public get(param0: com.google.android.gms.maps.model.Marker): T;
+ public get(param0: T): com.google.android.gms.maps.model.Marker;
+ }
+ export class MarkerModifier {
+ public static class: java.lang.Class;
+ public animate(param0: com.google.maps.android.clustering.view.DefaultClusterRenderer.MarkerWithPosition, param1: com.google.android.gms.maps.model.LatLng, param2: com.google.android.gms.maps.model.LatLng): void;
+ public animateThenRemove(param0: com.google.maps.android.clustering.view.DefaultClusterRenderer.MarkerWithPosition, param1: com.google.android.gms.maps.model.LatLng, param2: com.google.android.gms.maps.model.LatLng): void;
+ public handleMessage(param0: globalAndroid.os.Message): void;
+ public waitUntilFree(): void;
+ public add(param0: boolean, param1: com.google.maps.android.clustering.view.DefaultClusterRenderer.CreateMarkerTask): void;
+ public remove(param0: boolean, param1: com.google.android.gms.maps.model.Marker): void;
+ public queueIdle(): boolean;
+ public isBusy(): boolean;
+ }
+ export class MarkerWithPosition {
+ public static class: java.lang.Class;
+ public equals(param0: any): boolean;
+ public hashCode(): number;
+ }
+ export class RenderTask {
+ public static class: java.lang.Class;
+ public setMapZoom(param0: number): void;
+ public setProjection(param0: com.google.android.gms.maps.Projection): void;
+ public setCallback(param0: java.lang.Runnable): void;
+ public run(): void;
+ }
+ export class ViewModifier {
+ public static class: java.lang.Class;
+ public handleMessage(param0: globalAndroid.os.Message): void;
+ public queue(param0: java.util.Set): void;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export module collections {
+ export class CircleManager extends com.google.maps.android.collections.MapObjectManager implements com.google.android.gms.maps.GoogleMap.OnCircleClickListener {
+ public static class: java.lang.Class;
+ public newCollection(): com.google.maps.android.collections.CircleManager.Collection;
+ public removeObjectFromMap(param0: com.google.android.gms.maps.model.Circle): void;
+ public removeObjectFromMap(param0: any): void;
+ public newCollection(param0: string): any;
+ public onCircleClick(param0: com.google.android.gms.maps.model.Circle): void;
+ public constructor(param0: com.google.android.gms.maps.GoogleMap);
+ public newCollection(): any;
+ }
+ export module CircleManager {
+ export class Collection extends com.google.maps.android.collections.MapObjectManager.Collection {
+ public static class: java.lang.Class;
+ public setOnCircleClickListener(param0: com.google.android.gms.maps.GoogleMap.OnCircleClickListener): void;
+ public addAll(param0: java.util.Collection): void;
+ public remove(param0: any): boolean;
+ public showAll(): void;
+ public remove(param0: com.google.android.gms.maps.model.Circle): boolean;
+ public hideAll(): void;
+ public constructor(param0: com.google.maps.android.collections.MapObjectManager);
+ public addAll(param0: java.util.Collection, param1: boolean): void;
+ public addCircle(param0: com.google.android.gms.maps.model.CircleOptions): com.google.android.gms.maps.model.Circle;
+ public constructor(param0: com.google.maps.android.collections.CircleManager);
+ public getCircles(): java.util.Collection;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+declare module com {
+ export module google {
+ export module maps {
+ export module android {
+ export module collections {
+ export class GroundOverlayManager extends com.google.maps.android.collections.MapObjectManager implements com.google.android.gms.maps.GoogleMap.OnGroundOverlayClickListener {
+ public static class: java.lang.Class;
+ public newCollection(): com.google.maps.android.collections.GroundOverlayManager.Collection;
+ public removeObjectFromMap(param0: any): void;
+ public removeObjectFromMap(param0: com.google.android.gms.maps.model.GroundOverlay): void;
+ public newCollection(param0: string): any;
+ public constructor(param0: com.google.android.gms.maps.GoogleMap);
+ public newCollection(): any;
+ public onGroundOverlayClick(param0: com.google.android.gms.maps.model.GroundOverlay): void;
+ }
+ export module GroundOverlayManager {
+ export class Collection extends com.google.maps.android.collections.MapObjectManager.Collection {
+ public static class: java.lang.Class;
+ public constructor(param0: com.google.maps.android.collections.GroundOverlayManager);
+ public remove(param0: any): boolean;
+ public showAll(): void;
+ public addAll(param0: java.util.Collection): void;
+ public addAll(param0: java.util.Collection, param1: boolean): void;
+ public hideAll(): void;
+ public constructor(param0: com.google.maps.android.collections.MapObjectManager);
+ public setOnGroundOverlayClickListener(param0: com.google.android.gms.maps.GoogleMap.OnGroundOverlayClickListener): void;
+ public remove(param0: com.google.android.gms.maps.model.GroundOverlay): boolean;
+ public getGroundOverlays(): java.util.Collection