name: inverse layout: true class: center, middle, inverse --- # Implementing Location Lauren Bricker CSE 340 Spring 2022 --- layout: false [//]: # (Outline Slide) # Today's Agenda - Administrivia - Undo due tonight! - Poll (on Ed) What to do with Monday?!?!? - [Final project spec](/courses/cse340/22sp/assignments/final-project.html) - Turn in information (all on [Gradescope](https://www.gradescope.com/courses/378144)) - Learning goals - Review of [Sensors](../wk08/sensing.html#3) - Implement location - Time to work on Sensing activity (and turn in screenshot) --- # Do this now If you've already accepted the [sensing exercise](https://gitlab.cs.washington.edu/cse340/exercises/cse340-sensing-and-location), please do the following: 1. go into the directory where your source code exists 2. `git stash push` any files you have changed 3. `git pull` to get the latest source 4. `git stash pop` to put your files over the newly grabbed files. You will also likely have to Invalidate Caches and Restart... as well as sync with the new gradle information There have been changes in the `LocationActivity`, some of the resource files, and gradle to prep for today's in class work. --- # Location - Locations are generally reported as Latitude and Longitude coordinates. - Generally reported using “Global Position System” (GPS) - Can also use cell tower or WiFi localization. - Three ways to do this - [LocationManager](https://stuff.mit.edu/afs/sipb/project/android/docs/training/basics/location/locationmanager.html) - [Fused Location Provider API](https://developers.google.com/location-context/fused-location-provider) - Need to set up [Google Play Services](https://developer.android.com/google/play-services/setup) on the device (including emulators) - Less power consumption - [Google Awareness API](https://developers.google.com/awareness) - Requires Google credits ($$$) --- ## Location: Getting data with LocationManager Declare permissions in `AndroidManifest.xml` ```xml
``` --- ## Location: Getting data with LocationManager `LocationManager` - Main class to access location services - Reference can be obtained by calling ` getSystemService()` in in the `onCreate()` in your `Activity` - Pick a location provider (like `GPS_PROVIDER`) or have the system pick based on criteria such as cost or accuracy. - Check if the provider is available `LocationListener#onLocationChanged` - to get notifications at regular intervals `LocationManager#getLastKnownLocation()` - will get you a snapshot of the last known location `Location` - an actual location --- # LocationManager example ``` Java LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_COARSE); criteria.setCostAllowed(false); String provider = locationManager.getBestProvider(criteria, false); Location location = null; try { location = locationManager.getLastKnownLocation(provider); MyLocationListener mylistener = new MyLocationListener(); if (location != null) { mylistener.onLocationChanged(location); } else { ... } // location updates: at least 1 meter and 500 milli seconds change locationManager.requestLocationUpdates(provider, 500, 1, mylistener); } catch (SecurityException e) { ... } ``` --- ## Location: Getting data with Fused Location Provider - [fused location provider](https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderClient.html) is another mechanism to get locations - ✅ Faster - ✅ Provides more accurate locations - ❌ Requires Google Play Services installed on your device. - Specify app permissions - Do we need to get the locations in the foreground or background? - Do we want a precise or approximate location? - Create the location services client (a `FusedLocationProviderClient`) and set up a listener to get the location. --- ## Location: Getting data with LocationManager `FusedLocationProviderClient` - Location services client - Reference can be obtained by calling `LocationServices.getFusedLocationProviderClient()` in in the `onCreate()` in your `Activity` `FusedLocationProviderClient#requestLocationUpdates` - to get notifications at regular intervals `FusedLocationProviderClient#getLastKnownLocation()` - will get you a snapshot of the last known location - Need to have an `OnSuccessListener` callback set up. `Location` - an actual location --- ## Location: Getting data with FusedLocationProviderClient First get the `FusedLocationProviderClient` ```java // Initialize Location Services Client for continuous location checking FusedLocationProviderClient mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this); mLocationRequest = LocationRequest.create(); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); mLocationRequest.setInterval(DEFAULT_UPDATE_INTERVAL * 1000); mLocationRequest.setInterval(FAST_UPDATE_INTERVAL * 1000); ``` This will request the location permissions, need to gracefully handle if the user says no --- ## Location: Requestion updates from FusedLocationProviderClient First create a callback to handle the updates: ```java private final LocationCallback mLocationCallback = new LocationCallback() { @Override public void onLocationResult(LocationResult locationResult) { List
locationList = locationResult.getLocations(); if (locationList.size() > 0) { // do something with the locations... } } }; ``` --- ## Location: Requestion updates from FusedLocationProviderClient If the user approves location permissions, connect the callback. ```java mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper()); ``` --- ## Location: Stop tracking Location Generally good principle to stop tracking if the app is paused (responding to `onPause`) or the user revokes permissions ```java if (mFusedLocationClient != null) { mFusedLocationClient.removeLocationUpdates(mLocationCallback); ``` --- # Classroom activity .left-column40[ ![:img Location activity solution with a map on the screen, 50%, width](img/location/location-map.png) ] .right-column60[ Add some code in `LocationActivity#displayLocation(Location)` that will get additional information from the Location object and display it on the screen Alternatively add a Map! ] --- # Adding a map using Mapbox [Mapbox](https://www.mapbox.com/) is free to use if your app is under 25,000 monthly active users (no credit card needed to use the service) To use it: * Sign up for an account & verify your email * Create a token for your app * Follow the instructions for [how to install](https://docs.mapbox.com/android/maps/guides/install/) * The `README.md` in the [Sensing and Location](https://gitlab.cs.washington.edu/cse340/exercises/cse340-sensing-and-location) repository has information on how to get started. --- # Using a MapView interactor Once you've added your MapView to the screen (either in an `.xml` file or programatically), you can interact with it using their [mapbox-map API](https://docs.mapbox.com/android/maps/api/10.5.0/mapbox-maps-android/) API. Example 1 - setting the camera to a zoom level: ```java // Build a camera options object CameraOptions co = new CameraOptions.Builder().zoom(mZoomLevel).build(); // Set the camera to use the CameraOptions object mMapView.getMapboxMap().setCamera(co); ``` --- # Using a MapView interactor Once you've added your MapView to the screen (either in an `.xml` file or programatically), you can interact with it using their [mapbox-map API](https://docs.mapbox.com/android/maps/api/10.5.0/mapbox-maps-android/) API. Example 2 - setting the camera to a specific position: ```java Point p = Point.fromLngLat(mCurrentLocation.getLongitude(), mCurrentLocation.getLatitude()); // Build a camera options object to be at a particular Point CameraOptions co = new CameraOptions.Builder().center(p).build(); // Set the camera to use the CameraOptions object mMapView.getMapboxMap().setCamera(co); ``` --- # End of Deck