Ever since we released GeoFire for JavaScript, we've seen many requests for mobile ports of the library. Today, we're happy to announce GeoFire for iOS and Android!

GeoFire is now supported on our three major platforms - web, iOS and Android - and each library is open source! Each version comes with a sample app, which queries and displays San Francisco public transportation data in realtime.

You can find the corresponding sample apps as part of the GeoFire repos for Objective-C and Java.

What is GeoFire?

If you're new to GeoFire, it's a geolocation library that maps string keys to locations and stores them in Firebase. Using GeoFire, you can answer a simple but important question: Which keys lie within a given geographic region? But GeoFire's features don't stop at simple location queries, it's true power is that everything happens in realtime. When objects move, events will be fired as they enter, exit and move around the region.

GeoFire opens a wide range of possibilities: You can build an app that displays who's going for a run within a mile radius of yourself and show their location in realtime. You can display taxis within a search radius and animate them as they move. Or you can build an app that simply lists all interesting bars nearby.

Building your next app with GeoFire

The GeoFire libraries are available as a XCode Framework and as a Java jar-file for easy integration. Add them to your app, include the Firebase library and you're ready to go.

All three versions are compatible with each other. If you are storing locations in your iOS or Android app, you will be able to query them in the web and vice versa.

Take a look at our quick start guides for the Objective-C and the Java versions to get familiar with GeoFire on each platform.

Structuring your data

GeoFire is designed to be a lightweight add-on for Firebase, not a replacement. As such, you will continue to store your data just as you would normally do in Firebase and use GeoFire to query keys by location.

Let's assume we're building a social running app, where we want to display stats for all runners in our area. We'll start by storing basic data for each user like the following:

{
  "users": {
    "steve123": {
      "displayname": "Steve T.",
      "age": 29,
      "location": [37.12314, -122.49182],
      "stats": {
        "averageSpeed": 11.2,
        "currentSpeed": 9.7,
        ...
      }
    },
    "nikky_kay": {
      "displayname": "Nicole",
      "age": 37,
      "location": [37.67134, -122.32990],
      "stats": {
        ...
      }
    },
    ...
  }
}

Now that we've stored our user information in Firebase, we'll use GeoFire to search for nearby runners in realtime. In this example, we're storing each user by their username, and the user's location as a pair of latitude-longitude coordinates. By keeping the location key as a child of the user key, we can listen for realtime updates for a single user. Everytime we update the location of a user we simultaneously update the location for that user in GeoFire.

We'll now use a GeoQuery to retrieve all keys (usernames in this example) in a given geographic region. Using the key entered and key exited events, we can keep track of all users currently matching the query, e.g. with a NSMutableSet in Objective-C or Set<String> in Java.

NSMutableSet *runnersNearby = [NSMutableSet set];

// query around current user location with 1.6km radius
GFQuery *query = [self.geoFire queryAtLocation:currentUserLocation withRadius:1.6];

[query observeEventType:GFEventTypeKeyEntered withBlock:^(NSString *username, CLLocation *location) {
    [runnersNearby addObject:username];
    // additional code, like displaying a pin on the map
    // and adding Firebase listeners for this user
}];

[query observeEventType:GFEventTypeKeyExited withBlock:^(NSString *username, CLLocation *location) {
    [runnersNearby removeObject:username]
    // additional code, like removing a pin from the map
    // and removing any Firebase listener for this user
}];
final Set<String> runnersNearby = new HashSet<String>();

// query around current user location with 1.6km radius
GeoQuery geoQuery = geoFire.queryAtLocation(currentUserLocation, 1.6);

geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
    @Override
    public void onKeyEntered(String username, GeoLocation location) {
        runnersNearby.add(username);
        // additional code, like displaying a pin on the map
        // and adding Firebase listeners for this user
    }

    @Override
    public void onKeyExited(String username) {
        runnersNearby.remove(username);
        // additional code, like removing a pin from the map
        // and removing any Firebase listener for this user
    }

    ...
});

We're ready to update our UI in realtime! Now that we know which users are nearby and we want to display, we can add a normal Firebase listener to each user and keep their stats updated in realtime. Remember, adding a listener in Firebase is a very lightweight operation, and adding thousands of listeners is not a problem. If a user ever moves outside the query, all we need to do is remove that listener and update our UI.

Build the future of realtime location apps with GeoFire

We're excited to see the amazing apps you build with Firebase and GeoFire! If you have any feedback on our new mobile libraries, you can email me at [jonny@firebase.com](mailto:jonny@firebase.com?subject=GeoFire goes Mobile) or send us a pull request.