Use an online service to find the address for a tapped point.
Use case
You might use a geocoder to find a customer's delivery address based on the location returned by their device's GPS.
How to use the sample
Tap the map to see the nearest address displayed in a callout.
How it works
- Create a
LocatorTaskobject using a URL to a geocoder service. - Set the
GeocodeParametersfor theLocatorTaskand specify the geocoder's attributes. - Get the matching results from the
GeocodeResultusingLocatorTask.reverseGeocodeAsync. - Show the results using a
PictureMarkerSymboland add the symbol to aGraphicin theGraphicsOverlay.
Additional information
This sample uses the World Geocoding Service. For more information, see the Geocoding service help topic on the ArcGIS Developer website.
Relevant API
- GeocodeParameters
- LocatorTask
- ReverseGeocodeParameters
Tags
address, geocode, locate, reverse geocode, search
Sample Code
ReverseGeocode.cs
// Copyright 2019 Esri.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
// language governing permissions and limitations under the License.
using Android.App;
using Android.OS;
using Android.Widget;
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Symbology;
using Esri.ArcGISRuntime.Tasks.Geocoding;
using Esri.ArcGISRuntime.UI;
using Esri.ArcGISRuntime.UI.Controls;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Android.Views;
namespace ArcGISRuntimeXamarin.Samples.ReverseGeocode
{
[Activity (ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
[ArcGISRuntime.Samples.Shared.Attributes.Sample(
name: "Reverse geocode",
category: "Search",
description: "Use an online service to find the address for a tapped point.",
instructions: "Tap the map to see the nearest address displayed in a callout.",
tags: new[] { "address", "geocode", "locate", "reverse geocode", "search" })]
public class ReverseGeocode : Activity
{
// Create and hold reference to the MapView.
private MapView _myMapView;
// Service Uri to be provided to the LocatorTask (geocoder).
private readonly Uri _serviceUri = new Uri("https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer");
// The LocatorTask provides geocoding services.
private LocatorTask _geocoder;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
Title = "Reverse geocode";
CreateLayout();
Initialize();
}
private async void Initialize()
{
// Create new Map with basemap.
Map myMap = new Map(BasemapStyle.ArcGISImagery);
// Provide used Map to the MapView.
_myMapView.Map = myMap;
// Add a graphics overlay to the map for showing where the user tapped.
_myMapView.GraphicsOverlays.Add(new GraphicsOverlay());
// Enable tap-for-info pattern on results.
_myMapView.GeoViewTapped += _myMapView_GeoViewTapped;
// Initialize the LocatorTask with the provided service Uri.
try
{
_geocoder = await LocatorTask.CreateAsync(_serviceUri);
}
catch (Exception e)
{
new AlertDialog.Builder(this).SetMessage(e.ToString()).SetTitle("Error").Show();
}
// Set the initial viewpoint.
await _myMapView.SetViewpointCenterAsync(34.058, -117.195, 5e4);
}
private async void _myMapView_GeoViewTapped(object sender, GeoViewInputEventArgs e)
{
try
{
// Clear the existing graphics & callouts.
_myMapView.DismissCallout();
_myMapView.GraphicsOverlays[0].Graphics.Clear();
// Add a graphic for the tapped point.
Graphic pinGraphic = await GraphicForPoint(e.Location);
_myMapView.GraphicsOverlays[0].Graphics.Add(pinGraphic);
// Normalize the geometry - needed if the user crosses the international date line.
MapPoint normalizedPoint = (MapPoint)GeometryEngine.NormalizeCentralMeridian(e.Location);
// Reverse geocode to get addresses.
IReadOnlyList<GeocodeResult> addresses = await _geocoder.ReverseGeocodeAsync(normalizedPoint);
// Get the first result.
GeocodeResult address = addresses.First();
// Use the city and region for the Callout Title.
string calloutTitle = address.Attributes["Address"].ToString();
// Use the metro area for the Callout Detail.
string calloutDetail = address.Attributes["City"] +
" " + address.Attributes["Region"] +
" " + address.Attributes["CountryCode"];
// Define the callout.
CalloutDefinition calloutBody = new CalloutDefinition(calloutTitle, calloutDetail);
// Show the callout on the map at the tapped location.
_myMapView.ShowCalloutForGeoElement(pinGraphic, e.Position, calloutBody);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex);
new AlertDialog.Builder(this).SetMessage("No results found.").SetTitle("No results").Show();
}
}
private async Task<Graphic> GraphicForPoint(MapPoint point)
{
// Get current assembly that contains the image.
Assembly currentAssembly = Assembly.GetExecutingAssembly();
// Get image as a stream from the resources.
// Picture is defined as EmbeddedResource and DoNotCopy.
Stream resourceStream = currentAssembly.GetManifestResourceStream(
"ArcGISRuntime.Resources.PictureMarkerSymbols.pin_star_blue.png");
// Create new symbol using asynchronous factory method from stream.
PictureMarkerSymbol pinSymbol = await PictureMarkerSymbol.CreateAsync(resourceStream);
pinSymbol.Width = 60;
pinSymbol.Height = 60;
// The image is a pin; offset the image so that the pinpoint.
// is on the point rather than the image's true center.
pinSymbol.LeaderOffsetX = 30;
pinSymbol.OffsetY = 14;
return new Graphic(point, pinSymbol);
}
private void CreateLayout()
{
// Create a new vertical layout for the app.
var layout = new LinearLayout(this) { Orientation = Orientation.Vertical };
// Add a help label.
TextView helpLabel = new TextView(this);
helpLabel.Text = "Tap to find the nearest address.";
helpLabel.Gravity = GravityFlags.Center;
layout.AddView(helpLabel);
// Add the map view to the layout.
_myMapView = new MapView(this);
layout.AddView(_myMapView);
// Show the layout in the app.
SetContentView(layout);
}
}
}