diff --git a/package.json b/package.json index d8fe2d2eb8b..7d43f969a18 100644 --- a/package.json +++ b/package.json @@ -120,5 +120,5 @@ "lint": "next lint", "clean-references": "node tasks/clean-references.mjs" }, - "packageManager": "yarn@4.9.0" + "packageManager": "yarn@4.9.2" } diff --git a/src/components/GeoLegacyResourcesBanner/GeoLegacyResourcesBanner.tsx b/src/components/GeoLegacyResourcesBanner/GeoLegacyResourcesBanner.tsx new file mode 100644 index 00000000000..5059c8eb8b1 --- /dev/null +++ b/src/components/GeoLegacyResourcesBanner/GeoLegacyResourcesBanner.tsx @@ -0,0 +1,28 @@ +import { Callout } from '@/components/Callout'; +import Link from 'next/link'; +import classNames from 'classnames'; + +export const GeoLegacyResourcesBanner = () => { + return ( + + Amazon Location Service has introduced{' '} + + new APIs for Maps and Places + {' '} + which no longer require account-bound resources. Amplify Geo no longer + supports the provisioning of legacy (account-bound) maps and place + indices. Please{' '} + + visit the CDK API to learn more about provisioning legacy resources. + + + ); +}; diff --git a/src/components/GeoLegacyResourcesBanner/index.ts b/src/components/GeoLegacyResourcesBanner/index.ts new file mode 100644 index 00000000000..7a178bad3ba --- /dev/null +++ b/src/components/GeoLegacyResourcesBanner/index.ts @@ -0,0 +1 @@ +export { GeoLegacyResourcesBanner } from './GeoLegacyResourcesBanner'; diff --git a/src/components/Layout/Layout.tsx b/src/components/Layout/Layout.tsx index 3ff54bd60f6..2fa7e4b7064 100644 --- a/src/components/Layout/Layout.tsx +++ b/src/components/Layout/Layout.tsx @@ -37,6 +37,7 @@ import { } from '@/components/NextPrevious'; import { Modal } from '@/components/Modal'; import { Gen1Banner } from '@/components/Gen1Banner'; +import { GeoLegacyResourcesBanner } from '../GeoLegacyResourcesBanner'; import { PinpointEOLBanner } from '@/components/PinpointEOLBanner'; import { LexV1EOLBanner } from '../LexV1EOLBanner'; import { ApiModalProvider } from '../ApiDocs/ApiModalProvider'; @@ -288,6 +289,9 @@ export const Layout = ({ {(isGen1GettingStarted || isGen1HowAmplifyWorks) && ( )} + {asPathWithNoHash.includes('/geo/set-up-geo/') && ( + + )} {(asPathWithNoHash.includes('/push-notifications/') || asPathWithNoHash.includes('/analytics/') || asPathWithNoHash.includes('/in-app-messaging/')) && ( diff --git a/src/directory/directory.mjs b/src/directory/directory.mjs index 96eeea86fc6..f2ed3a0e73c 100644 --- a/src/directory/directory.mjs +++ b/src/directory/directory.mjs @@ -396,6 +396,44 @@ export const directory = { } ] }, + { + path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/index.mdx', + children: [ + { + path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/set-up-geo/index.mdx' + }, + { + path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/custom-authorization/index.mdx' + }, + { + path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/maps/index.mdx' + }, + { + path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/configure-location-search/index.mdx' + }, + { + path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/location-search/index.mdx' + }, + { + path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/configure-geofencing/index.mdx' + }, + { + path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/geofences/index.mdx' + }, + { + path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/existing-resources/index.mdx' + }, + { + path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/use-legacy-resources/index.mdx' + }, + { + path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/google-migration/index.mdx' + }, + { + path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/amazon-location-sdk/index.mdx' + } + ] + }, { path: 'src/pages/[platform]/build-a-backend/functions/index.mdx', children: [ @@ -524,38 +562,6 @@ export const directory = { } ] }, - { - path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/index.mdx', - children: [ - { - path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/set-up-geo/index.mdx' - }, - { - path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/maps/index.mdx' - }, - { - path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/configure-location-search/index.mdx' - }, - { - path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/location-search/index.mdx' - }, - { - path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/configure-geofencing/index.mdx' - }, - { - path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/geofences/index.mdx' - }, - { - path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/existing-resources/index.mdx' - }, - { - path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/google-migration/index.mdx' - }, - { - path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/amazon-location-sdk/index.mdx' - } - ] - }, { path: 'src/pages/[platform]/build-a-backend/add-aws-services/in-app-messaging/index.mdx', children: [ diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/geo/configure-geofencing/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/geo/configure-geofencing/index.mdx index fd7c4220bf3..a3cc6cec1fb 100644 --- a/src/pages/[platform]/build-a-backend/add-aws-services/geo/configure-geofencing/index.mdx +++ b/src/pages/[platform]/build-a-backend/add-aws-services/geo/configure-geofencing/index.mdx @@ -29,70 +29,62 @@ A Geofence is a virtual perimeter for a real-world geographic area. A Geofence c ## Setup a new Geofence Collection +```ts title="amplify/geo/resource.ts" +import { defineCollection } from "@aws-amplify/backend-geo"; + +export const collection = defineCollection({ + name: 'amplifyCollection', + description: 'This is an Amplify collection.', + access: (allow) => [ + allow.authenticated.to(['create', 'read', 'update', 'delete', 'list']), + allow.guest.to(['read', 'list']) + ] +}); +``` + +Now update your `backend.ts` file with the collection created in your `resource.ts` file. + ```ts title="amplify/backend.ts" import { defineBackend } from "@aws-amplify/backend"; import { Policy, PolicyStatement } from "aws-cdk-lib/aws-iam"; import { CfnGeofenceCollection } from "aws-cdk-lib/aws-location"; import { auth } from "./auth/resource"; import { data } from "./data/resource"; +import { collection } from "./geo/resource"; const backend = defineBackend({ auth, data, - // additional resources + collection }); +``` -const geoStack = backend.createStack("geo-stack"); - -// create a location services geofence collection -const myGeofenceCollection = new CfnGeofenceCollection( - geoStack, - "GeofenceCollection", - { - collectionName: "myGeofenceCollection", - pricingPlan: "RequestBasedUsage", - tags: [ - { - key: "name", - value: "myGeofenceCollection", - }, - ], - } -); - -// create an IAM policy to allow interacting with geofence collection resource -const myGeofenceCollectionPolicy = new Policy( - geoStack, - "GeofenceCollectionPolicy", - { - policyName: "myGeofenceCollectionPolicy", - statements: [ - new PolicyStatement({ - actions: [ - "geo:GetGeofence", - "geo:PutGeofence", - "geo:BatchPutGeofence", - "geo:BatchDeleteGeofence", - "geo:ListGeofences", - ], - resources: [myGeofenceCollection.attrArn], - }), - ], - } -); - -// apply the policy to the authenticated and unauthenticated roles -backend.auth.resources.authenticatedUserIamRole.attachInlinePolicy(myGeofenceCollectionPolicy); -backend.auth.resources.unauthenticatedUserIamRole.attachInlinePolicy(myGeofenceCollectionPolicy); - -// patch the geofence collection resource to the expected output configuration -backend.addOutput({ - geo: { - geofence_collections: { - default: myGeofenceCollection.collectionName, - items: [myGeofenceCollection.collectionName], - }, - }, + + +AWS Location API keys currently do not support geofence collections or their associated APIs. Adding access definitions for any API keys using the `allow.apiKey.to()` definition will NOT result in the creation of an API key. + + + +## Configure additional geofence collections + +Amplify Geo gives you the ability to configure your backend to automatically request and manage multiple geofence collections. + +You can define these additional geofence collections by reusing the `defineCollection` function while providing a unique `name` to identify the collection. You can configure specific access permissions to these collections by adding them to the API with the unique `name`. + + + +**Note**: If numerous geofence collections are defined, then one of them must be marked as default using the `isDefault` flag. + + + +```ts title="amplify/geo/resource.ts" +export const firstCollection = defineCollection({ + name: 'firstCollection', + isDefault: true +}); + +export const secondCollection = defineCollection({ + name: 'secondCollection' }); ``` @@ -100,7 +92,7 @@ backend.addOutput({ The pricing plan for the Geofence Collection will be set to `RequestBasedUsage`. We advice you to go through the [location service pricing](https://aws.amazon.com/location/pricing/) along with the [location service terms](https://aws.amazon.com/service-terms/) (_82.5 section_) to learn more about the pricing plan. -#### Group access +### Group access To scope access permissions based on [Cognito User Groups](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-user-groups.html) @@ -117,30 +109,21 @@ export const auth = defineAuth({ }); ``` -2. Add permissions to the Cognito User Pool Group role +2. Update the collection access definition in your `resource.ts` -```ts title="amplify/backend.ts" -const myGeofenceCollectionPolicy = new Policy( - geoStack, - "GeofenceCollectionPolicy", - { - policyName: "myGeofenceCollectionPolicy", - statements: [ - new PolicyStatement({ - actions: [ - "geo:GetGeofence", - "geo:PutGeofence", - "geo:BatchPutGeofence", - "geo:BatchDeleteGeofence", - "geo:ListGeofences", - ], - resources: [myGeofenceCollection.attrArn], - }), - ], - } -); - -backend.auth.resources.groups["User"].role.attachInlinePolicy(myGeofenceCollectionPolicy); +```ts title="amplify/geo/resource.ts" +import { defineCollection } from "@aws-amplify/backend-geo"; + +export const collection = defineCollection({ + name: 'amplifyCollection', + description: 'This is an Amplify collection.', + access: (allow) => [ + allow.authenticated.to(['create', 'read', 'update', 'delete', 'list']), + allow.guest.to(['read', 'list']), + // highlight-next-line + allow.groups("User").to(['read', 'update']) + ] +}); ``` > Note: If you combine `Auth/Guest user access` and `Individual Group access`, users who are members of a group will only be granted the permissions of the group, and not the authenticated user permissions. The permissions apply to ALL Geofences in a collection. For example, If you add `Read` permission such as `ListGeofences` and `GetGeofence` to `User` Cognito group, ALL users added to that group will be able to read the properties of ALL Geofences in that Geofence collection. diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/geo/configure-location-search/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/geo/configure-location-search/index.mdx index 6ab7f120493..8977ba41f49 100644 --- a/src/pages/[platform]/build-a-backend/add-aws-services/geo/configure-location-search/index.mdx +++ b/src/pages/[platform]/build-a-backend/add-aws-services/geo/configure-location-search/index.mdx @@ -27,152 +27,44 @@ export function getStaticProps(context) { }; } - -Amplify's `geo` category enables you to search by places, addresses, and coordinates in your app with "place index" resources. +Amplify's `geo` category enables you to search by places, addresses, and coordinates in your app with "place index" resources. These resources also include an API key with access restrictions specified from the `access` callback. This API key will be used to render the location search components if your application requires access control on the components. To set up Amazon Location API keys through Geo, visit the [set up guide](/[platform]/build-a-backend/add-aws-services/geo/set-up-geo/#generate-api-keys). ## Setup a new Location Search Index +```ts title="amplify/geo/resource.ts" +import { definePlace } from "@aws-amplify/backend-geo"; + +export const searchIndex = definePlace({ + name: 'amplifyPlace', + description: 'This is an Amplify search index.', + access: (allow) => [ + allow.authenticated.to(['autocomplete', 'geocode']), + allow.guest.to(['autocomplete', 'geocode']), + allow.apiKey.to(['search']) + ], + apiKeyProps: { + apiKeyName: 'amplifyPlaceIndexKey' + } +}); +``` + +Now update your `backend.ts` file with the place index created in your `resource.ts` file. + ```ts title="amplify/backend.ts" import { defineBackend } from "@aws-amplify/backend"; -import { Policy, PolicyStatement } from "aws-cdk-lib/aws-iam"; -// highlight-next-line -import { CfnMap, CfnPlaceIndex } from "aws-cdk-lib/aws-location"; import { auth } from "./auth/resource"; import { data } from "./data/resource"; +// highlight-next-line +import { searchIndex } from "./geo/resource"; const backend = defineBackend({ auth, data, - // additional resources -}); - -const geoStack = backend.createStack("geo-stack"); - -// create a location services map -const map = new CfnMap(geoStack, "Map", { - mapName: "myMap", - description: "Map", - configuration: { - style: "VectorEsriNavigation", - }, - pricingPlan: "RequestBasedUsage", - tags: [ - { - key: "name", - value: "myMap", - }, - ], -}); - - -// create an IAM policy to allow interacting with geo resource -const myGeoPolicy = new Policy(geoStack, "GeoPolicy", { - policyName: "myGeoPolicy", - statements: [ - new PolicyStatement({ - actions: [ - "geo:GetMapTile", - "geo:GetMapSprites", - "geo:GetMapGlyphs", - "geo:GetMapStyleDescriptor", - ], - resources: [map.attrArn], - }), - ], -}); - -// apply the policy to the authenticated and unauthenticated roles -backend.auth.resources.authenticatedUserIamRole.attachInlinePolicy(myGeoPolicy); -backend.auth.resources.unauthenticatedUserIamRole.attachInlinePolicy(myGeoPolicy); - -// highlight-start -// create a location services place index -const myIndex = new CfnPlaceIndex(geoStack, "PlaceIndex", { - dataSource: "Here", - dataSourceConfiguration: { - intendedUse: "SingleUse", - }, - indexName: "myPlaceIndex", - pricingPlan: "RequestBasedUsage", - tags: [ - { - key: "name", - value: "myPlaceIndex", - }, - ], -}); - -// create a policy to allow access to the place index -const myIndexPolicy = new Policy(geoStack, "IndexPolicy", { - policyName: "myIndexPolicy", - statements: [ - new PolicyStatement({ - actions: [ - "geo:SearchPlaceIndexForPosition", - "geo:SearchPlaceIndexForText", - "geo:SearchPlaceIndexForSuggestions", - "geo:GetPlace", - ], - resources: [myIndex.attrArn], - }), - ], -}); - -// attach the policy to the authenticated and unauthenticated IAM roles -backend.auth.resources.authenticatedUserIamRole.attachInlinePolicy(myIndexPolicy); -backend.auth.resources.unauthenticatedUserIamRole.attachInlinePolicy(myIndexPolicy); -// highlight-end - -// patch the place index resource to the expected output configuration -backend.addOutput({ - geo: { - aws_region: geoStack.region, - maps: { - items: { - [map.mapName]: { - style: "VectorEsriNavigation", - }, - }, - default: map.mapName, - }, -// highlight-start - search_indices: { - default: myIndex.indexName, - items: [myIndex.indexName], - }, -// highlight-end - }, + // highlight-next-line + searchIndex }); ``` - ## Location Search Index Pricing Plan The pricing plan for Search Index will be set to `RequestBasedUsage`. We advice you to go through the [location service pricing](https://aws.amazon.com/location/pricing/) along with the [location service terms](https://aws.amazon.com/service-terms/) (_82.5 section_) to learn more about the pricing plan. - - -## Advanced Settings -You can optionally configure the data provider and result storage location for your location search index. - -### Location Search data provider -You can select a data provider as the source for geocoding, reverse geocoding and searches. -Each provider gathers and curates their data using different means. They may also have varying expertise in different regions of the world. -The available data providers of geospatial data are shown. To learn more about data providers, please refer this [location service documentation](https://docs.aws.amazon.com/location/latest/developerguide/what-is-data-provider.html). - -- Here – For additional information about HERE Technologies, see [Here guide](https://docs.aws.amazon.com/location/latest/developerguide/HERE.html). -- Esri – For additional information about Esri, see [Esri guide](https://docs.aws.amazon.com/location/latest/developerguide/esri.html). - - - -**Note:** If your application is tracking or routing assets you use in your business (such as delivery vehicles or employees), you may only use `HERE` as your geolocation provider. -See section 82 of the [AWS service terms](https://aws.amazon.com/service-terms/) for more details. - - - -### Location Search result storage location -You can specify how the results of a search operation will be stored by the caller. - -- SingleUse - specifies that the results won't be stored. -- Storage - specifies that the result can be cached or stored in a database. - -Refer [this location service doc](https://docs.aws.amazon.com/location-places/latest/APIReference/API_DataSourceConfiguration.html#locationplaces-Type-DataSourceConfiguration-IntendedUse) for more information. diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/geo/custom-authorization/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/geo/custom-authorization/index.mdx new file mode 100644 index 00000000000..9a26b508f4c --- /dev/null +++ b/src/pages/[platform]/build-a-backend/add-aws-services/geo/custom-authorization/index.mdx @@ -0,0 +1,133 @@ +import { getCustomStaticPath } from '@/utils/getCustomStaticPath'; + +export const meta = { + title: 'Customize authorization', + description: 'Define fine-grained authorization rules for Geo resources.', + platforms: [ + 'android', + 'angular', + 'javascript', + 'nextjs', + 'react', + 'swift', + 'vue' + ], +}; + +export const getStaticPaths = async () => { + return getCustomStaticPath(meta.platforms); +}; + +export function getStaticProps(context) { + return { + props: { + platform: context.params.platform, + meta + } + }; +} + + + +AWS Location API keys currently do not support geofence collections or their associated APIs. Adding access definitions for any API keys using the `allow.apiKey.to()` definition will NOT result in the creation of an API key. + + + +Customize authorization for your geo resources by defining access to resource APIs for authenticated users, guest (unauthenticated) users, user groups, and API keys (maps and places only). + +## Access Acceptor Types + +Authentication is required to define access permissions for authenticated users, guest users, and user groups, please set it up [here](/[platform]/build-a-backend/auth/set-up-auth/) if not defined. + + + +To grant all guest (i.e. not signed in) users of your application `read` access to the collection resource, use the following `access` definition. + +```ts title="amplify/geo/resource.ts" +export const guestCollection = defineCollection({ + name: 'myCollection', + access: (allow) => [ + allow.guest.to(['read']) + ] +}); +``` + + + +To grant all authorized (i.e. signed in) users of your application `get` access to the map resource, use the following `access` definition. + +```ts title="amplify/geo/resource.ts" +export const authenticatedMap = defineMap({ + name: 'myProjectFiles', + access: (allow) => [ + allow.authenticated.to(['get']) + ] +}); +``` + + + +For any user groups you may have defined under `defineAuth`, you can orchestrate group specific access for your Geo resources. + +```ts title="amplify/auth/resource.ts" +export const auth = defineAuth({ + loginWith: { + email: true + }, + groups: ['admin', 'users'] +}); +``` + +You can use the following `access` definition to set fine grained permissions for the `admin` group to have all APIs accessible and the `users` group to only be able to search. + +```ts title="amplify/geo/resource.ts" +export const searchIndex = definePlace({ + name: 'myProjectFiles', + access: (allow) => [ + allow.groups(['admin']).to(['autocomplete', 'geocode', 'search']), // additional actions such as "write" and "delete" can be specified depending on your use case + allow.groups(['users']).to(['search']) + ] +}); +``` + + + +To grant users of the `Geo` generated API key get access to the map tiles, styles, and other components, use the following `access` definition. + +```ts title="amplify/geo/resource.ts" +export const map = defineMap({ + name: 'myProjectFiles', + access: (allow) => [ + allow.apiKey.to(['get']) // additional actions such as "write" and "delete" can be specified depending on your use case + ] +}); +``` + + + + +### Available Access Actions + +#### Map Actions + +| Custom Action Name | Accessible APIs | +| :------- | :------------------- | +| `get` |[`geo-maps:GetGlyphs`](https://docs.aws.amazon.com/location/latest/APIReference/API_geomaps_GetGlyphs.html)

[`geo-maps:GetSprites`](https://docs.aws.amazon.com/location/latest/APIReference/API_geomaps_GetSprites.html)

[`geo-maps:GetStaticMap`](https://docs.aws.amazon.com/location/latest/APIReference/API_geomaps_GetStaticMap.html)

[`geo-maps:GetStyleDescriptor`](https://docs.aws.amazon.com/location/latest/APIReference/API_geomaps_GetStyleDescriptor.html)

[`geo-maps:GetTile`](https://docs.aws.amazon.com/location/latest/APIReference/API_geomaps_GetTile.html) | + +#### Place Index Actions + +| Custom Action Name | Accessible APIs | +| :------- | :------------------- | +| `autocomplete` | [`geo-places:Autocomplete`](https://docs.aws.amazon.com/location/latest/APIReference/API_geoplaces_Autocomplete.html) | +| `geocode` | [`geo-places:Geocode`](https://docs.aws.amazon.com/location/latest/APIReference/API_geoplaces_Geocode.html)

[`geo-places:ReverseGeocode`](https://docs.aws.amazon.com/location/latest/APIReference/API_geoplaces_ReverseGeocode.html) | +| `search` | [`geo-places:GetPlace`](https://docs.aws.amazon.com/location/latest/APIReference/API_geoplaces_GetPlace.html)

[`geo-places:SearchNearby`](https://docs.aws.amazon.com/location/latest/APIReference/API_geoplaces_SearchNearby.html)

[`geo-places:SearchText`](https://docs.aws.amazon.com/location/latest/APIReference/API_geoplaces_SearchText.html)

[`geo-places:Suggest`](https://docs.aws.amazon.com/location/latest/APIReference/API_geoplaces_Suggest.html) | + +#### Geofence Collection Actions + +| Custom Action Name | Accessible APIs | +| :------- | :------------------- | +| `create` | [`geo:CreateGeofenceCollection`](https://docs.aws.amazon.com/location/latest/APIReference/API_WaypointGeofencing_CreateGeofenceCollection.html) | +| `read` | [`geo:DescribeGeofenceCollection`](https://docs.aws.amazon.com/location/latest/APIReference/API_WaypointGeofencing_DescribeGeofenceCollection.html)

[`geo:BatchEvaluateGeofences`](https://docs.aws.amazon.com/location/latest/APIReference/API_WaypointGeofencing_BatchEvaluateGeofences.html)

[`geo:ForecastGeofenceEvents`](https://docs.aws.amazon.com/location/latest/APIReference/API_WaypointGeofencing_ForecastGeofenceEvents.html)

[`geo:GetGeofence`](https://docs.aws.amazon.com/location/latest/APIReference/API_WaypointGeofencing_GetGeofence.html) | +| `update` | [`geo:BatchPutGeofence`](https://docs.aws.amazon.com/location/latest/APIReference/API_WaypointGeofencing_BatchPutGeofence.html)

[`geo:PutGeofence`](https://docs.aws.amazon.com/location/latest/APIReference/API_WaypointGeofencing_PutGeofence.html)

[`geo:UpdateGeofenceCollection`](https://docs.aws.amazon.com/location/latest/APIReference/API_WaypointGeofencing_UpdateGeofenceCollection.html) | +| `delete` | [`geo:BatchDeleteGeofence`](https://docs.aws.amazon.com/location/latest/APIReference/API_WaypointGeofencing_BatchDeleteGeofence.html)

[`geo:DeleteGeofenceCollection`](https://docs.aws.amazon.com/location/latest/APIReference/API_WaypointGeofencing_DeleteGeofenceCollection.html) | +| `list` | [`geo:ListGeofences`](https://docs.aws.amazon.com/location/latest/APIReference/API_WaypointGeofencing_ListGeofences.html)

[`geo:ListGeofenceCollections`](https://docs.aws.amazon.com/location/latest/APIReference/API_WaypointGeofencing_ListGeofenceCollections.html) | diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/geo/location-search/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/geo/location-search/index.mdx index c1e1d1203cf..0aa9f79495c 100644 --- a/src/pages/[platform]/build-a-backend/add-aws-services/geo/location-search/index.mdx +++ b/src/pages/[platform]/build-a-backend/add-aws-services/geo/location-search/index.mdx @@ -44,14 +44,80 @@ To add a location search UI component to your map, you can use the [maplibre-gl- Install the necessary dependencies with the following command: ```bash title="Terminal" showLineNumbers={false} -npm add @maplibre/maplibre-gl-geocoder maplibre-gl@1 maplibre-gl-js-amplify +npm add @maplibre/maplibre-gl-geocoder \ + maplibre-gl@1 \ + maplibre-gl-js-amplify \ + @aws-sdk/client-geo-places \ + @aws/amazon-location-utilities-auth-helper ``` > **Note:** Make sure that `maplibre-gl-js-amplify` version `4.0.0` or above is installed. First, create a map onto which you want to add the location search UI component. See the guide on [creating and displaying maps](/[platform]/build-a-backend/add-aws-services/geo/maps). -Then, use `createAmplifyGeocoder()` to get a new instance of `MaplibreGeocoder` and add the location search UI component to the map. + + + +Start off my getting an instance of GeoPlaces by authenticating using the API key and the `AmazonLocationClient`. + +```javascript +import { GeoPlaces, GeoPlacesClient } from "@aws-sdk/client-geo-places"; +import { withAPIKey } from "@aws/amazon-location-utilities-auth-helper"; + +const geoPlaces = getGeoPlaces(); + +function getGeoPlaces() { + const authHelper = amazonLocationClient.withAPIKey(API_KEY, AWS_REGION); // Authenticate using the API key and AWS region + const locationClient = new amazonLocationClient.GeoPlacesClient(authHelper.getClientConfig()); // Create a GeoPlaces client + const geoPlaces = new GeoPlaces(locationClient); // Create GeoPlaces instance + return geoPlaces; // Return the GeoPlaces instance +} +``` + +Create a new instance of `MaplibreGeocoder` and add the location search UI component to the map. Use the `map` from [this](/[platform]/build-a-backend/add-aws-services/geo/maps/#display-a-map) set up tutorial. + +> **Note:** Ensure that your package bundler (webpack, rollup, etc) is configured to handle css files. Check out the webpack documentation [here](https://webpack.js.org/loaders/css-loader/). + +```javascript +import maplibregl from "maplibre-gl"; +import "maplibre-gl/dist/maplibre-gl.css"; +import "@maplibre/maplibre-gl-geocoder/dist/maplibre-gl-geocoder.css"; +import "maplibre-gl-js-amplify/dist/public/amplify-geocoder.css"; // Optional CSS for Amplify recommended styling + +async function initializeMap(mapStyle = "Standard", colorScheme = "Dark") { + const styleUrl = `https://maps.geo.${AWS_REGION}.amazonaws.com/v2/styles/${mapStyle}/descriptor?key=${API_KEY}&color-scheme=${colorScheme}`; + const map = new maplibregl.Map({ + container: 'map', // The ID of the map container + style: styleUrl, // The style URL for the map + center: [-123.1187, 49.2819], // Starting center coordinates + zoom: 11, // Initial zoom levels + validateStyle: false // Disable style validation + }); + return map; // Return the initialized map +} + +const map = initializeMap(); + +// highlight-start +const geocoder = new MaplibreGeocoder(geoPlaces, { + maplibregl, + showResultsWhileTyping: true, // Show results while typing + debounceSearch: 300, // Debounce search requests + limit: 30, // Limit number of results + reverseGeocode: true, // Enable reverse geocoding + zoom: 14, // Zoom level on result selection + placeholder: "Search text or nearby (lat,long)" // Place holder text for search box. +}); + +// Add the search box to the map +map.addControl(geocoder, 'top-left'); +// highlight-end +``` + + + + +Use the `createAmplifyGeocoder()` to get a new instance of `MaplibreGeocoder` and add the location search UI component to the map. > **Note:** Ensure that your package bundler (webpack, rollup, etc) is configured to handle css files. Check out the webpack documentation [here](https://webpack.js.org/loaders/css-loader/). @@ -78,11 +144,25 @@ async function initializeMap() { initializeMap(); ``` + + ![A search box on the top right corner of a map](/images/geocoder-search-box-map.png) ### Display the location search box outside the map + + +You can also use maplibre-gl-geocoder to display the location search UI component anywhere in your application, even outside the map. + +Use `geocoder` from above to create a new `MaplibreGeocoder` and add it within your Amplify project. + +```javascript +document.getElementById("search").appendChild(geocoder.onAdd()); +``` + + + You can also use [maplibre-gl-geocoder](https://github.com/maplibre/maplibre-gl-geocoder) to display the location search UI component anywhere in your application, even outside the map. To do so, extract the html element using function `onAdd()` and attach it anywhere in your DOM instead of adding it via the map's `addControl()` function. @@ -91,11 +171,42 @@ To do so, extract the html element using function `onAdd()` and attach it anywhe const geocoder = createAmplifyGeocoder(); document.getElementById("search").appendChild(geocoder.onAdd()); ``` + + ![A search box with multiple Starbucks locations](/images/geocoder-search-box.png) ### Customize Search Icons + + +You can customize the search icons used by the [maplibre-gl-geocoder](https://github.com/maplibre/maplibre-gl-geocoder) to use any image of your choosing. [MapLibre markers](https://maplibre.org/maplibre-gl-js/docs/API/#markers-and-controls) require an [HTMLElement](https://developer.mozilla.org/en-US/docs/Web/HTML/Element) when passing in custom images. + +The following example puts an existing SVG icon into an HTMLElement before being passed to `createAmplifyGeocoder` which creates a [maplibre-gl-geocoder](https://github.com/maplibre/maplibre-gl-geocoder). + +```javascript +import myIcon from "./myIcon.svg" // relative path to your custom icon + +const icon = new Image(100, 100); +icon.src = myIcon; + +const geocoder = new MaplibreGeocoder(geoPlaces, { + maplibregl, + showResultsWhileTyping: true, // Show results while typing + debounceSearch: 300, // Debounce search requests + limit: 30, // Limit number of results + reverseGeocode: true, // Enable reverse geocoding + zoom: 14, // Zoom level on result selection + placeholder: "Search text or nearby (lat,long)", // Place holder text for search box. + // highlight-next-line + showResultMarkers: { element: icon } +}); + +map.addControl(geocoder); +``` + + + You can customize the search icons used by the [maplibre-gl-geocoder](https://github.com/maplibre/maplibre-gl-geocoder) to use any image of your choosing. [MapLibre markers](https://maplibre.org/maplibre-gl-js/docs/API/#markers-and-controls) require an [HTMLElement](https://developer.mozilla.org/en-US/docs/Web/HTML/Element) when passing in custom images. The following example puts an existing SVG icon into an HTMLElement before being passed to `createAmplifyGeocoder` which creates a [maplibre-gl-geocoder](https://github.com/maplibre/maplibre-gl-geocoder). @@ -109,6 +220,8 @@ icon.src = myIcon; const geocoder = createAmplifyGeocoder({ showResultMarkers: { element: icon } }); map.addControl(geocoder); ``` + + ![A search box on a map with multiple pointers](/images/geocoder-custom-images.png) diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/geo/maps/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/geo/maps/index.mdx index 8db2d651954..9b7233fbdb5 100644 --- a/src/pages/[platform]/build-a-backend/add-aws-services/geo/maps/index.mdx +++ b/src/pages/[platform]/build-a-backend/add-aws-services/geo/maps/index.mdx @@ -52,10 +52,50 @@ npm add maplibre-gl maplibre-gl-js-amplify Verify the following: - `maplibre-gl-js-amplify` version `4.0.0` or above is installed -- Any package bundlers (webpack, rollup, etc) are configured to handle css files. Check out the webpack documentation [here](https://webpack.js.org/loaders/css-loader/). +- Any package bundlers (webpack, rollup, etc) are configured to handle css files. Check out the webpack documentation [here](https://webpack.js.org/loaders/css-loader/). + + + + +You can render your map using an existing or provisioned API key. To generate API keys with Amplify Geo, visit the [set up page](/[platform]/build-a-backend/add-aws-services/geo/set-up-geo/#generate-api-keys) to learn more about setting up API keys. + +Start by importing the following libraries into your application: + +```ts +import * from 'maplibre-gl-js' as maplibregl; +import 'maplibre-gl/dist/maplibre-gl.css'; +``` + +Next, create and render the [Map](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/) by creating an instance through . + +**Note:** There must be a `div` with an `id="map"` on the DOM before making the call to `maplibregl.Map` in this way. + +With the region of your generated API key and the hidden value, you can use the `maplibregl.Map` function to render a map with a customized style and color scheme. Visit the official Amazon Location Service documentation to learn more about [style specifications](https://docs.aws.amazon.com/location/latest/developerguide/map-styles.html). +```javascript +const API_KEY = "Your_API_Key"; // your hidden value (should be v1.public.a1b2c3d4...) +const AWS_REGION = "Region_where_you_created_API_Key"; + +function initializeMap(mapStyle = "Standard", colorScheme = "Dark") { + const styleUrl = `https://maps.geo.${AWS_REGION}.amazonaws.com/v2/styles/${mapStyle}/descriptor?key=${API_KEY}&color-scheme=${colorScheme}`; + const map = new maplibregl.Map({ + container: 'map', // The ID of the map container + style: styleUrl, // The style URL for the map + center: [-123.1187, 49.2819], // Starting center coordinates + zoom: 11, // Initial zoom levels + validateStyle: false // Disable style validation + }); + return map; // Return the initialized map +} + +const map = initializeMap(); +``` + + + + Import the library into your application: ```javascript @@ -117,6 +157,10 @@ body, + + + + ![A map centered on Vancouver](/images/display-map.png) ## Display markers on map diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/geo/set-up-geo/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/geo/set-up-geo/index.mdx index 69846f5b435..61c722d740b 100644 --- a/src/pages/[platform]/build-a-backend/add-aws-services/geo/set-up-geo/index.mdx +++ b/src/pages/[platform]/build-a-backend/add-aws-services/geo/set-up-geo/index.mdx @@ -27,78 +27,173 @@ export function getStaticProps(context) { }; } -Amplify provides APIs and map UI components for maps and location search for your web apps.You can add maps and location search functionality to your app in just a few lines of code. The following is an example utilizing the [AWS Cloud Development Kit (AWS CDK)](https://docs.aws.amazon.com/cdk/latest/guide/home.html) to create a Geo resource powered by [Amazon Location Services](https://aws.amazon.com/location/). But do note there are no official hand-written (L2) constructs for this service yet. +In this guide, you will learn how to set up Geo in your Amplify project. You will set up your backend resources, manage their access, and integrate geo maps, place indices, and geofence collections within your application. + +If you have not yet created an Amplify project, visit the [quickstart guide](/[platform]/start/quickstart/). + +Amazon Location Services now offers independent APIs and UI components for maps and location search for your web apps, eliminating the need to provision these resources. You can add maps, location search (place index), and geofencing functionality to your app in just a few lines of code. Learn more about these resources [here](https://docs.aws.amazon.com/location/latest/developerguide/what-is.html). + +## Building your Geo backend + +First, create a file `amplify/geo/resource.ts` within your Amplify project. This file will be the location to configure your Geo backend resources. This entails managing access to maps and location search and provisioning geofence collections. For example, you can instantiate a geofence collection, place index, or a map resource by using the `defineMap`, `definePlace`, or `defineCollection` functions and providing a `name` for these resources. + +```ts title="amplify/geo/resource.ts" +import { + defineMap, + defineCollection, + definePlace, +} from '@aws-amplify/backend-geo'; + +export const map = defineMap({ + name: 'amplifyMap', +}); + +export const place = definePlace({ + name: 'amplifyPlaceIndex', +}); + +export const collection = defineCollection({ + name: 'amplifyCollection' +}); +``` + +Now, import these resource definitions within your `amplify/backend.ts` file that contains your backend definition. Add these Geo resources to `defineBackend`. ```ts title="amplify/backend.ts" -import { defineBackend } from "@aws-amplify/backend"; -import { Policy, PolicyStatement } from "aws-cdk-lib/aws-iam"; -import { CfnMap } from "aws-cdk-lib/aws-location"; -import { Stack } from "aws-cdk-lib/core"; -import { auth } from "./auth/resource"; -import { data } from "./data/resource"; - -const backend = defineBackend({ +import { defineBackend } from '@aws-amplify/backend'; +import { auth } from './auth/resource.js'; +// highlight-next-line +import { map, place, collection } from './geo/resource.js'; + +defineBackend({ auth, - data, - // additional resources + // highlight-start + map, + place, + collection, + // highlight-end +}); +``` + +To deploy these resources to your cloud sandbox, run the CLI command in your terminal: + + +```bash title="Terminal" showLineNumbers={false} +npx ampx sandbox +``` + + + + + +```bash title="Terminal" showLineNumbers={false} +npx ampx sandbox --outputs-out-dir +``` + + + + + +```bash title="Terminal" showLineNumbers={false} +npx ampx sandbox --outputs-out-dir +``` + + + + +```bash title="Terminal" showLineNumbers={false} +npx ampx sandbox --outputs-format dart --outputs-out-dir lib +``` + + + +This command will deploy a Geofence Collection to your cloud sandbox and generate access policies to integrate the map and location search resources with your Amplify project. + +## Define resource access permissions + +All maps, place indices, and geofence collections requested by Amplify Geo are inaccessible by users or other resources by default. Access to these resources must be explicitly granted within the `access` callback of the `defineMap`, `definePlace`, and `defineCollection` functions. Refer to [this](/[platform]/build-a-backend/add-aws-services/geo/custom-authorization/) page to learn more about access customization and possible access actions. + +The following example shows you how you can set up your map and collection access structure for authorized and guest users. + +1. Guests only have access to read into and list geofence collections. +2. Authenticated users can create, read, update, and delete geofence collections while also being able to access the static ma managed by AWS. + +```ts title="amplify/geo/resource.ts" +export const map = defineMap({ + name: 'amplifyMap', + access: (allow) => [ + allow.authenticated.to(['get']) + ], }); -const geoStack = backend.createStack("geo-stack"); - -// create a location services map -const map = new CfnMap(geoStack, "Map", { - mapName: "myMap", - description: "Map", - configuration: { - style: "VectorEsriNavigation", - }, - pricingPlan: "RequestBasedUsage", - tags: [ - { - key: "name", - value: "myMap", - }, +export const collection = defineCollection({ + name: 'amplifyCollection', + access: (allow) => [ + allow.authenticated.to(['create', 'read', 'update', 'delete']), + allow.guest.to(['read', 'list']), ], }); +``` + + -// create an IAM policy to allow interacting with geo resource -const myGeoPolicy = new Policy(geoStack, "GeoPolicy", { - policyName: "myGeoPolicy", - statements: [ - new PolicyStatement({ - actions: [ - "geo:GetMapTile", - "geo:GetMapSprites", - "geo:GetMapGlyphs", - "geo:GetMapStyleDescriptor", - ], - resources: [map.attrArn], - }), + + +AWS Location API keys currently do not support geofence collections or their associated APIs. Adding access definitions for any API keys using the `allow.apiKey.to()` definition will NOT result in the creation of an API key. + + + +## Generate API Keys + +You can use AWS Location API keys to authenticate and authorize anonymous users to use Geo resources. Refer to the [Amazon Location documentation](https://docs.aws.amazon.com/location/latest/developerguide/access.html) to learn more about authentication with API keys. + +To generate API keys for your map and location resources, you can configure their generation during resource instantiation. + +```ts title="amplify/geo/resource.ts" +export const map = defineMap({ + name: 'amplifyMap', + access: (allow) => [ + allow.authenticated.to(['get']) + // highlight-next-line + allow.apiKey.to(['get']) ], + // highlight-start + apiKeyProps: { + apiKeyName: 'testMapKey', + noExpiry: true + } + // highlight-end }); -// apply the policy to the authenticated and unauthenticated roles -backend.auth.resources.authenticatedUserIamRole.attachInlinePolicy(myGeoPolicy); -backend.auth.resources.unauthenticatedUserIamRole.attachInlinePolicy(myGeoPolicy); - -// patch the map resource to the expected output configuration -backend.addOutput({ - geo: { - aws_region: geoStack.region, - maps: { - items: { - [map.mapName]: { - style: "VectorEsriNavigation", - }, - }, - default: map.mapName, - }, - }, +export const collection = defineCollection({ + name: 'amplifyCollection', + access: (allow) => [ + allow.authenticated.to(['search', 'geocode', 'autocomplete']), + allow.guest.to(['search']), + // highlight-next-line + allow.apiKey.to(['search', 'geocode']) + ], + // highlight-start + apiKeyProps: { + apiKeyName: 'testIndexKey', + noExpiry: false + } + // highlight-end }); ``` +This will generate AWS Location API keys configured with the restrictions provided in the `access` block. The names of all provisioned API keys will then appear in the `amplify_outputs.json` file. To access their hidden values through AWS CLI, refer to the instructions below. You can also view the hidden value of your key through the AWS Location Services Console. - +Install the latest version of the [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) and configure it with your AWS account. + +```bash title="Terminal" showLineNumbers={false} +aws location describe-key \ + --key-name +``` + + +**Note:** To access information about generated API keys, you must ensure that `geo:DescribeKey` access is granted to your user roles and resources. learn more about setting up access for Location resources [here](https://docs.aws.amazon.com/location/latest/developerguide/set-up.html). + ## Configure your application diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/geo/use-legacy-resources/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/geo/use-legacy-resources/index.mdx new file mode 100644 index 00000000000..1edc0731691 --- /dev/null +++ b/src/pages/[platform]/build-a-backend/add-aws-services/geo/use-legacy-resources/index.mdx @@ -0,0 +1,575 @@ +import { getCustomStaticPath } from '@/utils/getCustomStaticPath'; + +export const meta = { + title: 'Use legacy Geo resources', + description: 'AWS Amplify Geo module provides a simple way to get map data, search for places, and reverse geocoding.', + platforms: [ + 'javascript', + 'swift', + 'android', + 'angular', + 'nextjs', + 'react', + 'vue' + ], +}; + +export const getStaticPaths = async () => { + return getCustomStaticPath(meta.platforms); +}; + +export function getStaticProps(context) { + return { + props: { + platform: context.params.platform, + meta + } + }; +} + +Amplify provides APIs and map UI components for maps and location search for your web apps.You can add maps and location search functionality to your app in just a few lines of code. The following is an example utilizing the [AWS Cloud Development Kit (AWS CDK)](https://docs.aws.amazon.com/cdk/latest/guide/home.html) to create a Geo resource powered by [Amazon Location Services](https://aws.amazon.com/location/). + +## Set up Maps + +Add the following code to your `backend.ts` file: + +```ts title="amplify/backend.ts" +import { defineBackend } from "@aws-amplify/backend"; +import { Policy, PolicyStatement } from "aws-cdk-lib/aws-iam"; +import { CfnMap } from "aws-cdk-lib/aws-location"; +import { Stack } from "aws-cdk-lib/core"; +import { auth } from "./auth/resource"; +import { data } from "./data/resource"; + +const backend = defineBackend({ + auth, + data, + // additional resources +}); + +const geoStack = backend.createStack("geo-stack"); + +// create a location services map +const map = new CfnMap(geoStack, "Map", { + mapName: "myMap", + description: "Map", + configuration: { + style: "VectorEsriNavigation", + }, + pricingPlan: "RequestBasedUsage", + tags: [ + { + key: "name", + value: "myMap", + }, + ], +}); + +// create an IAM policy to allow interacting with geo resource +const myGeoPolicy = new Policy(geoStack, "GeoPolicy", { + policyName: "myGeoPolicy", + statements: [ + new PolicyStatement({ + actions: [ + "geo:GetMapTile", + "geo:GetMapSprites", + "geo:GetMapGlyphs", + "geo:GetMapStyleDescriptor", + ], + resources: [map.attrArn], + }), + ], +}); + +// apply the policy to the authenticated and unauthenticated roles +backend.auth.resources.authenticatedUserIamRole.attachInlinePolicy(myGeoPolicy); +backend.auth.resources.unauthenticatedUserIamRole.attachInlinePolicy(myGeoPolicy); + +// patch the map resource to the expected output configuration +backend.addOutput({ + geo: { + aws_region: geoStack.region, + maps: { + items: { + [map.mapName]: { + style: "VectorEsriNavigation", + }, + }, + default: map.mapName, + }, + }, +}); +``` + +### Map Pricing Plan +The pricing plan for the Map example is set to `RequestBasedUsage`. +We advice you to go through the [location service pricing](https://aws.amazon.com/location/pricing/) along with the [location service terms](https://aws.amazon.com/service-terms/) (_82.5 section_) to learn more about the pricing plan. + +## Set up Places + +Amplify's `geo` category enables you to search by places, addresses, and coordinates in your app with "place index" resources. + +```ts title="amplify/backend.ts" +import { defineBackend } from "@aws-amplify/backend"; +import { Policy, PolicyStatement } from "aws-cdk-lib/aws-iam"; +// highlight-next-line +import { CfnMap, CfnPlaceIndex } from "aws-cdk-lib/aws-location"; +import { auth } from "./auth/resource"; +import { data } from "./data/resource"; + +const backend = defineBackend({ + auth, + data, + // additional resources +}); + +const geoStack = backend.createStack("geo-stack"); + +// create a location services map +const map = new CfnMap(geoStack, "Map", { + mapName: "myMap", + description: "Map", + configuration: { + style: "VectorEsriNavigation", + }, + pricingPlan: "RequestBasedUsage", + tags: [ + { + key: "name", + value: "myMap", + }, + ], +}); + + +// create an IAM policy to allow interacting with geo resource +const myGeoPolicy = new Policy(geoStack, "GeoPolicy", { + policyName: "myGeoPolicy", + statements: [ + new PolicyStatement({ + actions: [ + "geo:GetMapTile", + "geo:GetMapSprites", + "geo:GetMapGlyphs", + "geo:GetMapStyleDescriptor", + ], + resources: [map.attrArn], + }), + ], +}); + +// apply the policy to the authenticated and unauthenticated roles +backend.auth.resources.authenticatedUserIamRole.attachInlinePolicy(myGeoPolicy); +backend.auth.resources.unauthenticatedUserIamRole.attachInlinePolicy(myGeoPolicy); + +// highlight-start +// create a location services place index +const myIndex = new CfnPlaceIndex(geoStack, "PlaceIndex", { + dataSource: "Here", + dataSourceConfiguration: { + intendedUse: "SingleUse", + }, + indexName: "myPlaceIndex", + pricingPlan: "RequestBasedUsage", + tags: [ + { + key: "name", + value: "myPlaceIndex", + }, + ], +}); + +// create a policy to allow access to the place index +const myIndexPolicy = new Policy(geoStack, "IndexPolicy", { + policyName: "myIndexPolicy", + statements: [ + new PolicyStatement({ + actions: [ + "geo:SearchPlaceIndexForPosition", + "geo:SearchPlaceIndexForText", + "geo:SearchPlaceIndexForSuggestions", + "geo:GetPlace", + ], + resources: [myIndex.attrArn], + }), + ], +}); + +// attach the policy to the authenticated and unauthenticated IAM roles +backend.auth.resources.authenticatedUserIamRole.attachInlinePolicy(myIndexPolicy); +backend.auth.resources.unauthenticatedUserIamRole.attachInlinePolicy(myIndexPolicy); +// highlight-end + +// patch the place index resource to the expected output configuration +backend.addOutput({ + geo: { + aws_region: geoStack.region, + maps: { + items: { + [map.mapName]: { + style: "VectorEsriNavigation", + }, + }, + default: map.mapName, + }, +// highlight-start + search_indices: { + default: myIndex.indexName, + items: [myIndex.indexName], + }, +// highlight-end + }, +}); +``` + +### Location Search Index Pricing Plan +The pricing plan for Search Index will be set to `RequestBasedUsage`. +We advice you to go through the [location service pricing](https://aws.amazon.com/location/pricing/) along with the [location service terms](https://aws.amazon.com/service-terms/) (_82.5 section_) to learn more about the pricing plan. + +### Advanced Settings +You can optionally configure the data provider and result storage location for your location search index. + +### Location Search data provider +You can select a data provider as the source for geocoding, reverse geocoding and searches. +Each provider gathers and curates their data using different means. They may also have varying expertise in different regions of the world. +The available data providers of geospatial data are shown. To learn more about data providers, please refer this [location service documentation](https://docs.aws.amazon.com/location/latest/developerguide/what-is-data-provider.html). + +- Here – For additional information about HERE Technologies, see [Here guide](https://docs.aws.amazon.com/location/latest/developerguide/HERE.html). +- Esri – For additional information about Esri, see [Esri guide](https://docs.aws.amazon.com/location/latest/developerguide/esri.html). + + + +**Note:** If your application is tracking or routing assets you use in your business (such as delivery vehicles or employees), you may only use `HERE` as your geolocation provider. +See section 82 of the [AWS service terms](https://aws.amazon.com/service-terms/) for more details. + + + +### Location Search result storage location +You can specify how the results of a search operation will be stored by the caller. + +- SingleUse - specifies that the results won't be stored. +- Storage - specifies that the result can be cached or stored in a database. + +Refer [this location service doc](https://docs.aws.amazon.com/location-places/latest/APIReference/API_DataSourceConfiguration.html#locationplaces-Type-DataSourceConfiguration-IntendedUse) for more information. + + + +## Configure your application + +To display a map in your application, you can use the [Amplify React MapView component](https://ui.docs.amplify.aws/react/components/geo) or the [MapLibre GL](https://github.com/maplibre/maplibre-gl-js) with `maplibre-gl-js-amplify` libraries are required. + +Install the necessary dependencies by running the following command: + +```bash title="Terminal" showLineNumbers={false} +npm add aws-amplify @aws-amplify/geo +``` + +> **Note:** Make sure that version `6.0.0` or above is installed. + +Import and load the configuration file in your app. It's recommended you add the Amplify configuration step to your app's root entry point. + + +```javascript title="src/index.js" +import { Amplify } from 'aws-amplify'; +import outputs from '../amplify_outputs.json'; +Amplify.configure(outputs); +``` + + + + +```javascript title="pages/_app.js" +import { Amplify } from 'aws-amplify'; +import outputs from '@/amplify_outputs.json'; +Amplify.configure(outputs); +``` + + + + + +Make sure you call `Amplify.configure` as early as possible in your application’s life-cycle. A missing configuration or `NoCredentials` error is thrown if `Amplify.configure` has not been called before other Amplify JavaScript APIs. + + + + + + + +Amplify Geo provides APIs and map UI components for mobile app development such that you can add maps to your app in just a few lines of code. Amplify Geo APIs are powered by [Amazon Location Service](https://aws.amazon.com/location/) and the map UI components from [MapLibre](https://maplibre.org/) are already integrated with the Geo APIs. + + +## Prerequisites + + +* An Android application targeting at least Android SDK API level 24 with Amplify libraries integrated + * For a full example of creating Android project, please follow the [project setup walkthrough](/[platform]/start/quickstart/) + + + +An application with Amplify libraries integrated and a minimum target of any of the following: +- **iOS 13.0**, using **Xcode 14.1** or later. +- **macOS 10.15**, using **Xcode 14.1** or later. +- **tvOS 13.0**, using **Xcode 14.3** or later. +- **watchOS 9.0**, using **Xcode 14.3** or later. +- **visionOS 1.0**, using **Xcode 15 beta 2** or later. (Preview support - see below for more details.) + +For a full example, please follow the [project setup walkthrough](/[platform]/start/quickstart/). + + + +visionOS support is currently in **preview** and can be used by using the latest [Amplify Release](https://github.com/aws-amplify/amplify-swift/releases). +As new Xcode and visionOS versions are released, the support will be updated with any necessary fixes on a best effort basis. + + + + + +## Install Amplify Libraries + + +Add the following dependencies to your **build.gradle.kts (Module :app)** file and click "Sync Now" when prompted: + +```kotlin title="app/build.gradle.kts" +android { + compileOptions { + // Support for Java 8 features + isCoreLibraryDesugaringEnabled = true + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } +} + +dependencies { + // Amplify API dependencies + // highlight-start + implementation("com.amplifyframework:aws-auth-cognito:ANDROID_VERSION") + implementation("com.amplifyframework:aws-geo-location:ANDROID_VERSION") + // highlight-end + // ... other dependencies + coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.3") +} +``` + + + +**Note:** The Geo plugin has a dependency on Cognito Auth. + + + + + +The Geo plugin is dependent on Cognito Auth. + +1. To install the Amplify Libraries in your application, open your project in Xcode and select **File > Add Packages...**. + +2. Enter the **Amplify Library for Swift** GitHub repo URL (`https://github.com/aws-amplify/amplify-swift`) into the search bar and click **Add Package**. + + + + **Note:** **Up to Next Major Version** should be selected from the **Dependency Rule** dropdown. + + + +3. Lastly, add **AWSLocationGeoPlugin**, **AWSCognitoAuthPlugin**, and **Amplify** to your target. Then click **Add Package**. + + + +## Initialize Amplify Geo + + +To initialize Amplify Geo, use the `Amplify.addPlugin()` method to add the AWS Location Geo plugin. Next, finish configuring Amplify by calling `Amplify.configure()`. + +Add the following code to your `onCreate()` method in your application class: + + +Before calling the `Amplify.configure` function, make sure to either download the `amplify_outputs.json` file from the console, or generate it with the following command: + +```bash title="Terminal" showLineNumbers={false} +npx ampx generate outputs --app-id --branch main --out-dir app/src/main/res/raw +``` + +Next, be sure the file you generated or downloaded is in the appropriate resource directory for your application (for example, `app/src/main/res/raw`) in your Android project. Otherwise, you will not be able to compile your application. + + + + + +```java +Amplify.addPlugin(new AWSCognitoAuthPlugin()); +Amplify.addPlugin(new AWSLocationGeoPlugin()); +Amplify.configure(AmplifyOutputs.fromResource(R.raw.amplify_outputs), getApplicationContext()); +``` + +Your class will look like this: + +```java +public class MyAmplifyApp extends Application { + @Override + public void onCreate() { + super.onCreate(); + + try { + Amplify.addPlugin(new AWSCognitoAuthPlugin()); + Amplify.addPlugin(new AWSLocationGeoPlugin()); + Amplify.configure(AmplifyOutputs.fromResource(R.raw.amplify_outputs), getApplicationContext()); + Log.i("MyAmplifyApp", "Initialized Amplify"); + } catch (AmplifyException error) { + Log.e("MyAmplifyApp", "Could not initialize Amplify", error); + } + } +} +``` + + + + +```kotlin +Amplify.addPlugin(AWSCognitoAuthPlugin()) +Amplify.addPlugin(AWSLocationGeoPlugin()) +Amplify.configure(AmplifyOutputs.fromResource(R.raw.amplify_outputs), applicationContext) +``` + +Your class will look like this: + +```kotlin +class MyAmplifyApp : Application() { + override fun onCreate() { + super.onCreate() + + try { + Amplify.addPlugin(AWSCognitoAuthPlugin()) + Amplify.addPlugin(AWSLocationGeoPlugin()) + Amplify.configure(AmplifyOutputs.fromResource(R.raw.amplify_outputs), applicationContext) + Log.i("MyAmplifyApp", "Initialized Amplify") + } catch (error: AmplifyException) { + Log.e("MyAmplifyApp", "Could not initialize Amplify", error) + } + } +} +``` + + + + +```java +RxAmplify.addPlugin(new AWSCognitoAuthPlugin()); +RxAmplify.addPlugin(new AWSLocationGeoPlugin()); +RxAmplify.configure(AmplifyOutputs.fromResource(R.raw.amplify_outputs), getApplicationContext()); +``` + +Your class will look like this: + +```java +public class MyAmplifyApp extends Application { + @Override + public void onCreate() { + super.onCreate(); + + try { + RxAmplify.addPlugin(new AWSCognitoAuthPlugin()); + RxAmplify.addPlugin(new AWSLocationGeoPlugin()); + RxAmplify.configure(AmplifyOutputs.fromResource(R.raw.amplify_outputs), getApplicationContext()); + Log.i("MyAmplifyApp", "Initialized Amplify"); + } catch (AmplifyException error) { + Log.e("MyAmplifyApp", "Could not initialize Amplify", error); + } + } +} +``` + + + + +Upon building and running this application you should see the following in your console window: + +```console +Initialized Amplify +``` + + + + +Make sure to generate the `amplify_outputs.json` file by running the following command: + +```bash title="Terminal" showLineNumbers={false} +npx ampx sandbox +``` + +Next, move the file to your project. You can do this by dragging and dropping the file into your Xcode project. + + +To initialize Amplify Geo, use the `Amplify.add(plugin:)` method to add the AWS Location Geo plugin. Next, finish configuring Amplify by calling `Amplify.configure(with:)`. + +Open the main file of the application - `AppDelegate.swift` or `App.swift` depending on the app's life cycle - and **add the following** import statements at the top of the file: + +```swift +import Amplify +import AWSCognitoAuthPlugin +import AWSLocationGeoPlugin +``` + +In the same file, **create a function** to configure Amplify: +```swift +func configureAmplify() { + do { + try Amplify.add(plugin: AWSCognitoAuthPlugin()) + try Amplify.add(plugin: AWSLocationGeoPlugin()) + try Amplify.configure(with: .amplifyOutputs) + print("Initialized Amplify"); + } catch { + print("Could not initialize Amplify: \(error)") + } +} +``` + +Now **call the `configureAmplify()` function** in the starting point of your application. + + + +```swift +@main +struct App: App { + // add a default initializer and configure Amplify + public init() { + configureAmplify() + } +} +``` + + + + +```swift +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + func application(_: UIApplication, + didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + configureAmplify() + return true + } + // ... +} +``` + + + + +Upon building and running this application you should see the following in your console window: + +```console +Initialized Amplify +``` + + + + + +**Notes:** +- If you want to use existing Amazon Location Service resources [follow this guide](/[platform]/build-a-backend/add-aws-services/geo/existing-resources/) instead. +- If you want to use Amazon Location Service APIs not directly supported by Geo, use the [escape hatch](/[platform]/build-a-backend/add-aws-services/geo/amazon-location-sdk/) to access the Amazon Location Service SDK. + +### References + +[Location Construct Library](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_location-readme.html)