diff --git a/plugin/README.md b/plugin/README.md
index 2964128..6dea13a 100644
--- a/plugin/README.md
+++ b/plugin/README.md
@@ -1183,6 +1183,13 @@ but the current specification only allows X, Y, and (optionally) Z to be defined
number[]
+#### Marker
+
+Supports markers of either either "legacy" or "advanced" types.
+
+google.maps.Marker | google.maps.marker.AdvancedMarkerElement
+
+
### Enums
diff --git a/plugin/e2e-tests/android/app/src/main/AndroidManifest.xml b/plugin/e2e-tests/android/app/src/main/AndroidManifest.xml
index 49f93ce..bd137e1 100644
--- a/plugin/e2e-tests/android/app/src/main/AndroidManifest.xml
+++ b/plugin/e2e-tests/android/app/src/main/AndroidManifest.xml
@@ -11,7 +11,7 @@
android:theme="@style/AppTheme">
/dev/null && printf '%s
+' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -133,10 +134,13 @@ location of your Java installation."
fi
else
JAVACMD=java
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
+ fi
fi
# Increase the maximum file descriptors if we can.
@@ -144,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC3045
+ # shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@@ -152,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC3045
+ # shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -197,11 +201,15 @@ if "$cygwin" || "$msys" ; then
done
fi
-# Collect all arguments for the java command;
-# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
-# shell script including quotes and variable substitutions, so put them in
-# double quotes to make sure that they get re-expanded; and
-# * put everything else in single quotes, so that it's not re-expanded.
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
diff --git a/plugin/e2e-tests/android/gradlew.bat b/plugin/e2e-tests/android/gradlew.bat
index 6689b85..9b42019 100644
--- a/plugin/e2e-tests/android/gradlew.bat
+++ b/plugin/e2e-tests/android/gradlew.bat
@@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
+@rem SPDX-License-Identifier: Apache-2.0
+@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
+echo. 1>&2
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
goto fail
@@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
+echo. 1>&2
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
goto fail
diff --git a/plugin/e2e-tests/android/variables.gradle b/plugin/e2e-tests/android/variables.gradle
index 06370a5..14eafdf 100644
--- a/plugin/e2e-tests/android/variables.gradle
+++ b/plugin/e2e-tests/android/variables.gradle
@@ -2,12 +2,12 @@ ext {
minSdkVersion = 23
compileSdkVersion = 35
targetSdkVersion = 35
- androidxActivityVersion = '1.8.0'
+ androidxActivityVersion = '1.9.2'
androidxAppCompatVersion = '1.7.0'
androidxCoordinatorLayoutVersion = '1.2.0'
- androidxCoreVersion = '1.12.0'
- androidxFragmentVersion = '1.6.2'
- androidxWebkitVersion = '1.9.0'
+ androidxCoreVersion = '1.15.0'
+ androidxFragmentVersion = '1.8.4'
+ androidxWebkitVersion = '1.12.1'
androidxJunitVersion = '1.2.1'
androidxEspressoCoreVersion = '3.6.1'
cordovaAndroidVersion = '10.1.1'
diff --git a/plugin/e2e-tests/ios/App/App.xcodeproj/project.pbxproj b/plugin/e2e-tests/ios/App/App.xcodeproj/project.pbxproj
index e584de3..fedc3e1 100644
--- a/plugin/e2e-tests/ios/App/App.xcodeproj/project.pbxproj
+++ b/plugin/e2e-tests/ios/App/App.xcodeproj/project.pbxproj
@@ -297,7 +297,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -348,7 +348,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
@@ -364,7 +364,7 @@
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 9YN2HU59K8;
INFOPLIST_FILE = App/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = io.ionic.googlemaps;
@@ -383,7 +383,7 @@
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 9YN2HU59K8;
INFOPLIST_FILE = App/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.ionic.googlemaps;
PRODUCT_NAME = "$(TARGET_NAME)";
diff --git a/plugin/e2e-tests/package.json b/plugin/e2e-tests/package.json
index 3f3292b..6ace8ba 100644
--- a/plugin/e2e-tests/package.json
+++ b/plugin/e2e-tests/package.json
@@ -3,17 +3,14 @@
"version": "0.0.1",
"private": true,
"dependencies": {
- "@capacitor/android": "^6.0.0",
- "@capacitor/app": "^6.0.0",
- "@capacitor/core": "^6.0.0",
- "@capacitor/android": "next",
- "@capacitor/core": "next",
+ "@capacitor/app": "^7.0.0",
+ "@capacitor/android": "^7.0.0",
+ "@capacitor/core": "^7.0.0",
"@capacitor/google-maps": "file:..",
- "@capacitor/haptics": "^6.0.0",
- "@capacitor/ios": "^6.0.0",
- "@capacitor/keyboard": "^6.0.0",
- "@capacitor/status-bar": "^6.0.0",
- "@capacitor/ios": "next",
+ "@capacitor/haptics": "^7.0.0",
+ "@capacitor/ios": "^7.0.0",
+ "@capacitor/keyboard": "^7.0.0",
+ "@capacitor/status-bar": "^7.0.0",
"@ionic/react": "^6.0.0",
"@ionic/react-router": "^6.0.0",
"@testing-library/jest-dom": "^5.11.9",
@@ -80,11 +77,10 @@
]
},
"devDependencies": {
- "@capacitor/cli": "^6.0.0",
+ "@capacitor/cli": "^7.0.0",
"@ionic/e2e": "0.2.0-next.6",
"@ionic/e2e-components-ionic": "0.2.0-next.6",
- "@capacitor/cli": "next",
"appium": "^1.22.1"
},
"description": "An Ionic project"
-}
+}
\ No newline at end of file
diff --git a/plugin/package.json b/plugin/package.json
index 0967fff..85c8117 100644
--- a/plugin/package.json
+++ b/plugin/package.json
@@ -56,7 +56,7 @@
"devDependencies": {
"@capacitor/android": "next",
"@capacitor/core": "next",
- "@capacitor/docgen": "0.2.2",
+ "@capacitor/docgen": "0.3.0",
"@capacitor/ios": "next",
"@ionic/prettier-config": "^1.0.1",
"@types/resize-observer-browser": "^0.1.7",
@@ -89,8 +89,8 @@
"access": "public"
},
"dependencies": {
- "@googlemaps/js-api-loader": "~1.13.7",
- "@googlemaps/markerclusterer": "~2.0.7",
- "@types/google.maps": "~3.50.5"
+ "@googlemaps/js-api-loader": "~1.16.8",
+ "@googlemaps/markerclusterer": "~2.5.3",
+ "@types/google.maps": "~3.58.1"
}
}
diff --git a/plugin/src/web.ts b/plugin/src/web.ts
index 87cea93..f1ba7c0 100644
--- a/plugin/src/web.ts
+++ b/plugin/src/web.ts
@@ -31,12 +31,14 @@ import type {
export class CapacitorGoogleMapsWeb extends WebPlugin implements CapacitorGoogleMapsPlugin {
private gMapsRef: typeof google.maps | undefined = undefined;
+ private AdvancedMarkerElement: typeof google.maps.marker.AdvancedMarkerElement | undefined = undefined;
+ private PinElement: typeof google.maps.marker.PinElement | undefined = undefined;
private maps: {
[id: string]: {
element: HTMLElement;
map: google.maps.Map;
markers: {
- [id: string]: google.maps.Marker;
+ [id: string]: google.maps.marker.AdvancedMarkerElement;
};
polygons: {
[id: string]: google.maps.Polygon;
@@ -55,6 +57,7 @@ export class CapacitorGoogleMapsWeb extends WebPlugin implements CapacitorGoogle
private currPolygonId = 0;
private currCircleId = 0;
private currPolylineId = 0;
+ private currMapId = 0;
private onClusterClickHandler: onClusterClickHandler = (
_: google.maps.MapMouseEvent,
@@ -64,24 +67,27 @@ export class CapacitorGoogleMapsWeb extends WebPlugin implements CapacitorGoogle
const mapId = this.getIdFromMap(map);
const items: any[] = [];
- if (cluster.markers != undefined) {
+ if (cluster.markers != undefined && this.AdvancedMarkerElement) {
for (const marker of cluster.markers) {
- const markerId = this.getIdFromMarker(mapId, marker);
-
- items.push({
- markerId: markerId,
- latitude: marker.getPosition()?.lat(),
- longitude: marker.getPosition()?.lng(),
- title: marker.getTitle(),
- snippet: '',
- });
+ if (marker instanceof this.AdvancedMarkerElement) {
+ const markerId = this.getIdFromMarker(mapId, marker);
+ const position = marker.position as google.maps.LatLngLiteral;
+
+ items.push({
+ markerId: markerId,
+ latitude: position.lat,
+ longitude: position.lng,
+ title: marker.title ?? '',
+ snippet: '',
+ });
+ }
}
}
this.notifyListeners('onClusterClick', {
mapId: mapId,
- latitude: cluster.position.lat(),
- longitude: cluster.position.lng(),
+ latitude: cluster.position.lat,
+ longitude: cluster.position.lng,
size: cluster.count,
items: items,
});
@@ -97,7 +103,7 @@ export class CapacitorGoogleMapsWeb extends WebPlugin implements CapacitorGoogle
return '';
}
- private getIdFromMarker(mapId: string, marker: google.maps.Marker): string {
+ private getIdFromMarker(mapId: string, marker: google.maps.marker.AdvancedMarkerElement): string {
for (const id in this.maps[mapId].markers) {
if (this.maps[mapId].markers[id] == marker) {
return id;
@@ -119,6 +125,12 @@ export class CapacitorGoogleMapsWeb extends WebPlugin implements CapacitorGoogle
});
const google = await loader.load();
this.gMapsRef = google.maps;
+
+ // Import marker library once
+ const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary('marker') as google.maps.MarkerLibrary;
+ this.AdvancedMarkerElement = AdvancedMarkerElement;
+ this.PinElement = PinElement;
+
console.log('Loaded google maps API');
}
}
@@ -251,13 +263,12 @@ export class CapacitorGoogleMapsWeb extends WebPlugin implements CapacitorGoogle
const map = this.maps[_args.id];
for (const markerArgs of _args.markers) {
- const markerOpts = this.buildMarkerOpts(markerArgs, map.map);
- const marker = new google.maps.Marker(markerOpts);
+ const advancedMarker = this.buildMarkerOpts(markerArgs, map.map);
const id = '' + this.currMarkerId;
- map.markers[id] = marker;
- this.setMarkerListeners(_args.id, id, marker);
+ map.markers[id] = advancedMarker;
+ await this.setMarkerListeners(_args.id, id, advancedMarker);
markerIds.push(id);
this.currMarkerId++;
@@ -267,14 +278,12 @@ export class CapacitorGoogleMapsWeb extends WebPlugin implements CapacitorGoogle
}
async addMarker(_args: AddMarkerArgs): Promise<{ id: string }> {
- const markerOpts = this.buildMarkerOpts(_args.marker, this.maps[_args.id].map);
-
- const marker = new google.maps.Marker(markerOpts);
+ const advancedMarker = this.buildMarkerOpts(_args.marker, this.maps[_args.id].map);
const id = '' + this.currMarkerId;
- this.maps[_args.id].markers[id] = marker;
- this.setMarkerListeners(_args.id, id, marker);
+ this.maps[_args.id].markers[id] = advancedMarker;
+ await this.setMarkerListeners(_args.id, id, advancedMarker);
this.currMarkerId++;
@@ -285,14 +294,18 @@ export class CapacitorGoogleMapsWeb extends WebPlugin implements CapacitorGoogle
const map = this.maps[_args.id];
for (const id of _args.markerIds) {
- map.markers[id].setMap(null);
- delete map.markers[id];
+ if (map.markers[id]) {
+ map.markers[id].map = null;
+ delete map.markers[id];
+ }
}
}
async removeMarker(_args: RemoveMarkerArgs): Promise {
- this.maps[_args.id].markers[_args.markerId].setMap(null);
- delete this.maps[_args.id].markers[_args.markerId];
+ if (this.maps[_args.id].markers[_args.markerId]) {
+ this.maps[_args.id].markers[_args.markerId].map = null;
+ delete this.maps[_args.id].markers[_args.markerId];
+ }
}
async addPolygons(args: AddPolygonsArgs): Promise<{ ids: string[] }> {
@@ -383,7 +396,7 @@ export class CapacitorGoogleMapsWeb extends WebPlugin implements CapacitorGoogle
}
async enableClustering(_args: EnableClusteringArgs): Promise {
- const markers: google.maps.Marker[] = [];
+ const markers: google.maps.marker.AdvancedMarkerElement[] = [];
for (const id in this.maps[_args.id].markers) {
markers.push(this.maps[_args.id].markers[id]);
@@ -400,8 +413,17 @@ export class CapacitorGoogleMapsWeb extends WebPlugin implements CapacitorGoogle
}
async disableClustering(_args: { id: string }): Promise {
- this.maps[_args.id].markerClusterer?.setMap(null);
- this.maps[_args.id].markerClusterer = undefined;
+ const mapInstance = this.maps[_args.id];
+ if (mapInstance.markerClusterer) {
+ const markers = Object.values(mapInstance.markers);
+
+ mapInstance.markerClusterer.setMap(null);
+ mapInstance.markerClusterer = undefined;
+
+ for (const marker of markers) {
+ marker.map = mapInstance.map;
+ }
+ }
}
async onScroll(): Promise {
@@ -420,8 +442,14 @@ export class CapacitorGoogleMapsWeb extends WebPlugin implements CapacitorGoogle
console.log(`Create map: ${_args.id}`);
await this.importGoogleLib(_args.apiKey, _args.region, _args.language);
+ // Ensure we have a Map ID for Advanced Markers
+ const config = { ..._args.config };
+ if (!config.mapId) {
+ config.mapId = `capacitor_map_${this.currMapId++}`;
+ }
+
this.maps[_args.id] = {
- map: new window.google.maps.Map(_args.element, { ..._args.config }),
+ map: new window.google.maps.Map(_args.element, config),
element: _args.element,
markers: {},
polygons: {},
@@ -503,50 +531,56 @@ export class CapacitorGoogleMapsWeb extends WebPlugin implements CapacitorGoogle
});
}
- async setMarkerListeners(mapId: string, markerId: string, marker: google.maps.Marker): Promise {
+ async setMarkerListeners(mapId: string, markerId: string, marker: google.maps.marker.AdvancedMarkerElement): Promise {
marker.addListener('click', () => {
+ const position = marker.position as google.maps.LatLngLiteral;
this.notifyListeners('onMarkerClick', {
mapId: mapId,
markerId: markerId,
- latitude: marker.getPosition()?.lat(),
- longitude: marker.getPosition()?.lng(),
- title: marker.getTitle(),
+ latitude: position.lat,
+ longitude: position.lng,
+ title: marker.title ?? '',
snippet: '',
});
});
- marker.addListener('dragstart', () => {
- this.notifyListeners('onMarkerDragStart', {
- mapId: mapId,
- markerId: markerId,
- latitude: marker.getPosition()?.lat(),
- longitude: marker.getPosition()?.lng(),
- title: marker.getTitle(),
- snippet: '',
+ if (marker.gmpDraggable) {
+ marker.addListener('dragstart', () => {
+ const position = marker.position as google.maps.LatLngLiteral;
+ this.notifyListeners('onMarkerDragStart', {
+ mapId: mapId,
+ markerId: markerId,
+ latitude: position.lat,
+ longitude: position.lng,
+ title: marker.title ?? '',
+ snippet: '',
+ });
});
- });
- marker.addListener('drag', () => {
- this.notifyListeners('onMarkerDrag', {
- mapId: mapId,
- markerId: markerId,
- latitude: marker.getPosition()?.lat(),
- longitude: marker.getPosition()?.lng(),
- title: marker.getTitle(),
- snippet: '',
+ marker.addListener('drag', () => {
+ const position = marker.position as google.maps.LatLngLiteral;
+ this.notifyListeners('onMarkerDrag', {
+ mapId: mapId,
+ markerId: markerId,
+ latitude: position.lat,
+ longitude: position.lng,
+ title: marker.title ?? '',
+ snippet: '',
+ });
});
- });
- marker.addListener('dragend', () => {
- this.notifyListeners('onMarkerDragEnd', {
- mapId: mapId,
- markerId: markerId,
- latitude: marker.getPosition()?.lat(),
- longitude: marker.getPosition()?.lng(),
- title: marker.getTitle(),
- snippet: '',
+ marker.addListener('dragend', () => {
+ const position = marker.position as google.maps.LatLngLiteral;
+ this.notifyListeners('onMarkerDragEnd', {
+ mapId: mapId,
+ markerId: markerId,
+ latitude: position.lat,
+ longitude: position.lng,
+ title: marker.title ?? '',
+ snippet: '',
+ });
});
- });
+ }
}
async setMapListeners(mapId: string): Promise {
@@ -598,31 +632,40 @@ export class CapacitorGoogleMapsWeb extends WebPlugin implements CapacitorGoogle
});
}
- private buildMarkerOpts(marker: Marker, map: google.maps.Map): google.maps.MarkerOptions {
- let iconImage: google.maps.Icon | undefined = undefined;
+ private buildMarkerOpts(marker: Marker, map: google.maps.Map): google.maps.marker.AdvancedMarkerElement {
+ if (!this.AdvancedMarkerElement || !this.PinElement) {
+ throw new Error('Marker library not loaded');
+ }
+
+ let content: HTMLElement | undefined = undefined;
+
if (marker.iconUrl) {
- iconImage = {
- url: marker.iconUrl,
- scaledSize: marker.iconSize ? new google.maps.Size(marker.iconSize.width, marker.iconSize.height) : null,
- anchor: marker.iconAnchor
- ? new google.maps.Point(marker.iconAnchor.x, marker.iconAnchor.y)
- : new google.maps.Point(0, 0),
- origin: marker.iconOrigin
- ? new google.maps.Point(marker.iconOrigin.x, marker.iconOrigin.y)
- : new google.maps.Point(0, 0),
+ const img = document.createElement('img');
+ img.src = marker.iconUrl;
+ if (marker.iconSize) {
+ img.style.width = `${marker.iconSize.width}px`;
+ img.style.height = `${marker.iconSize.height}px`;
+ }
+ content = img;
+ } else {
+ const pinOptions: google.maps.marker.PinElementOptions = {
+ scale: marker.opacity ?? 1,
+ glyph: marker.title,
+ background: marker.tintColor ? `rgb(${marker.tintColor.r}, ${marker.tintColor.g}, ${marker.tintColor.b})` : undefined,
};
+
+ const pin = new this.PinElement(pinOptions);
+ content = pin.element;
}
- const opts: google.maps.MarkerOptions = {
+ const advancedMarker = new this.AdvancedMarkerElement({
position: marker.coordinate,
map: map,
- opacity: marker.opacity,
+ content: content,
title: marker.title,
- icon: iconImage,
- draggable: marker.draggable,
- zIndex: marker.zIndex ?? 0,
- };
+ gmpDraggable: marker.draggable,
+ });
- return opts;
+ return advancedMarker;
}
}