E2 on Android

Android apps call the E2 hosted REST endpoints and draw the results as markers, route lines, and stats on a native map.

Documentation navigation

How E2 fits

There is no Android SDK; E2 exposes plain REST endpoints over HTTPS. Search returns GeoJSON, routing returns a route geometry, and compute returns numbers — all easy to consume from Kotlin with Retrofit or OkHttp and render with any native map.

Setup

build.gradle.kts
dependencies {
  implementation("com.squareup.retrofit2:retrofit:2.11.0")
  implementation("com.squareup.retrofit2:converter-gson:2.11.0")
  implementation("org.maplibre.gl:android-sdk:11.0.0")
}
E2Api.kt
interface E2Api {
  @GET("search")
  suspend fun search(
    @Query("feature") feature: String,
    @Query("area") area: String,
    @Query("limit") limit: Int,
  ): SearchResponse
}

// Configure the base URL for your deployment
val api = Retrofit.Builder()
  .baseUrl(BuildConfig.E2_BASE_URL)
  .addConverterFactory(GsonConverterFactory.create())
  .build()
  .create(E2Api::class.java)

Search

SearchViewModel.kt
data class SearchResponse(val type: String, val features: List<GeoFeature>)
data class GeoFeature(val geometry: Geometry, val properties: Map<String, Any?>)
data class Geometry(val coordinates: List<Double>)

viewModelScope.launch {
  val places = api.search(feature = "restaurant", area = "Manhattan", limit = 500)

  places.features.forEach { feature ->
    val (lng, lat) = feature.geometry.coordinates
    mapLibreMap.addMarker(
      MarkerOptions().position(LatLng(lat, lng))
        .title(feature.properties["name"] as? String ?: "Restaurant"),
    )
  }
}

Routing

RoutingViewModel.kt
interface E2Api {
  @POST("route")
  suspend fun route(@Body request: RouteRequest): RouteResponse
}

data class RouteRequest(val locations: List<LatLngDto>, val mode: String)
data class RouteResponse(val geometry: RouteGeometry)
data class RouteGeometry(val coordinates: List<List<Double>>)

val route = api.route(
  RouteRequest(
    locations = listOf(LatLngDto(40.74, -73.99), LatLngDto(40.71, -74.01)),
    mode = "walking",
  ),
)

val line = route.geometry.coordinates.map { (lng, lat) -> LatLng(lat, lng) }
mapLibreMap.addPolyline(
  PolylineOptions().addAll(line).color(0xFFE2B07A.toInt()).width(6f),
)

Compute

ComputeViewModel.kt
interface E2Api {
  @GET("compute/count")
  suspend fun computeCount(
    @Query("feature") feature: String,
    @Query("region") region: String,
    @Query("near") near: String,
    @Query("distance") distance: Int,
  ): CountResponse
}

data class CountResponse(val count: Int)

val nearParks = api.computeCount("restaurant", "Manhattan", "park", 500)
_stats.value = "${nearParks.count} restaurants within 500 m of a park"

Notes

The base URL is configurable — point it at the E2 hosted platform or your own deployment. Keep API keys in BuildConfig or a secrets store rather than source, and cache responses on device if you query the same features repeatedly.