Android Location

Download Report

Transcript Android Location

Android Location Maps
Mobile Application Development
Selected Topics – CPIT 490
8-Apr-16
Objective


Android Location
 MapViews
 Overlays
Google Maps External Library
 Location Services
2
Location Service



Two main LBS elements
 Location Manager: Provides hooks to the location-based services
 Location Providers: Each of these represents a different location finding technology used to determine the device’s current location
Location Manager
 Obtain current location
 Track movement
 Set proximity alerts for areas
 Find available Location Providers
Location Providers
 Various location-finding technologies (GPS, Cellular network)
3
Global Positioning System (GPS)




--- Miami1795 km
--- Caracas 1874 km
--- Bogota 1251 km
San Jose, CR
4
Cell Tower Triangulation





An alternative method to determine the
location of a cell phone is to estimate its
distance to three nearby cell towers.
Distance of the phone to each antenna
could be estimated based upon the lag
time between the moment the tower
sends a ping to the phone and receives
the answering ping back.
Quite similar to the 2D-Trilateration
Method.
Reference:
http://searchengineland.com/cell-phonetriangulation-accuracy-is-all-over-themap-14790
5
Latitude and Longitude


Latitude in GPS-Decimal notation: +90.00000 (North) to 90.000000 (South)
Longitude GPS-Decimal notation: +180.000000 (East) to 180.000000 (West)
6
Latitude and Longitude
7
Google API Key (Google Maps v1)









To use the Google Map service an API key is needed. The API key can obtained as
follows for development/debugging application:
1) Get debug.keystore file. You can find the location to the files under “Default debug
keystore” from: Windows Preferences Android build.
2) Use keytool tool to generate Certificate fingerprint (MD5). Use following command
on command prompt

keytool -list -alias androiddebugkey -keystore <keystore_location>.keystore storepass android -keypass android
3) Go to ‘Sign Up for the Android Maps API’ page. Put your Certificate fingerprint
(MD5) And get your API key for android GMap application.
4) Replace “API_Key_String” in MapView layout item with your API key.
Add the API key obtained in main.xml as <com.google.android.maps.MapView …
android:apiKey=“key“ />
In AndroidManifest.xml add:
<uses-permission android:name=”android.permission.INTERNET”/>
<application … ><uses-library android:name=”com.google.android.maps”
/></application>
8
Google API Key (Google Maps v2)

In order to develop Google API based android applications, make sure the following
are available:

Obtain the SHA1 key:
 To obtain the SHA1 key, use C:\Program Files (x86)\Java\<jdk
folder>\bin>keytool.exe -list -alias androiddebugkey -keystore
C:\Users\mibuhari\.android\debug.keystore -storepass android -keypass
android –v
 OR You could use the Eclipse to obtain the SHA1 key. This is possible using
Window  Preferences  Android  Build

Obtain the API key:
 Register your client ID and obtain Google API key at
https://code.google.com/apis/console/
 You will need to use your gmail login
 Under services, enable Google Maps Android API v2. You could click on
Create New Android key to generate the key. You need your SHA1 key and
the package name for this. Enter the values of SHA1 key and package name,
separated with a semi-colon.
9
Google API Key (Google Maps v2)






Note the API key obtain from the previous step. Also, note its validity period.
Go to SDK Manager in Eclipse:

Select the respective Google Maps API that matches the android version and install
it; if you want to upgrade your Android API level, you need to use help  Install
New Software

Under Extras, select Google Play Services and install it
Add the Google Play Services project into your Eclipse workspace.

Click File -> Import..., select Android -> Existing Android Code into Workspace

Browse to and select <android-sdkfolder>/extras/google/google_play_services/libproject/google-play-services_lib

You don’t need to enable the option to copy the library into your workspace
To add the dependency to Google Play Services into your project

Project -> Properties -> Android -> Library, Add -> google-play-services_lib
Update MainActivity.java to extend FragmentActivity instead of Activity
Note: If there is an error with regards to a missing library, you need to right click on the
project and go to Build Path and configure Build Path. In the libraries tab, remove the
wrongly added libraries.
10
Google API Key (Google Maps v2)



Your new API key will be a 40 character string
Add the following tag into your AndroidManifest.xml just before the closing
</application> tag

<meta-data android:name="com.google.android.maps.v2.API_KEY"
android:value="your_api_key"/>
Your application now also needs the following permissions in the AndroidManifest.xml

<permission android:name="your_package_name.permission.MAPS_RECEIVE“
android:protectionLevel="signature"/>

<usespermission android:name="your_package_name.permission.MAPS_RECEIVE"/>

<uses-permission android:name="android.permission.INTERNET"/>

<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<uses-permission
android:name="com.google.android.providers.gsf.permission.READ_GSERVICE
S"/>
11
Google API Key (Google Maps v2)












Optionally you can include one or both of these permissions to enable auto-location

<uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION"/>

<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"/>
Maps v2 uses OpenGl so the following uses-feature is also required
<uses-feature android:glEsVersion="0x00020000" android:required="true"/>
The layout file is like this:
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="@+id/the_map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.google.android.gms.maps.MapFragment"
map:cameraTilt="45" map:cameraZoom="14" />
12
Issues with Google Android Maps v2







In order to run the application on an Android device, whose android version is less that
android version 12, use
<fragment … android:name="com.google.android.gms.maps.SupportMapFragment"
/>
Instead of
<fragment … android:name="com.google.android.gms.maps.MapFragment" />
Make sure Target build is Google API. You could check that on Right-click on Project
 Preferences  Android  Project Build Target
You need to check whether your project has google-play-services_lib as a library.
Doing this process includes the google-play-services_lib.jar file into Android
Dependencies for the current project. This is possible only after importing the googleplay-services_lib into Eclipse.
Possible errors and solutions:

ClassNotFoundException: This error indicates that respective class is not found in
the apk file. To solve this, you need to include the google-play-services_lib as a
library to your project.
13
Issues with Google Android Maps v2


NOTE: Google Android API codes work only on Android device and not on the
emulator. In the emulator, you get only the grids and no maps.
Possible errors and solutions:

Program opens and closes immediately:
 Happens in the emulator:
 There might be problems with the target SDK version or there is a
mistake in the manifest file
 You need to have your network connection enabled
 Happens in the device: Check the minimum and Target SDK version provided
in the Manifest file along with that of the mobile device itself. A mismatch in
this will cause the program to crash

Crashing of eclipse is possible with .metadata/.log indicating as below:
 Plug-in com.android.ide.eclipse.adt was unable to load class
com.android.ide.eclipse.adt.internal.welcome
 Go to .metadata/.plugins folder and rename
.metadata/.plugins/org.eclipse.e4.workbench to.metadata/.plugins/org.ecli
pse.e4.workbench.temp and restart eclipse
14
Issues with Google Android Maps v2





android.view.InflateException: Binary XML file line #2: Error inflating class fragment

Make sure this entry is present in layout file
android:name="com.google.android.gms.maps.SupportMapFragment“
Make sure to add the below in manifest file under <application> tag

<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />

<meta-data android:name="com.google.android.maps.v2.API_KEY“
android:value="API-key" />
Google Maps Android API v2 only supports devices with OpenGL ES 2.0 and above

This error is possible if your emulator selected does not support OpenGL ES 2.0
and also if the device does not support OpenGL ES 2.0.
Library is missing while compiling the program. Also, import
android.support.v4.app.FragmentActivity; has an error

Right click on the project and choose properties. Then in Java Build Path, add
android-support-v4.jar (ADT-Folder\sdk\extra\android\support\v4)as an external
jar
https://developers.google.com/maps/documentation/android/
15
Android Location Classes





The Android API provides Location data based on a variety
of methods including: Cell Tower Triangulation, and most
commonly GPS chip readings.
GPS is the most common location provider on the Android based
phones.
It offers the most accuracy.
Picture: Epson Infineon GPS (2.8 x 2.9mm)
Reference: http://gizmodo.com/5152146/
16
Android Location Classes
17
Location Class




A class representing a geographic location sensed at a particular time.
A location consists of a latitude and longitude, a UTC timestamp and
optionally information on altitude, speed, and bearing.
Information specific to a particular provider or class of providers may be
communicated to the application using getExtras, which returns a Bundle of
key/value pairs.
Each provider will only provide those entries for which information is
available.
18
Location Values Format

The three common formats:

There are sixty seconds in a minute (60" = 1') and
There are sixty minutes in a degree (60' = 1°).
Examples:
DDD° MM' SS.S” 32° 18' 23.1" N 122° 36' 52.5" W
DDD° MM.MMM’ 32° 18.385' N 122° 36.875' W
DDD.DDDDD° 32.30642° N 122.61458° W
or +32.30642, -122.61458





19
Location Manager






This class provides access to the system location services.
These services allow applications
1. To obtain periodic updates of the device's geographical
location,
2. or to fire an application-specified Intent when the device
enters the proximity of a given geographical location.
String service_name = Context.LOCATION_SERVICE;
LocationManager locationManager = (LocationManager)
getSystemService(service_name)
20
Location Manager’s Methods
21
LocationProvider Class





An abstract superclass for location providers.
A location provider supplies periodic reports on the geographical location of
the device.
Each provider has a set of criteria under which it may be used; for example,
 some providers require GPS hardware and visibility to a number of
satellites;
 others require the use of the cellular radio,
 or access to a specific carrier's network,
 or access to the Internet.
They may also have different battery consumption characteristics or monetary
costs to the user.
The Criteria class allows providers to be selected based on user-specified
criteria.
22
LocationProvider’s Methods
23
LocationProvider Class








Provider Reference
String providerName = LocationManager.GPS_PROVIDER;
LocationProvider gpsProvider;
gpsProvider = locationManager.getProvider(providerName);
Common Location Providers:
 LocationManager.GPS_PROVIDER
 LocationManager.NETWORK_PROVIDER
Getting list of all providers
boolean enabledOnly = true;
List<String> providers =
locationManager.getProviders(enabledOnly);
24
Finding Location Providers using Criteria











Provider with specific requirements
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_COARSE);
criteria.setPowerRequirement(Criteria.POWER_LOW);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setSpeedRequired(false);
criteria.setCostAllowed(true);
String bestProvider = locationManager.getBestProvider(criteria, true);
To get all matching Providers
List<String> matchingProviders = locationManager.getProviders(criteria,
false);
25
LocationListener Class


Used for receiving notifications from the LocationManager
when the location has changed.
These methods are called if the LocationListener has been
registered with the location manager service using the method:
 requestLocationUpdates (Provider, minTime,
minDistance, LocationListener)
26
LocationListener’s Methods
27
LocationListener


















String provider = LocationManager.GPS_PROVIDER;
int t = 5000; // milliseconds
int distance = 5; // meters
LocationListener myLocationListener = new LocationListener() {
public void onLocationChanged(Location location) {
// Update application based on new location.
}
public void onProviderDisabled(String provider){
// Update application if provider disabled.
}
public void onProviderEnabled(String provider){
// Update application if provider enabled.
}
public void onStatusChanged(String provider, int status, Bundle extras){
// Update application if provider hardware status changed.
}
};
locationManager.requestLocationUpdates(provider, t, distance, myLocationListener);
28
Finding your location









Reference Location Manager
String service_name = Context.LOCATION_SERVICE;
LocationManager locationManager = (LocationManager)
getSystemService(service_name)
Permissions in Manifest
<uses-permission android:name =
"android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name =
"android.permission.ACCESS_COARSE_LOCATION" />
Last location “fix”
String provider = LocationManager.GPS_PROVIDER;
Location location = locationManager.getLastKnownLocation(provider);
29
Example – Obtain Location from GPS


In this example we request GPS services and display latitude and
longitude values on the UI.
Notes
 1. Observe the GPS chip is not a synchronous device that will
immediately respond to a “give me a GPS reading” call.
 2. In order to engineer a good solution that takes into account
the potential delays in obtaining location data we place the UI
in the main activity and the request for location call in a
background service.
 3. Remember the service runs in the same process space as the
main activity, therefore for the sake of responsiveness we
must place the logic for location data request in a separate
parallel thread.
30
Example – Obtain Location from GPS
31
Geocoding








Geocoding lets you translate between street addresses and longitude/latitude
map coordinates.
The geocoding lookups are done on the server, so your applications will
require you to include an Internet uses-permission in your manifest, as shown
here:
<uses-permission android:name ="android.permission.INTERNET"/>
The Geocoder class provides access to two geocoding functions:
 Forward geocoding: Finds the latitude and longitude of an address
 Reverse geocoding: Finds the street address for a given latitude and
longitude
The Geocoder object converts the latitude and longitude into an address using
the getFromLocation() method
For more details:
http://developer.android.com/reference/android/location/Geocoder.html
http://developer.android.com/reference/android/location/Address.html
32
Reverse Geocoding












Geocoder gc= new Geocoder(context, Locale.US);
List<Address> streets = gc.getFromLocation(latitude, longitude, 1);
// search based on address
// List<Address> addresses = geoCoder.getFromLocationName(“empire state
building”, 5); if (addresses.size() > 0) { p = new GeoPoint((int)
(addresses.get(0).getLatitude() * 1E6), (int) (addresses.get(0).getLongitude() * 1E6));
location = locationManager.getLastKnownLocation
(LocationManager.GPS_PROVIDER);
double latitude = location.getLatitude();
double longitude = location.getLongitude();
List<Address> addresses = null;
Geocoder gc = new Geocoder(this, Locale.getDefault());
try {
addresses = gc.getFromLocation(latitude, longitude, 10);
} catch (IOException e) {}
33
Forward Geocoding









Geocoder gc= new Geocoder(this);
// get decimal coordinates for up to 5 (best) matching
locations
List<Address> lstFoundAddresses=
gc.getFromLocationName (txtStreetAddress, 5);
Geocoder fwdGeocoder = new Geocoder(this, Locale.US);
String streetAddress = "160 Riverside Drive, New York,
New York";
List<Address> locations = null;
try {
locations =
fwdGeocoder.getFromLocationName(streetAddress, 10);
} catch (IOException e) {}
34
Emulating GPS Location


Use Eclipse’s DDMS > Emulator Control
Keyhole Markup Language
35
Google Maps External Library (Google Maps v1)




Android uses the Google Maps External Library to
add mapping capabilities to your applications.
Google Maps External Library includes the
com.google.android.maps package. The classes of
this package offer built-in downloading, rendering,
and caching of Maps tiles, as well as a variety of
display options and controls.
The key class in the Maps package is
com.google.android.maps.MapView, a subclass of
ViewGroup.
The MapView provides an ideal user interface Road
View option for presenting geographical data.
Road View
36
Map Views (Google Maps v1)




MapViews support annotation using Overlays and by
pinning Views to geographical locations.
The Maps external library is not part of the standard
Android library, so it may not be present on some
compliant Android-powered devices.
By default the Android SDK includes the Google APIs
add-on , which in turn includes the Maps external
library.
MapViews offer full programmatic control of the map
display, letting you control the zoom, location, and
display modes — including the option to display
satellite, street, and traffic views.
Aerial View
37
Google Map Classes (Google Maps v1)






MapView is the Map View control.
MapActivity is the base class you extend to create a new Activity that can
include a Map View. MapActivity handles the application life cycle and
background service management required for displaying maps. Map Views are
used only within MapActivity-derived Activities.
MapController is used to control the map, enabling you to set the center
location and zoom levels.
Overlay is the class used to annotate your maps.
MyLocationOverlay is a special Overlay that can be used to display the
current position and orientation of the device.
ItemizedOverlays and OverlayItems are used together to let you create a
layer of map markers, displayed using Drawables and associated text.
38
Creating a Map-Based Activity (Google Maps v1)
Manifest XML
<uses-library android:name = "com.google.android.maps" />
<uses-permission android:name = "android.permission.INTERNET" />

Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.google.android.maps.MapView
android:id="@+id/map_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:enabled="true"
android:clickable="true" android:apiKey="mymapapikey" />
</LinearLayout>

39
MapActivity (Google Maps v1)

















import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import android.os.Bundle;
public class MyMapActivity extends MapActivity {
private MapView mapView;
private MapController mapController;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.map_layout);
mapView = (MapView)findViewById(R.id.map_view);
}
@Override
protected boolean isRouteDisplayed() {
// IMPORTANT: This method must return true if your Activity
// is displaying driving directions. Otherwise return false.
return false ;
} }
40
Configuring and Using Map Views (Google Maps v1)





Specifying how the map is displayed.

mapView.setSatellite(true); // satellite view

mapView.setStreetView(true);

mapView.setTraffic(true); // show traffic conditions on the map
Querying the Map View.

int maxZoom = mapView.getMaxZoomLevel();

GeoPoint center = mapView.getMapCenter();

int latSpan = mapView.getLatitudeSpan();

int longSpan = mapView.getLongitudeSpan();
Optionally display the standard map zoom controls

mapView.setBuiltInZoomControls(true);
Reference:
http://code.google.com/android/add-ons/googleapis/reference/com/google/android/maps/MapView.html
41
Using the Map Controller





Use the Map Controller to pan and zoom a MapView.
 getController get a reference to a MapView’s controller.
 MapController mapController = mapView.getController();
Map locations are represented by GeoPoint objects.
 Double lat = 37.422006*1E6; // multiply by 1e6, which is one million
 Double lng = -122.084095*1E6;
 GeoPoint point = new GeoPoint(lat.intValue(), lng.intValue());
Re-center and zoom the Map.
 mapController.setCenter(point);
 mapController.setZoom(1); // 1=widest (or most distant), 21=tightest
(nearest) view
‘‘jump’’ to a new location
 mapController.animateTo(point);
To redraw a map: mapView.invalidate();
42
Creating and Using Overlays







Overlays enable you to add annotations and click handling to MapViews.
Each Overlay lets you draw 2D primitives, including text, lines, images, etc.
All the Overlays assigned to a Map View are added as layers, with newer
layers potentially obscuring older ones.
User clicks are passed through the stack until they are either handled by an
Overlay or registered as clicks on the Map View itself
To add an overlay to a map that will handle tapping events, you can use
onTouchEvent() method within the MapOverlay class. The method has two
parameters: MotionEvent and MapView. Using the MotionEvent parameter,
you can determine whether the user has lifted his or her finger from the screen
using the getAction() method
Reference:
http://code.google.com/android/add-ons/googleapis/reference/com/google/android/maps/Overlay.html
43
Creating New Overlays
















To add a new Overlay create a new class that extends Overlay .
Override the draw method to draw the annotations you want to add, and override
onTap to react to user clicks
import android.graphics.Canvas;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
public class MyOverlay extends Overlay {
@Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
if (shadow == false ) { //[ . . . Draw annotations on main map layer . . . ]
}
else { //[ . . . Draw annotations on the shadow layer . . . ]
} }
@Override
public boolean onTap(GeoPoint point, MapView mapView) {
// Return true if screen tap is handled by this overlay
return false ; } }
44
Projections









The Projection class lets you translate between latitude/longitude coordinates
(stored as GeoPoints) and x/y screen pixel coordinates (stored as Points).
A map’s Projection may change between subsequent calls to draw, so it’s good
practice to get a new instance each time.
 Projection projection = mapView.getProjection();
Use the fromPixel and toPixel methods to translate from GeoPoints to Points
and vice versa.
Point myPoint = new Point();
// To screen coordinates
projection.toPixels(geoPoint, myPoint);
// To GeoPoint location coordinates
projection.fromPixels(myPoint.x, myPoint.y);
To put a marker (pushpin image) on a specific location:
 Bitmap bmp = BitmapFactory.decodeResource(getResources(),
R.drawable.pushpin);
45
 canvas.drawBitmap(bmp, screenPts.x, screenPts.y-50, null);
Drawing on the Overlay Canvas


















// draw on the map
@Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
Projection projection = mapView.getProjection();
Double lat = -31.960906*1E6;
Double lng = 115.844822*1E6;
GeoPoint geoPoint = new GeoPoint(lat.intValue(), lng.intValue());
if (shadow == false ) {
Point myPoint = new Point(); projection.toPixels(geoPoint, myPoint);
// Create and setup your paint brush
Paint paint = new Paint(); paint.setARGB(250, 255, 0, 0);
paint.setAntiAlias(true); paint.setFakeBoldText(true);
// Create the circle
int rad = 5; RectF oval = new RectF(myPoint.x-rad, myPoint.y-rad, myPoint.x+rad,
myPoint.y+rad);
// Draw on the canvas
canvas.drawOval(oval, paint);
canvas.drawText("Red Circle", myPoint.x+rad, myPoint.y, paint);
} }
46
Handling Map Tap Events













The onTap handler receives two parameters:
A GeoPoint that contains the latitude/longitude of the map location tapped
The MapView that was tapped to trigger this event
@Override
public boolean onTap(GeoPoint point, MapView mapView) {
// Perform hit test to see if this overlay is handling the click
if ([ . . . perform hit test . . . ]) {
//[ . . . execute on tap functionality . . . ]
return true ;
}
// If not handled return false
return false ;
}
47
Adding and Removing Overlays








Each MapView contains a list of Overlays currently displayed.
 List<Overlay> overlays = mapView.getOverlays();
To add an Overlay onto a Map View, create a new instance of the
Overlay and add it to the list
Good practice to call postInvalidate after you modify the list to
update the changes on the map display
List<Overlay> overlays = mapView.getOverlays();
MyOverlay myOverlay = new MyOverlay();
overlays.add(myOverlay);
mapView.postInvalidate();
projection.fromPixels(myPoint.x, myPoint.y);
48
My Location Overlay





Special Overlay designed to show your current location and orientation on a
MapView.
 List<Overlay> overlays = mapView.getOverlays();
 MyLocationOverlay myLocationOverlay = new MyLocationOverlay(this,
mapView);
 overlays.add(myLocationOverlay);
Can display both your current location (represented as a flashing blue marker)
and your current orientation (shown as a compass on the map display).
 myLocationOverlay.enableCompass();
 myLocationOverlay.enableMyLocation();
Stopping the service
 myLocationOverlay.disableCompass();
 myLocationOverlay.disableMyLocation();
Reference:
http://code.google.com/android/add-ons/google49
apis/reference/com/google/android/maps/MyLocationOverlay.html
Additional Features


Itemized Overlays and Overlay Items Classes

OverlayItems are used to supply simple maker functionality to your Map Views via
the ItemizedOverlay class

The ItemizedOverlay instance handles the drawing, placement, click handling,
focus control, and layout optimization of each OverlayItem marker for you

Extends ItemizedOverlay<OverlayItem> , override size() to return the number
of markers to display and createItem() to create a new item based on the index of
each marker
Pinning Views to the Map and Map Positions

You can pin any View-derived object to a Map View attaching it to either a screen
position or a geographical map location

Call addView() on the MapView, usually from the onCreate or onRestore
methods within the MapActivity containing it. Pass in the View you want to pin
and the layout parameters to use

The MapView.LayoutParams parameters you pass in to addView determine
how, and where, the View is added to the map
50
LocationManager









In Android, location-based services are provided by the LocationManager class, located
in the android.location package. Using the LocationManager class, your application can
obtain periodic updates of the device’s geographical locations, as well as fire an intent
when it enters the proximity of a certain location
//---use the LocationManager class to obtain locations data--lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationListener = new MyLocationListener();
Using LocationListener abstract class, we need to override four methods in this
implementation:
onLocationChanged(Location location) — Called when the location has changed
onProviderDisabled(String provider) — Called when the provider is disabled by the
user
onProviderEnabled(String provider) — Called when the provider is enabled by the user
onStatusChanged(String provider, int status, Bundle extras) — Called when the
provider status changes
51
LocationManager



To be notified whenever there is a change in location, you needed to register a request
for location changes so that your program can be notified periodically. This is done via
the requestLocationUpdates() method
The requestLocationUpdates() method takes four arguments:

provider — The name of the provider with which you register. In this case, you are
using GPS to obtain your geographical location data

minTime — The minimum time interval for notifications, in milliseconds. 0
indicates that you want to be continually informed of location changes.

minDistance — The minimum distance interval for notifications, in meters. 0
indicates that you want to be continually informed of location changes.

listener — An object whose onLocationChanged() method will be called for each
location update
To use the network provider, you need to add the ACCESS_COARSE_LOCATION
permission to the AndroidManifest.xml

Note: This will only work on real device and not on the emulator
52
LocationManager












//---request for location updates--- for Network and GPS
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0,
locationListener); lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
0, locationListener);
//---called when the provider is disabled--public void onProviderDisabled(String provider) { … }
//---called when the provider is enabled--public void onProviderEnabled(String provider) { … }
//---called when there is a change in the provider status--public void onStatusChanged(String provider, int status, Bundle extras) { … }
// monitoring the location
//---PendingIntent to launch activity if the user is within some locations--PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new
Intent(android.content.Intent.ACTION_VIEW, Uri.parse(“http://www.amazon.com”)),
0); lm.addProximityAlert(37.422006, -122.084095, 5, -1, pendingIntent);
The addProximityAlert() method takes five arguments: latitude, longitude, radius (in
meters), expiration (duration for which the proximity alert is valid, after which it is
53
deleted; -1 for no expiration), and the pending intent
Additional Features






In AndroidManifest.xml add the following within <application> tag to wake
up an application upon receipt of an SMS
<receiver android:name=”.SMSReceiver”>
<intent-filter android:priority=”100”>
<action android:name=”android.provider.Telephony.SMS_RECEIVED” />
</intent-filter> </receiver>
List of Intents to invoking Google applications on Android
devices
http://developer.android.com/guide/appendix/g-app-intents.html
54
Location – Summary




Permissions in the Manifest

Internet (if want Network-based location)
 <uses-permission android:name=“android.permission.INTERNET” />

Fine Location – NETWORK_PROVIDER, GPS_PROVIDER
 <uses-permission
android:name=“android.permission.ACCESS_FINE_LOCATION” />

Coarse Location – only NETWORK_PROVIDER
 <uses-permission
android:name=“android.permission.ACCESS_COARSE_LOCATION” />
LocationManager

getSystemService(Context.LOCATION_SERVICE)
LocationProvider

locationManager.getProvider(LocationManager.GPS_PROVIDER)
Make sure LocationProvider enabled

locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
55
Location – Summary

Getting the Last Known Location


Reverse Geocode the Location




Instantiate a new Geocoder object
Geocoder geocoder = new Geocoder(context, locale)


locationManager.getLastKnownLocation(locationProvider)
Most likely to be Locale.ENGLISH
Get location from Geocoder object
List<Address> addresses =
geocoder.getFromLocation(lastKnownLocation.getLatit
ude(), lastKnownLocation.getLongitude(), maxResults)
First one is usually accurate enough for usage
56
Example 1 – Obtain Location from GPS














<?xml version= "1.0" encoding="utf-8"?>
<LinearLayout android:id= "@+id/widget32"
android:layout_width= "fill_parent"
android:layout_height= "fill_parent"
android:orientation= "vertical"
xmlns:android= "http://schemas.android.com/apk/res/android" >
<EditText
android:id= "@+id/txtMsg" android:layout_width= "fill_parent"
android:layout_height= "120px" android:textSize= "12sp" >
</EditText>
<Button android:id= "@+id/btnStopService" android:layout_width= "151px"
android:layout_height= "wrap_content" android:text= "Stop Service" >
</Button>
</LinearLayout>
57
Example 1 – Obtain Location from GPS















Manifest
<?xml version ="1.0" encoding = "utf-8"?>
<manifest xmlns:android = "http://schemas.android.com/apk/res/android"
package = "edu.odu.cs.cs495.mappinggps" android:versionCode = "1"
android:versionName = "1.0" >
<application android:icon = "@drawable/icon"
android:label = "@string/app_name" android:debuggable = "true" >
<activity android:name = ".MyGPS" android:label = "@string/app_name" >
<intent-filter> <action android:name = "android.intent.action.MAIN" />
<category android:name = "android.intent.category.LAUNCHER" />
</intent-filter>
</activity> <service android:name = "MyGpsService"> </service>
</application> <uses-sdk android:minSdkVersion =“8" />
<uses-permission android:name =
"android.permission.ACCESS_FINE_LOCATION" />
</manifest>
58
Example 1 – Obtain Location from GPS
















Main Activity: MyGPS
// Request GPS location, show lat & long
// Application logic and its BroadcastReceiver in the same class
package edu.odu.cs.495.mappinggps;
import android.app.Activity;
import android.os.Bundle;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.telephony.gsm.SmsManager;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.*;
59
Example 1 – Obtain Location from GPS








Main Activity: MyGPS
public class MyGPS extends Activity {
Buttonbtn StopService;
TextView txtMsg;
Intent intentMyService;
ComponentName service;
BroadcastReceiver receiver;
String GPS_FILTER= "cs495.action.GPS_LOCATION";
60
Example 1 – Obtain Location from GPS














Main Activity: MyGPS
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txtMsg = (TextView) findViewById(R.id.txtMsg);
// initiate the service
intentMyService = new Intent(this, MyGpsService.class);
service = startService(intentMyService);
txtMsg.setText("MyGpsServicestarted-(see DDMS Log)");
// register & define filter for local listener
IntentFilter mainFilter = new IntentFilter(GPS_FILTER);
receiver = new MyMainLocalReceiver();
registerReceiver(receiver, mainFilter);
61
Example 1 – Obtain Location from GPS















Main Activity: MyGPS
btnStopService= (Button) findViewById(R.id.btnStopService);
btnStopService.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
try{
stopService(new Intent(intentMyService) );
txtMsg.setText("After stopingService: \n" + service.getClassName());
btnStopService.setText("Finished");
btnStopService.setClickable(false);
} catch (Exception e) {
Log.e("MYGPS" , e.getMessage());
}
}
});
} //onCreate
62
Example 1 – Obtain Location from GPS













Main Activity: MyGPS
//////////////////////////////////////////////////////////////////////
@Override
public void onDestroy() {
super.onDestroy();
try {
stopService(intentMyService);
unregisterReceiver(receiver);
} catch (Exception e) {
Log.e("MAIN-DESTROY>>>", e.getMessage());
}
Log.e("MAIN-DESTROY>>>", "Adios");
} // onDestroy
63
Example 1 – Obtain Location from GPS














Main Activity: MyGPS
// local RECEIVER
private class MyMainLocalReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context localContext, Intent callerIntent) {
double latitude = callerIntent.getDoubleExtra("latitude" ,-1);
double longitude = callerIntent.getDoubleExtra("longitude" ,-1);
Log.e("MAIN>>>" , Double.toString(latitude));
Log.e("MAIN>>>" , Double.toString(longitude));
String msg = " lat: " + Double. toString(latitude) + " " + " lon: " +
Double.toString(longitude);
txtMsg.append("\n" + msg); Toast.makeText(this, msg, 1000).show();
}
} //MyMainLocalReceiver
} //MyGPS
64
Example 1 – Obtain Location from GPS
















Main Activity: MyGpsService
// This is the GPS service. Requests location updates
// in a parallel thread. sends broadcast using filter.
package edu.odu.cs.cs495.mappinggps;
import android.app.Service; import android.content.Context;
import android.content.Intent; import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle; import android.os.IBinder;
import android.os.Looper; import android.util.Log;
import android.widget.Toast;
public class MyGpsService extends Service {
String GPS_FILTER= "cs495.action.GPS_LOCATION" ;
Thread triggerService; LocationManager lm;
GPSListener myLocationListener;
boolean isRunning = true ;
65
Example 1 – Obtain Location from GPS














Main Activity: MyGpsService
@Override
public Ibinder onBind(Intent arg0) {
return null ;
}
@Override
public void onCreate() { super .onCreate(); }
@Override
public void onStart(Intent intent, int startId) {
super .onStart(intent, startId);
Log. e("<<MyGpsService-onStart>>" , "I am alive-GPS!");
// we place the slow work of the service in its own thread so the
// response we send our caller who run a "startService(...)" method
// gets a quick OK from us.
66
Example 1 – Obtain Location from GPS
















Main Activity: MyGpsService
triggerService = new Thread(newRunnable() {
public void run() {
try{ Looper.prepare();
// try to get your GPS location using the LOCATION.SERVIVE provider
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// This listener will catch and disseminate location updates
myLocationListener = new GPSListener();
long minTime = 10000; // frequency update: 10 seconds
float minDistance = 50; // frequency update: 50 meter
lm.requestLocationUpdates( //request GPS updates
LocationManager.GPS_PROVIDER, minTime, minDistance, myLocationListener);
Looper.loop(); } catch ( Exception e) {
Log.e("MYGPS", e.getMessage() ); }
} // run
}); triggerService.start(); } // onStart
67
Example 1 – Obtain Location from GPS















Main Activity: MyGpsService
// location listener becomes aware of the GPS data and sends a broadcast
private class GPSListener implements LocationListener{
public void onLocationChanged(Location location) {
//capture location data sent by current provider
double latitude = location.getLatitude();
double longitude = location.getLongitude();
//assemble data bundle to be broadcasted
Intent myFilteredResponse = new Intent(GPS_FILTER);
myFilteredResponse.putExtra("latitude", latitude);
myFilteredResponse.putExtra("longitude", longitude);
Log.e(">>GPS_Service<<" , "Lat:" + latitude + " lon:" + longitude);
//send the location data out
sendBroadcast(myFilteredResponse);
}
68
Example 1 – Obtain Location from GPS









Main Activity: MyGpsService
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status,
Bundle extras) {
}
}; //GPSListener class
} // MyGPSService
69
Example 2 – Hello, Map View



Create a simple Activity that can view and navigate a map.
Reference:
http://developer.android.com/guide/tutorials/views/hellomapview.html
70
Example 2 – Hello, Map View



1. Start a new project/Activity called HelloMapView.
2. Because we're using the Google Maps library, which is not a
part of the standard Android library, we need to declare it in the
Android Manifest. Open the AndroidManifest.xml file and add
the following as a child of the <application> element:
 <uses-library android:name="com.google.android.maps" />
3. We also need access to the Internet in order to retrieve the
Google Maps tiles, so the application must request the
INTERNET permissions. In the manifest file, add the following
as a child of the <manifest> element:
 <uses-permission
android:name="android.permission.INTERNET" />
71
Example 2 – Hello, Map View











4. Now open the main layout file for your project. Define a layout with a
com.google.android.maps.MapView inside a RelativeLayout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/
apk/res/android" android:id="@+id/mainlayout"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.google.android.maps.MapView
android:id="@+id/mapview" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:clickable="true"
android:apiKey = "Your Maps API Key " />
</RelativeLayout>
72
Example 2 – Hello, Map View





4. cont.
The clickable attribute defines whether you want to allow userinteraction with the map. In this case, we set it "true" so that the
user can navigate.
The apiKey attribute holds the Google Maps API Key that
proves your application and signer certificate has been registered
with the Google Maps service.
Because MapView uses Google Maps data, this key is required in
order to receive the map data, even while you are
For the purpose of this tutorial, you should register with the
fingerprint of the SDK debug certificate. Once you've acquired
the Maps API Key, insert it for the apiKey value.
73
Example 2 – Hello, Map View



5. Now open the HelloMapView.java file. For this Activity, we're going to
extend the special sub-class of Activity called MapActivity, so change the
class declaration to extend MapActicity, instead of Activity:
 public class HelloMapView extends MapActivity {
6. The isRouteDisplayed() method is required, so add it inside the class:
 @Override
 protected boolean isRouteDisplayed() {

return false;

}
7. Now go back to the HelloMapView class. At the top of HelloMapView,
instantiate a handles for the MapView and the Map controller.

MapView mapView;

MapController controller;
74
Example 2 – Hello, Map View












8. Wire-up the XML layout widget and the Java controls.
public void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MapView mapView;
mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
GeoPoint point = new GeoPoint (25800000,-80266667); // Miami City
controller = map.getController();
controller.animateTo(point);
controller.setZoom(3);
}
75
Example 2 – Hello, Map View




9. In the previous fragment the mapView is activated by the use
of the built-in zoom facility (new feature). This zoom control will
appear at the center-bottom of the screen each time the user taps
on the screen, and will disappear a few seconds later.
10. The MapController method .animateTo(geoPoint) center the
map on the given coordinates.
11. The zoom factor range is 1..17 (17 closest to the map).
12. Ready to run.
76
Example 2 – Hello, Map View
Initial Map
After tapping
and zooming in
After panning to
go south
77
Example 3 - GeoCoder



In this example we will create an application
that converts an address to its corresponding
GeoPoint and displays the location on a
Mapview.
In the case of multiple possible locations a list
of addresses is provided
(TODO: show the list in a dialog box or list
selector and allow the user to make her
selection by clicking on the best choice. As an
example try: “Main Ave. Ohio”)
78
Example 3 – GeoCoder Layout




















<?xml version= "1.0" encoding="utf-8"?>
<LinearLayout android:layout_width= "fill_parent"
android:layout_height= "fill_parent" android:orientation= "vertical"
xmlns:android= "http://schemas.android.com/apk/res/android" >
<TextView android:id= "@+id/myCaption"
android:layout_width= "wrap_content" android:layout_height= "wrap_content"
android:text= "Address/Coordinates" />
<LinearLayout android:layout_width= "fill_parent" android:layout_height= "wrap_content"
android:orientation= "horizontal" >
<EditText android:id= "@+id/myAddress" android:layout_width= "wrap_content"
android:layout_height= "wrap_content" android:layout_weight= "2"
android:hint= "Enter location (address)" android:textSize= "18sp" />
<Button android:id= "@+id/myBtnSearch" android:layout_width= "wrap_content"
android:layout_height= "wrap_content" android:padding= "10px"
android:text= "Go" />
</LinearLayout>
<com.google.android.maps.MapView android:id= "@+id/myMap"
android:apiKey= "0SN3rTw6p317v08_uva72oCS_hgPTe92J2t_nwQ"
android:layout_width= "fill_parent" android:layout_height= "wrap_content"
android:layout_weight= "2" android:clickable= "true" /> </LinearLayout>
79
Example 3 – GeoCoder Manifest















<? xml version = "1.0" encoding = "utf-8" ?>
< manifest xmlns:android = "http://schemas.android.com/apk/res/android"
package = “edu.odu.cs.cs495.geocoder" android:versionCode = "1"
android:versionName = "1.0" >
<!-- Permissions -->
< uses-permission android:name = "android.permission.ACCESS_COARSE_LOCATION" />
< uses-permission android:name = "android.permission.INTERNET" />
< uses-sdk android:minSdkVersion = “8" />
< application android:icon = "@drawable/icon" android:label = "@string/app_name" >
< uses-library android:name = "com.google.android.maps" />
< activity android:name = ".GeopointDemo1" android:label = ".GeopointDemo1" >
< intent-filter >
< action android:name = "android.intent.action.MAIN" />
< category android:name = "android.intent.category.LAUNCHER" />
</ intent-filter > </ activity > </ application > </ manifest >
80
Example 3 – GeoCoder















// GeopointDemo1
// Enter address get location choices from a list
// show MapView location from last list entry
package edu.odu.cs.cs495.geocoder;
import java.util.List;
import android.app.AlertDialog; import android.app.Dialog;
import android.location.Address; import android.location.Geocoder;
import android.os.Bundle; import android.util.Log;
import android.view.View; import android.view.View.OnClickListener;
import android.widget.Button; import android.widget.EditText;
import android.widget.Toast;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
81
Example 3 – GeoCoder















public class GeopointDemo1 extends MapActivity {
private MapView myMap ; private Button btnSearch ;
private EditText address ; private Geocoder gc ;
private double lat ; private double lon ;
protected boolean isRouteDisplayed() { return false ; }
@Override
public void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.main);
Toast. makeText(this , "Try: MAIN AVE OHIO" , 1).show();
//define handle to map and attach zooming[+ -] capabilities
myMap = (MapView) findViewById(R.id.myMap);
myMap.setBuiltInZoomControls(true);
gc = new Geocoder(this);
address = (EditText) findViewById(R.id.myAddress);
82
Example 3 – GeoCoder
















btnSearch = (Button) findViewById(R.id.myBtnSearch);
btnSearch .setOnClickListener( new OnClickListener() {
public void onClick(View v) {
String addressInput = address .getText().toString(); // Get input text
try { // get up to 5 locations
List<Address> lstFoundAddresses = gc.getFromLocationName(addressInput, 5);
if (lstFoundAddresses.size() == 0) showInvalidAddressMsg();
else {
showListOfFoundAddresses(lstFoundAddresses);
//for now map the first address from the list
navigateToLocation(lstFoundAddresses.get(0), myMap );
}
} catch (Exception e) { Toast. makeText(getBaseContext(), e.getMessage(), 1).show(); }
} // onClick
}); // btnSearch
}// onCreate
83
Example 3 – GeoCoder


















// Navigates a given MapView to the specified Longitude and Latitude
public static void navigateToLocation(Address adr, MapView map) {
try {
//covert to integer representation of microdegrees
double latitude = adr.getLatitude()*1000000;
double longitude = adr.getLongitude()*1000000;
// new GeoPoint to be placed on the MapView
GeoPoint geoPt = new GeoPoint((int) latitude, (int) longitude);
MapController mapCtrl = map.getController();
mapCtrl.animateTo(geoPt); // move map to the given point
int maxZoomlevel = map.getMaxZoomLevel(); // detect maximum zoom level
int zoomapCtrlhosenLevel = (int) ((maxZoomlevel + 1)/1.25);
mapCtrl.setZoom(zoomapCtrlhosenLevel); // zoom at chosen level
mapCtrl.setCenter(geoPt); //center the map around the given address
map.setSatellite(false); // display only "normal road" mapview
map.setTraffic(false); // do not show traffic info
} catch (Exception e) { Log.e( "ERROR>>>" , e.getMessage() ); }
} // navigateTo
84
Example 3 - GeoCoder


















private void showInvalidAddressMsg() {
Dialog locationError = new AlertDialog.Builder(GeopointDemo1. this)
.setIcon(0)
.setTitle("Error")
.setPositiveButton("OK" , null )
.setMessage("Sorry, your address doesn't exist.")
.create(); locationError.show();
} // showInvalidAddressMsg
private void showListOfFoundAddresses (List<Address> foundAddresses){
String msg = "" ; for ( int i = 0; i < foundAddresses.size(); ++i) {
// show results as address, Longitude and Latitude
// TODO : for multiple results show a select-list, try : MAIN AVE OHIO
Address a = foundAddresses.get(i); lat = a.getLatitude(); lon = a.getLongitude();
String adr = "\n" + a.getAddressLine(0) + "\n" + a.getAddressLine(1);
msg += "\n" + i + " " + lat + " " + lon + adr;
Toast. makeText (getApplicationContext(), msg, 1).show();
} } // showListOfFoundAddresses
} //class
85
Example 3 - GeoCoder
86
Example 4 - Overlays


In this example we map downtown Cleveland placing markers on
important places around the city’s downtown and the Euclid
Corridor.
When the user taps on a marker a brief note with the name and
description of the site appears, a long tap produces an invitation
for a virtual tour of the site (to be done!)
87
Example 4 - Overlays





<? xml version = "1.0" encoding = "utf-8" ?>
< RelativeLayout
xmlns:android = "http://schemas.android.com/apk/res/android"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent" >







< com.google.android.maps.MapView
android:id = "@+id/map"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
android:apiKey = "myapikey"
android:clickable = "true" />


</ RelativeLayout >
88
Example 4 - Overlays















<? xml version = "1.0" encoding = "utf-8" ?>
<manifest xmlns:android = "http://schemas.android.com/apk/res/android"
package = “edu.odu.cs.cs495.overlays"
android:versionCode = "1"
android:versionName = "1.0" >
<!-- Permissions -->
<uses-permission android:name = "android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name = "android.permission.INTERNET" />
<uses-sdk android:minSdkVersion = “8" />
<application android:icon = "@drawable/icon" android:label = "@string/app_name" >
<uses-library android:name = "com.google.android.maps" />
<activity android:name = "ClevelandOverlays" android:label = "Cleveland Overlays" >
<intent-filter>
<action android:name = "android.intent.action.MAIN" />
<category android:name = "android.intent.category.LAUNCHER" />
</intent-filter> </activity> </application> </manifest>
89
Example 4 - Overlays


















package edu.odu.cs.cs495.overlays;
// Mapping CLEVELAND DOWNTOWN - OHIO
// demonstrates SHORT & LONG TAP events
import android.content.res.Resources.NotFoundException;
import android.graphics.drawable.Drawable;
import android.graphics.Canvas; import android.os.Bundle;
import android.view.KeyEvent; import android.view.MotionEvent;
import android.widget.Toast; import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;
import java.util.ArrayList; import java.util.List;
public class ClevelandRocks extends MapActivity {
// handle to the MapView
private MapView map = null ;
//next two variables are part of a test for longPress event
private long lastTouchTimeDown = -1; private long lastTouchTimeUp = -1;
90
Example 4 - Overlays

















@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
map = (MapView)findViewById(R.id.map);
// place Terminal Tower at the Center of the map
map.getController().setCenter(getPoint(41.498370, -81.693883));
map.getController().setZoom(14); // range 1..21
map.setBuiltInZoomControls(true);
Drawable marker = getResources().getDrawable(R.drawable.marker); //see note below
marker.setBounds(0, 0, marker.getIntrinsicWidth(), marker.getIntrinsicHeight());
map.getOverlays().add(new SitesOverlay(marker)); map.setSatellite(false);
} catch (NotFoundException e) {
Toast.makeText(getApplicationContext(), e.getMessage(), 1).show();
}
} // onCreate
Note. You may pick any drawable marker from your SDK folder, say
C:\Android\platforms\android-1.6\data\res\drawable
91
Example 4 - Overlays












@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_S) {
map.setSatellite(!map.isSatellite()); return(true);
}
return(super.onKeyDown(keyCode, event));
}
private GeoPoint getPoint(double lat, double lon) {
return(new GeoPoint((int)(lat*1000000.0), (int)(lon*1000000.0)));
}
@Override
protected boolean isRouteDisplayed() { return (false); }

92
Example 4 - Overlays
















private class SitesOverlay extends ItemizedOverlay<OverlayItem> {
private List<OverlayItem> items = new ArrayList<OverlayItem>();
private Drawable marker = null ;
public SitesOverlay(Drawable marker) { super (marker); this.marker = marker;
items.add(new OverlayItem(getPoint(41.498370,-81.693883), "Terminal Tower", "AT the heart of the city" ));
items.add(new OverlayItem(getPoint(41.506052,-81.699560), "Cleveland Browns Stadium", "Football legends since 1946" ));
items.add(new OverlayItem(getPoint(41.496550,-81.688198), "Quicken Loans Arena", "Home of the Cleveland Cavaliers" ));
items.add (new OverlayItem(getPoint(41.495749,-81.685333), "Progressive Field", "Cleveland Indians Home\nMajor League
Baseball since 1900's" ));
items.add(new OverlayItem(getPoint(41.501719,-81.675140), "Cleveland State University", "The People's University \nEngaged
Learning" ));
items.add(new OverlayItem(getPoint(41.502088,-81.623003), "Cleveland Clinic", "Top Hospital & Medical Research in the
USA"));
items.add(new OverlayItem(getPoint(41.506106,-81.609615), "Severance Hall", "Cleveland Orchestra - Best in the World"));
items.add(new OverlayItem(getPoint(41.504223,-81.608512), "Case Western Reserve University", "One of the Nation's Top
Universities"));
items.add(new OverlayItem(getPoint(41.508968,-81.611754), "Cleveland Museum of Art", "Most Distinguished \nOpen Museum
in the World"));
items.add(new OverlayItem(getPoint(41.508421,-81.695540), "Rock & Roll Hall of Fame", "Preserving for the world \nthe
history of RR music"));
populate();
}
93
Example 4 - Overlays

















@Override
protected OverlayItem createItem(int i) { return(items.get(i)); }
@Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
super.draw(canvas, mapView, shadow); boundCenterBottom(marker); }
@Override
protected boolean onTap(int i) {
// if time Difference between lastTouchTimeUp & lastTouchTimeDown is:
// > 1500 millisec. it was a LONG TAP
// < 1500 just a NORMAL tap
// on LONG TAPs we may want to show a dialog box with additional
// data about item i-th such as pictures, links to web-sites, ???, etc.
String text = "NORMAL TAP" ;
long pressTotalTime = lastTouchTimeUp - lastTouchTimeDown;
if (pressTotalTime > 1500) { text = "LONG TAP" ; }
Toast.makeText(getApplicationContext(), text + " " + pressTotalTime + " msec.\n" +
items.get(i).getTitle() + "\n" + items.get(i).getSnippet(), 1).show();
return(true); }
94
Example 4 - Overlays
















// TODO implement longPress actions (such as dialog box showing
//
pictures, links, ???, of selected point.
@Override
public boolean onTouchEvent(MotionEvent event, MapView mapView) {
//remember the initial time the user touches the screen
if (event.getAction() == MotionEvent.ACTION_DOWN ) {
lastTouchTimeDown = event.getDownTime();
lastTouchTimeDown = System.currentTimeMillis(); }
if (event.getAction() == MotionEvent.ACTION_UP ) {
lastTouchTimeUp = System.currentTimeMillis(); }
return super.onTouchEvent(event, mapView);
}
@Override
public int size() { return(items.size()); }
} // SitesOverlay
} //class
95
Example 5 – My Location

In this example we draw current location (and also compass) on
the Map.
96
Example 5 – My Location
















Manifest file
<?xml version="1.0" encoding="utf--‐8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.AndroidMapView" android:versionCode="1" android:versionName="1.0">
<uses‐sdk android:minSdkVersion= "8" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<uses‐library android:name="com.google.android.maps" />
<activity android:name=".AndroidMapViewActivity" android:label="@string/app_name">
<intent‐filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent‐filter> </activity>
</application>
<uses‐permission android:name="android.permission.INTERNET"/>
<uses‐permission android:name="android.permission.ACCESS_FINE_LOCATION">
</uses‐permission>
</manifest>
97
Example 5 – My Location






Main.xml
<?xml version="1.0" encoding="utf--‐8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content"
android:text="@string/hello" />
<com.google.android.maps.MapView android:id="@+id/mapview"
android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true"
android:apiKey="Your Maps API key here" />
</LinearLayout>
98
Example 5 – My Location
















MyItemizedOverlay.java
package edu.odu.cs.cs495.mylocation;
import java.util.ArrayList;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;
public class MyItemizedOverlay extends ItemizedOverlay<OverlayItem>{
private ArrayList<OverlayItem> overlayItemList = new ArrayList<OverlayItem>();
public MyItemizedOverlay(Drawable marker)
{ super(boundCenterBottom(marker));
// TODO Auto‐generated constructor stub
populate();
}
99
Example 5 – My Location


















MyItemizedOverlay.java
public void addItem(GeoPoint p, String title, String snippet){
OverlayItem newItem = new OverlayItem(p, title, snippet);
overlayItemList.add(newItem); populate(); }
@Override
protected OverlayItem createItem(int i) {
// TODO Auto‐generated method stub
return overlayItemList.get(i); }
@Override
public int size() {
// TODO Auto‐generated method stub
return overlayItemList.size(); }
@Override
public void draw(Canvas canvas, MapView mapView, boolean shadow)
{ // TODO Auto‐generated method stub
super.draw(canvas, mapView, shadow);
//boundCenterBottom(marker);
}
100
Example 5 – My Location

















AndroidMapViewActivity.java
package edu.odu.cs.cs495.mylocation;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
public class AndroidMapViewActivity extends MapActivity {
MyItemizedOverlay myItemizedOverlay = null;
MyLocationOverlay myLocationOverlay = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.main);
MapView mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
101
Example 5 – My Location

















AndroidMapViewActivity.java
Drawable marker=getResources().getDrawable(android.R.drawable.star_big_on);
int markerWidth = marker.getIntrinsicWidth(); int markerHeight = marker.getIntrinsicHeight();
marker.setBounds(0, markerHeight, markerWidth, 0);
myItemizedOverlay = new MyItemizedOverlay(marker);
mapView.getOverlays().add(myItemizedOverlay);
GeoPoint myPoint1 = new GeoPoint(0*1000000, 0*1000000);
myItemizedOverlay.addItem(myPoint1, "myPoint1", "myPoint1");
GeoPoint myPoint2 = new GeoPoint(50*1000000, 50*1000000);
myItemizedOverlay.addItem(myPoint2,"myPoint2", "myPoint2");
myLocationOverlay = new MyLocationOverlay(this, mapView);
mapView.getOverlays().add(myLocationOverlay); mapView.postInvalidate();
}
@Override
protected boolean isLocationDisplayed() {
// TODO Auto‐generated method stub
return false; }
102
Example 5 – My Location


















AndroidMapViewActivity.java
@Override
protected boolean isRouteDisplayed()
{
// TODO Auto‐generated method stub
return false;
}
@Override
protected void onResume() {
// TODO Auto‐generated method stub
super.onResume(); myLocationOverlay.enableMyLocation();
myLocationOverlay.enableCompass();
}
@Override
protected void onPause()
{ // TODO Auto‐generated method stub
super.onPause(); myLocationOverlay.disableMyLocation();
myLocationOverlay.disableCompass(); } }
103
References





App Development for Smart Devices
 http://www.cs.odu.edu/~cs495/
http://stackoverflow.com/questions/6343166/android-osnetworkonmainthreadexception
http://stackoverflow.com/questions/15638884/google-mapsrouting-api-v2-android/15643705#15643705
http://stackoverflow.com/questions/14702621/answer-draw-pathbetween-two-points-using-google-maps-android-apiv2/14702636#14702636
http://stackoverflow.com/questions/16262837/how-to-drawroute-in-google-maps-api-v2-from-my-location
104