Maps are another truly cool part of mobile computing. They provide a means of navigation, finding points of interest in an area, as well as supporting many other useful scenarios.
There are two basic approaches to interfacing with maps from an app:
The first option is much easier to implement, whereas the second option allows for tighter integration and control of the maps at the cost of more code and complexity.
We chose to go with the first option for the POIApp
example for the following reasons:
Xamarin's website contains articles with all the details required to get the second option working.
To navigate to the map app, we will rely on the Intent
class we used earlier in the book; however, rather than specifying the Activity
class we want to start, we will specify the type of information we would like to view using a URI. Android contains a registry of apps that can display different types of information and will launch the most appropriate app.
The Android platform defines a set of Intent
classes that can be used to launch Google apps on Android devices. The following table summarizes the Intent
classes related to locations:
URI |
Action |
---|---|
|
This action opens the map application centered at a latitude or longitude. |
|
This action opens the map application centered at a latitude or longitude and zoomed to the specified level. |
|
This action opens the map application to the location of a street address. |
|
This action opens the map application and displays the annotated search results. |
In our case, we have a street address, latitude and longitude, or both. If the street address is present, we should build the Intent
class with it, because this will cause the street address to appear in the map app, making it more user friendly. If the street address is not present, we will build the Intent
class using latitude and longitude. The following code shows the logic for building the Intent
class:
Android.Net.Uri geoUri; if (String.IsNullOrEmpty (_addrEditText.Text)) { geoUri = Android.Net.Uri.Parse (String.Format("geo:{0},{1}", _poi.Latitude, _poi.Longitude)); } else { geoUri = Android.Net.Uri.Parse (String.Format("geo:0,0?q={0}", _addrEditText.Text)); } Intent mapIntent = new Intent (Intent.ActionView, geoUri);
Prior to launching the Intent
class, we need to be sure there is an app that can handle the Intent
class; otherwise, we might end up with an unhandled exception from StartActivity()
.
Apps provide information about any capabilities they provide (the Intent
classes) in their manifest files as an <intent-filter/>
element. Since we are relying on an external map app to display our location for us, we should check to be sure such an app exists on the device we are running on. We accomplish this with a few calls to the PackageManager
class. The PackageManager
class allows you to retrieve various types of information about the application packages installed on a device. The QueryIntentActivities()
method allows you to check if there are any apps available to handle a specific Intent
class. The following code demonstrates the use of QueryIntentActivities()
:
PackageManager packageManager = PackageManager; IList<ResolveInfo> activities = packageManager.QueryIntentActivities(mapIntent, 0); if (activities.Count == 0) { AlertDialog.Builder alertConfirm = new AlertDialog.Builder (this); alertConfirm.SetCancelable (false); alertConfirm.SetPositiveButton ("OK", delegate {}); alertConfirm.SetMessage ("No map app available."); alertConfirm.Show (); } else StartActivity (mapIntent);
Create a MapClicked()
event handler, attach it to the mapImageButton
, and fill in the logic for building and starting the Intent
class.
Run POIApp
and test navigating to the map from POI. You will notice that once the map app has been presented with the POI location, you have the option of choosing to navigate to it from your current location.
3.145.206.169