Creating a Location Aware “Hot and Cold” Mobile App

Part 1 of Creating a “Hot and Cold” Game as a Location Awareness Proof of Concept

Background

You may have played the hot and cold game before. One player hides something, and the other player must search for it. The only clue is that the hider must tell the searcher whether they are getting hotter or colder as they get closer to or further away from the hidden item.

The principles of the hot and cold game provide a good test case for location awareness in a mobile application. I want to be able to tell if the mobile device is hot or cold relative to a given location.

This post documents the creation of a mobile application that presents the user with a map. Using this map, they can mark a set of arbitrary locations. The application then alerts the user when they are getting closer to the marked locations.

The github repo for this project is located here.

If you have the Expo Client (which can be found in either Apple’s App Store or Google Play) installed on your phone, you can download and play with the application here: https://exp.host/@reggie3/geofencing-proof-of-concept

This will be a two post series. In the first post, I will describe the setup and basic UI functionality. The final result will be an application in which the user can click on a map to place a named location marker. Additionally, they will be able to look at and delete locations from a list.

The final product

The second article will detail location distance detection and user feedback.

Introduction

The JavaScript functionality of the application can be applied across multiple frameworks. For my own ease of use, I will be using a combination of react-native, expo.io, and redux to build this application.

There are numerous outstanding guides and tutorials on using each of these tools so I won’t be discussing any of these in depth here. This post will be easiest to follow for those who have completed Facebook’s react-native tutorial, are able to use the expo.io xde to create a react-native application (which is super easy), and are familiar enough with redux (or any react state management tool) to use it in a react application.

Design

The design of this program is pretty simple since it only needs to do the following:

  1. Allow the user to set locations
  2. Display those locations to the user
  3. Provide feedback to the user as they get closer to or further away (hotter/colder) from the location

I also anticipate that there will be a need to adjust some settings as I get the hang of determining location sensitivities.

Based on this list of requirements, I decided to build a three screen application using a tab navigation system to simplify routing. The “home” screen will be a map that the user can touch to place a marker. This map will also display the markers and provide the required hotter/colder feedback. A second screen will display a list of locations. The third a final screen will be used for settings.

Implementation

Setup

Using expo.io, I was able to quickly scaffold a two page tab navigated application by following the “Creating Application” section of their getting started guide. The setup wizard even presents the option of building a blank or tab navigated application that is built on react-navigation. I don’t think they could make the process any easier, and I hope they offer more setup options in the future.

Another piece of expo.io goodness was the inclusion of a Airbnb’s react-native-maps as a component. Expo provides a guide to include the component along with clear instructions along with instructions on how to include it. Airbnb’s documentation provides more information about map options including how to show the user’s current location, and respond to touch events.

In addition to redux for state management , react-redux to bind react to redux, and redux-logger to catch my mistakes, I also installed the following packages:

  1. geolib which bills itself as a “Library to provide basic geospatial operations like distance calculation, conversion of decimal coordinates to sexagesimal and vice versa, etc.” This will be useful to calculate the distance from the user’s location to the markers.
  2. react-native-prompt which is advertised as “A cross-platform prompt component for React Native.” I will use this to get marker names from the user when they click on the map to place.
  3. uuid to give each marker a unique ID.
  4. shortid to give each marker name a unique short string that is shorter than the uuid.

User Interface

Next, I altered the MainTabNavigator.js file that expo created to include three screens (MapScreen, LocationsScreen, and SettingsScreen) vice the two defaults.

While the SettingsScreen already exists when expo.io created the project, I had to create the Map and Locations screen myself. However, they are both pretty simple to make thanks to the guides that exist.

As stated previously, expo already provides a guide for displaying a map in a view. This guide served as the basis for my MapScreen.

Similarly, Facebook provides a guide for creating and displaying a list of components (whether those components be simple text or something more complicated). This list was the foundation of the LocationsScreen and will contain a component that corresponds to the location of each marker placed on the map.

To summarize, I created three screens. One to show the map, another to show a list of locations, and a third to contain settings information.

The final screens

Location Data

The first set of location data I wanted to obtain is the user’s current location. Expo also includes functionality to get device location information. At the risk of sounding repetitive, they also have a guide to include this functionality. I included the code from the guide in the App.js file’s componentWillMount function. The App.js file is created by the expo project builder and is the root of the project. I included a call to a redux action to update the program’s redux store every time the device location changed.

I then accessed that location from the MapScreen and displayed it as the center of the initialRegion in the Expo.MapView component. Setting showsUserLocation={true} in the Expo.MapView component’s props presents us with that familiar light blue circle representing the device’s current location, which thanks to our work with initialRegion should be at the center of the screen.

The other set of location data I needed was the marker location, but first I had to give the user the ability to place markers. The MapView includes an onPress event which did two things to component state: store the location the point pressed, and change the boolean controling prompt visibility to true. This boolean determines wheter react-native-prop component is displayed as documented in the react-native-prompt github page. Submitting the prompt results in the dispatch of an event that puts an object containing the location’s name and coordinates in an array inside the redux store.

Once the user has placed a marker, it gets displayed on the map using the Expo.MapView.Marker component which is inside a map call to the locations array in the redux store.

The final result is that the user’s current location is displayed by a blue dot that is in the center of the map screen. Additionally, the user can touch the map to specify new markers to be placed on the map.

Gist of MapScreen component

Publishing

Expo includes the ability to publish and share apps without having to go through Google Play or Apple’s App Store. Sharing applications this way requires other users to have the Expo Client installed on their phone. The upside is that the client only needs to install Expo once to run any applications published this way. This application can be downloaded at https://exp.host/@reggie3/geofencing-proof-of-concept

This technique allow for easy distribution. It also means that the deployed applications will receive updates as they are made.

Yeah, Expo is pretty awesome

Conclusion

That’s it for the program’s UI and its basic functionality. The next article will describe the process of measuring “hot and cold”, and providing the user feedback as they get closer or further away from their markers.

End result

Reginald Johnson has maintained his passion for coding throughout his 20+ year career as an Officer in the United States Navy. He enjoys applying his training and experience in programming, Systems Engineering, and Operational Planning towards programming. Follow him Twitter @reginald3.