Custom Heatmap Layer
This example shows how to Add a HeatMap layer to MapView
-
Create HeatMap source with GeoJson Source
-
Create HeatMap Layer with heatmap properties
-
Add HeatMap Layer to MapView

For all code examples, refer to Android Maps SDK Code Examples
activity_heatmaplayer.xml view source
1<?xml version="1.0" encoding="utf-8"?>
2<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent"
5 android:orientation="vertical">
6
7 <ai.nextbillion.maps.core.MapView
8 android:id="@+id/mapView"
9 android:layout_width="match_parent"
10 android:layout_height="match_parent" />
11
12</RelativeLayout>
HeatmapLayerActivity view source
1package ai.nextbillion;
2
3import android.os.Bundle;
4
5import java.net.URI;
6import java.net.URISyntaxException;
7
8import ai.nextbillion.maps.core.MapView;
9import ai.nextbillion.maps.core.NextbillionMap;
10import ai.nextbillion.maps.core.Style;
11import ai.nextbillion.maps.style.layers.CircleLayer;
12import ai.nextbillion.maps.style.layers.HeatmapLayer;
13import ai.nextbillion.maps.style.sources.GeoJsonSource;
14import androidx.appcompat.app.AppCompatActivity;
15
16import static ai.nextbillion.maps.style.expressions.Expression.get;
17import static ai.nextbillion.maps.style.expressions.Expression.heatmapDensity;
18import static ai.nextbillion.maps.style.expressions.Expression.interpolate;
19import static ai.nextbillion.maps.style.expressions.Expression.linear;
20import static ai.nextbillion.maps.style.expressions.Expression.literal;
21import static ai.nextbillion.maps.style.expressions.Expression.rgb;
22import static ai.nextbillion.maps.style.expressions.Expression.rgba;
23import static ai.nextbillion.maps.style.expressions.Expression.stop;
24import static ai.nextbillion.maps.style.expressions.Expression.zoom;
25import static ai.nextbillion.maps.style.layers.PropertyFactory.circleColor;
26import static ai.nextbillion.maps.style.layers.PropertyFactory.circleOpacity;
27import static ai.nextbillion.maps.style.layers.PropertyFactory.circleRadius;
28import static ai.nextbillion.maps.style.layers.PropertyFactory.circleStrokeColor;
29import static ai.nextbillion.maps.style.layers.PropertyFactory.circleStrokeWidth;
30import static ai.nextbillion.maps.style.layers.PropertyFactory.heatmapColor;
31import static ai.nextbillion.maps.style.layers.PropertyFactory.heatmapIntensity;
32import static ai.nextbillion.maps.style.layers.PropertyFactory.heatmapOpacity;
33import static ai.nextbillion.maps.style.layers.PropertyFactory.heatmapRadius;
34import static ai.nextbillion.maps.style.layers.PropertyFactory.heatmapWeight;
35
36/**
37 * Test activity showcasing the heatmap layer api.
38 */
39public class HeatmapLayerActivity extends AppCompatActivity {
40
41 private static final String EARTHQUAKE_SOURCE_URL = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson";
42 private static final String EARTHQUAKE_SOURCE_ID = "earthquakes";
43 private static final String HEATMAP_LAYER_ID = "earthquakes-heat";
44 private static final String HEATMAP_LAYER_SOURCE = "earthquakes";
45 private static final String CIRCLE_LAYER_ID = "earthquakes-circle";
46
47 private MapView mapView;
48 private NextbillionMap nextbillionMap;
49
50 @Override
51 public void onCreate(Bundle savedInstanceState) {
52 super.onCreate(savedInstanceState);
53 setContentView(R.layout.activity_heatmaplayer);
54 mapView = findViewById(R.id.mapView);
55 mapView.onCreate(savedInstanceState);
56 mapView.getMapAsync(map -> {
57 nextbillionMap = map;
58
59 try {
60 nextbillionMap.setStyle(new Style.Builder()
61 .fromUri("https://api.nextbillion.io/maps/dark/style.json")
62 .withSource(createEarthquakeSource())
63 .withLayerAbove(createHeatmapLayer(), "waterway-bridge")
64 .withLayerBelow(createCircleLayer(), HEATMAP_LAYER_ID)
65 );
66 } catch (URISyntaxException exception) {
67 }
68 });
69 }
70
71 private GeoJsonSource createEarthquakeSource() throws URISyntaxException {
72 return new GeoJsonSource(EARTHQUAKE_SOURCE_ID, new URI(EARTHQUAKE_SOURCE_URL));
73 }
74
75 private HeatmapLayer createHeatmapLayer() {
76 HeatmapLayer layer = new HeatmapLayer(HEATMAP_LAYER_ID, EARTHQUAKE_SOURCE_ID);
77 layer.setMaxZoom(9);
78 layer.setSourceLayer(HEATMAP_LAYER_SOURCE);
79 layer.setProperties(
80
81 // Color ramp for heatmap. Domain is 0 (low) to 1 (high).
82 // Begin color ramp at 0-stop with a 0-transparancy color
83 // to create a blur-like effect.
84 heatmapColor(
85 interpolate(
86 linear(), heatmapDensity(),
87 literal(0), rgba(33, 102, 172, 0),
88 literal(0.2), rgb(103, 169, 207),
89 literal(0.4), rgb(209, 229, 240),
90 literal(0.6), rgb(253, 219, 199),
91 literal(0.8), rgb(239, 138, 98),
92 literal(1), rgb(178, 24, 43)
93 )
94 ),
95
96 // Increase the heatmap weight based on frequency and property magnitude
97 heatmapWeight(
98 interpolate(
99 linear(), get("mag"),
100 stop(0, 0),
101 stop(6, 1)
102 )
103 ),
104
105 // Increase the heatmap color weight weight by zoom level
106 // heatmap-intensity is a multiplier on top of heatmap-weight
107 heatmapIntensity(
108 interpolate(
109 linear(), zoom(),
110 stop(0, 1),
111 stop(9, 3)
112 )
113 ),
114
115 // Adjust the heatmap radius by zoom level
116 heatmapRadius(
117 interpolate(
118 linear(), zoom(),
119 stop(0, 2),
120 stop(9, 20)
121 )
122 ),
123
124 // Transition from heatmap to circle layer by zoom level
125 heatmapOpacity(
126 interpolate(
127 linear(), zoom(),
128 stop(7, 1),
129 stop(9, 0)
130 )
131 )
132 );
133 return layer;
134 }
135
136 private CircleLayer createCircleLayer() {
137 CircleLayer circleLayer = new CircleLayer(CIRCLE_LAYER_ID, EARTHQUAKE_SOURCE_ID);
138 circleLayer.setProperties(
139
140 // Size circle radius by earthquake magnitude and zoom level
141 circleRadius(
142 interpolate(
143 linear(), zoom(),
144 literal(7), interpolate(
145 linear(), get("mag"),
146 stop(1, 1),
147 stop(6, 4)
148 ),
149 literal(16), interpolate(
150 linear(), get("mag"),
151 stop(1, 5),
152 stop(6, 50)
153 )
154 )
155 ),
156
157 // Color circle by earthquake magnitude
158 circleColor(
159 interpolate(
160 linear(), get("mag"),
161 literal(1), rgba(33, 102, 172, 0),
162 literal(2), rgb(103, 169, 207),
163 literal(3), rgb(209, 229, 240),
164 literal(4), rgb(253, 219, 199),
165 literal(5), rgb(239, 138, 98),
166 literal(6), rgb(178, 24, 43)
167 )
168 ),
169
170 // Transition from heatmap to circle layer by zoom level
171 circleOpacity(
172 interpolate(
173 linear(), zoom(),
174 stop(7, 0),
175 stop(8, 1)
176 )
177 ),
178 circleStrokeColor("white"),
179 circleStrokeWidth(1.0f)
180 );
181
182 return circleLayer;
183 }
184
185 @Override
186 protected void onStart() {
187 super.onStart();
188 mapView.onStart();
189 }
190
191 @Override
192 protected void onResume() {
193 super.onResume();
194 mapView.onResume();
195 }
196
197 @Override
198 protected void onPause() {
199 super.onPause();
200 mapView.onPause();
201 }
202
203 @Override
204 protected void onStop() {
205 super.onStop();
206 mapView.onStop();
207 }
208
209 @Override
210 public void onSaveInstanceState(Bundle outState) {
211 super.onSaveInstanceState(outState);
212 mapView.onSaveInstanceState(outState);
213 }
214
215 @Override
216 public void onLowMemory() {
217 super.onLowMemory();
218 mapView.onLowMemory();
219 }
220
221 @Override
222 public void onDestroy() {
223 super.onDestroy();
224 mapView.onDestroy();
225 }
226}
227
This code is an example of an Android activity that showcases the use of a heatmap layer in a map view. The activity creates a map view, sets up a heatmap layer with a GeoJSON data source, and adds the heatmap layer to the map view.
initMapView:
- The map view is initialized in the onCreate method by calling mapView.onCreate(savedInstanceState). This sets up the map view and prepares it for use.
Create HeatMap source with GeoJson Source:
- The createEarthquakeSource method creates a GeoJsonSource for the heatmap layer using a GeoJSON data source. It takes the URL of the GeoJSON data as a parameter and creates a new GeoJsonSource object with a unique ID and the provided data source URL.
Create HeatMap Layer with heatmap properties:
-
The createHeatmapLayer method creates a HeatmapLayer object with a unique ID and sets various properties for the heatmap layer.
-
The properties include the color ramp for the heatmap, the weight of the heatmap based on frequency and magnitude, the intensity and radius of the heatmap based on the zoom level, and the opacity transition from the heatmap to the circle layer.
Add HeatMap Layer to MapView:
-
In the onCreate method, after setting up the map view, the nextbillionMap.setStyle method is called to set the map style and add the heatmap layer to the map view.
-
The Style.Builder is used to create a new map style and the createEarthquakeSource and createHeatmapLayer methods are called to create the GeoJSON data source and heatmap layer, respectively.
-
The created source and layer are then added to the map style using the withSource and withLayerAbove or withLayerBelow methods, depending on the desired layer order.
Note: The code also includes methods for creating a circle layer, setting up the map view lifecycle callbacks, and handling various other lifecycle events of the activity.