Android app development course Unit 6- + Location Based Services. Geo-positioning. Google Maps API, Geocoding 1
Location Based Services LBS is a concept that encompasses different technologies which offer a service based on the device's location. They usually use one or a combination of the following smartphone's capabilities: GPS Wifi Radio triangulation Problem! The emulator doesn't support natively LBS services DDMS 2
Location Based Services Android framework location API (not recommended) We need a handle to a LocationManager object through getsystemservice(context.location_service) Then we can do three things: Query a LocationProvider to get the last know user location Register/unregister for periodic updates of user location Define proximity alerts by specifying a radius (in meters) of a given lat/long. 3
Location Based Services Google Location Services API (recommended) First step: setup Google Play Services SDK Download and configure the SDK using the SDK Manager Extras > Google Play services Import the following library project into your project <android-sdk>/extras/google/google_play_services/ libproject/google-play-services_lib/ Reference the library project in your Android project Properties > Android > Library window > Add Can only be tested on an AVD running the Google APIs platform based on Android 4.2.2+! 4
Google Location Services API Retrieve current location the Location Services API automatically maintains the user's current location. request location permissions android.permission.access_coarse_location android.permission.access_fine_location query the current location through com.google.android.gms.location.locationclient 5
Google Location Services API Retrieve current location Create a LocationClient object mlocationclient = new LocationClient(this, this, this); Connect it to the Location Services mlocationclient.connect(); Get the current location Location mcurrlocation = mlocationclient.getlastlocation(); Implement the Location Services interfaces GooglePlayServicesClient.ConnectionCallbaks GooglePlayServicesClient.OnConnectionFailedListener 6
Google Location Services API Implementing Location Services interfaces public class MyActivity extends FragmentActivity implements GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener { @Override public void onconnected(bundle databundle) { // Called when the request to connect the client finishes successfully // We can request the current location or start periodic updates } @Override public void ondisconnected() { // Called if the connection to the client drops because an error } } @Override public void onconnectionfailed(connectionresult connectionresult) { // Called if the attempt to connect the client fails } 7
Google Location Services API We must always check that the Google Play services are installed and ready to use! int resultcode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); if (ConnectionResult.SUCCESS == resultcode) { // Google Play services is available and ready to use } else { } // Get the error dialog from Google Play services Dialog errordialog = GooglePlayServicesUtil.getErrorDialog( errorcode, this, MY_REQUEST_CODE); // Display the dialog in a DialogFragment 8
Google Location Services API Sometimes we are interested in navigation or tracking, so we need to get the user's location at regular intervals. we can set up location updates specifying the interval between updates and the accuracy required requestlocationupdates(locationrequest, listener) removeupdates(listener) Location updates will be received through a LocationListener interface in its method @Override public void onlocationchanged(location location) { } 9
Google Location Services API Specifying request parameters // Create a LocationRequest object LocationRequest mlocationrequest = LocationRequest.create(); // Use high accuracy for location updates mlocationrequest.setpriority(locationrequest.priority_high_accuracy); // Set the update interval to 5 seconds mlocationrequest.setinterval(5 * 1000); // Set the fastest update interval to 1 second mlocationrequest.setfastestinterval(1 * 1000); You should also: request updates in the onconnected() method of the ConnectionCallbacks interface remove updates in the Activity's onstop() method 10
Google Location Services API Geofencing Detecting the user entering/living a given area of interest We should define Latitude, longitude and radius Expiration time An Intent (PendingIntent) for geofence transitions Geofences must be stored (locally or in remote locations), but Location Services require an instance of Geofence, which we can create through Geofence.Builder Geofence monitor request (through LocationClient) addgeofences(geofenceslist, pendingintent, this) 11
Google Location Services API Activity recognition (not Android Activity!) Trying to detect the user's current physical activity, such as walking, driving, etc. Very similar to requesting periodic location updates New permission com.google.android.gms.permission.activity_recognition Request a connection to Location Services through ActivityRecognitionClient Request activity recognition updates using a detection interval and a PendingIntent requestactivityupdates(interval, pendingintent) 12
Google Maps API Google offers a specific set of services to a finite set of supported devices, and the installed apps can use or consume them. The most common and used service is without doubt Google Maps, over which we can add markers based on a latitude and a longitude. We must target devices having the Google Android APIs installed or AVDs supporting them (Google API Android 4.2.2+. 13
Google Maps API Google Maps Android API v1 Deprecated! Google Maps Android API v2 14
Google Maps API Google reinvented its Maps service and completely deprecated the previous API version! In order to use the new API we need to: Configure the Google Play Services project library Obtain a key or API key through the Google APIs Console Configure our AndroidManifest Add a map to our Activity using a MapFragment 15
Google Maps API Setup Google Play Services SDK we have already seen how to do it as part of the Google Location Services API! (Slide #4) 16
Google Maps API Google Maps API Key The maps have to be accessed through the Google Maps servers We need a key (API Key) to access the content We can obtain it through the Google API Console We must add the obtained the API Key in the Manifest file as a child of <application> <meta-data android:name="com.google.android.maps.v2.api_key" android:value="your_api_key"/> 17
Google Maps API In order to get a key for the maps service We need a hash or fingerprint of the certificate we use to sign our application for the Play Store Eclipse automatically manages a Debug certificate for testing purposes, and which we can typically find at ~/.android/debug.keystore (Linux/Mac) Important! This development certificate is host-specific two different computers have different debug certificates, and therefore require two different API keys! 18
Google Maps API (cont) To obtain the Debug certificate's fingerprint we can use the following command-line tool keytool -list -v \ -keystore ~/.android/debug.keystore \ -alias androiddebugkey \ -storepass android \ -keypass android We must add the obtained hash jointly with the app's package name at Google APIs Console > API Access > Create New Android Key... button 19
Google Maps API AndroidManifest We must add some permissions to use the Google Maps API in our Manifest file <uses-permission android:name="android.permission.internet" /> <uses-permission android:name="android.permission.access_network_state" /> <uses-permission android:name="android.permission.write_external_storage" /> <uses-permission android:name="com.google.android.providers.gsf.permission.read_gservices" /> <uses-permission android:name="android.permission.access_coarse_location" /> <uses-permission android:name="android.permission.access_fine_location" />...and a special permission <permission android:name="<package_name>.permission.maps_receive" android:protectionlevel="signature" /> <uses-permission android:name="<package_name>.permission.maps_receive"/> 20
Google Maps API (cont) We also need to add an <uses-feature> element to signal that Google Maps API requires OpenGL ES version 2 <uses-feature android:glesversion="0x00020000" android:required="true" /> That means that Google Play Store will hide our app to those devices not supporting OpenGL ES version 2! 21
Google Maps API And finally, we must add a map to our Activity's layout! XML <fragment android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" class="com.google.android.gms.maps.supportmapfragment"/> Java public class SimpleMapActivity extends FragmentActivity { } @Override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_simple_map); } 22
Activity 6.1 6.1.1 Create a FragmentActivity which includes a map in its layout. 6.1.2 Use SupportMapFragment! 23
Google Maps API GoogleMap Main class to handle map interaction Allows us to customize the map's behavior through different interfaces that respond to different kinds of interaction (touch, pan, zoom, etc.) Handles markers (with an icon) placed on the map We can obtain an instance through the getmap() function private GoogleMap mmap; //... mmap = ((SupportMapFragment) getsupportfragmentmanager(). findfragmentbyid(r.id.map)).getmap(); 24
Google Maps API Configure the map's initial state The Google Maps API provides specific XML attributes to configure a map maptype: type of the map (road, satellite, hybrid) cameratargetlat, cameratargetlng, camerazoom, camerabearing, cameratilt: camera controls uizoomcontrols, uicompass: if we want the zoom and compass controls to be visible uizoomgestures, uiscrollgestures, uirotategestures, uitiltgestures: possible interactions with the map We must add the following namespace xmlns:map="http://schemas.android.com/apk/res-auto" 25
Google Maps API (cont) <fragment xmlns:android="http://schemas.android.com/apk/res/android" xmlns:map="http://schemas.android.com/apk/res-auto" android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" class="com.google.android.gms.maps.supportmapfragment" map:camerabearing="112.5" map:cameratargetlat="41.499876" map:cameratargetlng="2.11275" map:cameratilt="30" map:camerazoom="13" map:maptype="terrain" map:uicompass="false" map:uirotategestures="true" map:uiscrollgestures="false" map:uitiltgestures="true" map:uizoomcontrols="false" map:uizoomgestures="true" /> 26
Google Maps API CameraPosition or how to change our view of the map Our view of the map is modeled through a look-down camera view model The camera's position is computed base on the following properties: target (lat/long), zoom, bearing and tilt 27
Google Maps API To change the part of the world that is visible through the map, use the following methods movecamera( CameraUpdate ) animatecamera( CameraUpdate ) To obtain a CameraUpdate object we should use the methods in CameraUpdateFactory newlatlng(latlng) newlatlngzoom(latlng, float) newcameraposition(cameraposition) 28
Google Maps API Animate the camera to show the city of Sydney static final CameraPosition SYDNEY = new CameraPosition.Builder().target(new LatLng(-33.891614, 151.276417)).zoom(15.5f).bearing(300).tilt(45).build(); mgmap.animatecamera(cameraupdatefactory.newcameraposition(sydney)); 29
Google Maps API We can identify specific positions on the map through different Markers GoogleMap.addMarker(markerOptions)...which we can customize mmap.addmarker(new MarkerOptions().position(new LatLng(0, 0)).title( Hello! ).snippet( I'm a Marker! ).icon(bitmapdescriptorfactory. fromresource(r.drawable.arrow))) 30
Google Maps API The Markers we add on the map Can have a detailed view pop-up window which appears when the user clicks the marker Implemented through InfoWindowAdapter And called by GoogleMap.setInfoWindowAdapter() Can handle different events OnMarkerClickListener OnMarkerDragListener OnInfoWindowClickListener 31
Activity 6.2 6.2.1 Modify the map in the previous activity 6.2.2 Center the map at. latitude = 41.499876. longitude = 2.11275 6.2.3 Add a new marker at this point using whatever information you may find suitable 32
Geocoding Geocoding is the process through which we can map addresses to latitude/longitude coordinates and viceversa. Forward geocoding: given an address, find its latitude and longitude coordinates Reverse geocoding: obtain possible addresses matching a given coordinate pair Geocoding is an external service, so we must set the android.permission.internet accordingly. 33
Geocoding The Geocoder class Handles the address translation process Uses a Locale or the application's context to perform the translation new Geocoder(context, locale) The address translation process is synchronous, so we might consider performing it in a separate thread. 34
Geocoding Forward Geocoding Obtains a list of addresses, containing the latitude and longitude coordinates, from the address's physical description List<Address> getfromlocationname(string, int) The second parameter bound the maximum number of addresses to be returned Returns null if no address matches the description We can limit the search to a bounding box (specified using lat/long coordinates) 35
Geocoding Reverse Geocoding The input represents a coordinate pair (latitude, longitude) The output is a list of relevant locations (with their physical description) found at those coordinates List<Address> getfromlocation(double, double, int) The last parameter bounds the number of addresses to be returned Return null if there is no address to be found at the specified GPS coordinates 36
If you want to know more... Professional Android Application Development. Chapter 8 Pro Android. Chapter 17 Android Developers: Location and Maps Android Developers: Making Your App Location Aware Google Play Services Google Maps Android API v2 37