package com.airbnb.airmapview.sample; import android.graphics.Bitmap; import android.graphics.Point; import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.Toast; import com.airbnb.android.airmapview.AirMapGeoJsonLayer; import com.airbnb.android.airmapview.AirMapInterface; import com.airbnb.android.airmapview.AirMapMarker; import com.airbnb.android.airmapview.AirMapPolygon; import com.airbnb.android.airmapview.AirMapPolyline; import com.airbnb.android.airmapview.AirMapView; import com.airbnb.android.airmapview.AirMapViewTypes; import com.airbnb.android.airmapview.DefaultAirMapViewBuilder; import com.airbnb.android.airmapview.GoogleChinaMapType; import com.airbnb.android.airmapview.LeafletBaiduMapType; import com.airbnb.android.airmapview.LeafletGaodeMapType; import com.airbnb.android.airmapview.LeafletGoogleChinaMapType; import com.airbnb.android.airmapview.LeafletGoogleMapType; import com.airbnb.android.airmapview.LeafletWebViewMapFragment; import com.airbnb.android.airmapview.MapType; import com.airbnb.android.airmapview.WebAirMapViewBuilder; import com.airbnb.android.airmapview.listeners.OnCameraChangeListener; import com.airbnb.android.airmapview.listeners.OnCameraMoveListener; import com.airbnb.android.airmapview.listeners.OnInfoWindowClickListener; import com.airbnb.android.airmapview.listeners.OnLatLngScreenLocationCallback; import com.airbnb.android.airmapview.listeners.OnMapClickListener; import com.airbnb.android.airmapview.listeners.OnMapInitializedListener; import com.airbnb.android.airmapview.listeners.OnMapMarkerClickListener; import com.airbnb.android.airmapview.listeners.OnSnapshotReadyListener; import com.google.android.gms.maps.model.LatLng; import org.json.JSONException; import java.util.Arrays; public class MainActivity extends AppCompatActivity implements OnCameraChangeListener, OnMapInitializedListener, OnMapClickListener, OnCameraMoveListener, OnMapMarkerClickListener, OnInfoWindowClickListener, OnLatLngScreenLocationCallback { private final LogsAdapter adapter = new LogsAdapter(); private static final String TAG = MainActivity.class.getSimpleName(); private AirMapView map; private DefaultAirMapViewBuilder mapViewBuilder; private RecyclerView logsRecyclerView; private View bottomToolsView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mapViewBuilder = new DefaultAirMapViewBuilder(this); map = findViewById(R.id.map); bottomToolsView = findViewById(R.id.bottom_tools); logsRecyclerView = findViewById(R.id.logs); ((LinearLayoutManager) logsRecyclerView.getLayoutManager()).setReverseLayout(true); logsRecyclerView.setAdapter(adapter); Button btnMapTypeNormal = findViewById(R.id.btnMapTypeNormal); Button btnMapTypeSattelite = findViewById(R.id.btnMapTypeSattelite); Button btnMapTypeTerrain = findViewById(R.id.btnMapTypeTerrain); btnMapTypeNormal.setOnClickListener(new View.OnClickListener() { @Override public void onClick(@NonNull View v) { map.setMapType(MapType.MAP_TYPE_NORMAL); } }); btnMapTypeSattelite.setOnClickListener(new View.OnClickListener() { @Override public void onClick(@NonNull View v) { map.setMapType(MapType.MAP_TYPE_SATELLITE); } }); btnMapTypeTerrain.setOnClickListener(new View.OnClickListener() { @Override public void onClick(@NonNull View v) { map.setMapType(MapType.MAP_TYPE_TERRAIN); } }); map.setOnMapClickListener(this); map.setOnCameraChangeListener(this); map.setOnCameraMoveListener(this); map.setOnMarkerClickListener(this); map.setOnMapInitializedListener(this); map.setOnInfoWindowClickListener(this); map.initialize(getSupportFragmentManager()); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); AirMapInterface airMapInterface = null; switch (id) { case R.id.action_native_map: try { airMapInterface = mapViewBuilder.builder(AirMapViewTypes.NATIVE).build(); } catch (UnsupportedOperationException e) { Toast.makeText(this, "Sorry, native Google Maps are not supported by this device. " + "Please make sure you have Google Play Services installed.", Toast.LENGTH_SHORT).show(); } break; case R.id.action_mapbox_map: airMapInterface = mapViewBuilder.builder(AirMapViewTypes.WEB).build(); break; case R.id.action_google_web_map: // force Google Web maps since otherwise AirMapViewTypes.WEB returns MapBox by default. airMapInterface = new WebAirMapViewBuilder().build(); break; case R.id.action_google_china_web_map: airMapInterface = new WebAirMapViewBuilder().withOptions(new GoogleChinaMapType()).build(); break; case R.id.action_leaflet_google_web_map: airMapInterface = new WebAirMapViewBuilder().withOptions(new LeafletGoogleMapType()).build(); break; case R.id.action_leaflet_google_china_web_map: airMapInterface = new WebAirMapViewBuilder().withOptions(new LeafletGoogleChinaMapType()).build(); break; case R.id.action_baidu_web_map: airMapInterface = new WebAirMapViewBuilder().withOptions(new LeafletBaiduMapType()).build(); break; case R.id.action_gaode_web_map: airMapInterface = new WebAirMapViewBuilder().withOptions(new LeafletGaodeMapType()).build(); break; case R.id.action_clear_logs: adapter.clearLogs(); break; case R.id.add_geojson_layer: // Draws a layer on top of Australia String geoJsonString = Util.readFromRawResource(this, R.raw.google); AirMapGeoJsonLayer layer = new AirMapGeoJsonLayer.Builder(geoJsonString) .strokeColor(getResources().getColor(android.R.color.holo_green_dark)) .strokeWidth(10) .fillColor(getResources().getColor(android.R.color.holo_green_light)) .build(); try { map.getMapInterface().setGeoJsonLayer(layer); } catch (JSONException e) { Log.e(TAG, "Failed to add GeoJson layer", e); } break; case R.id.remove_geojson_layer: map.getMapInterface().clearGeoJsonLayer(); break; case R.id.take_snapshot: map.getMapInterface().getSnapshot(new OnSnapshotReadyListener() { @Override public void onSnapshotReady(@Nullable Bitmap bitmap) { if (bitmap != null) { appendBitmap(bitmap); } else { appendLog("Null bitmap"); } } }); break; case R.id.enable_location: map.setMyLocationEnabled(true); break; case R.id.disable_location: map.setMyLocationEnabled(false); case R.id.add_padding: map.setPadding(0, 0, 0, bottomToolsView.getHeight()); break; case R.id.center_map: { LatLng wfcLatLng = new LatLng(39.918786, 116.459273); map.setCenter(wfcLatLng); break; } case R.id.animateCenter: { LatLng wfcLatLng = new LatLng(39.918786, 116.459273); map.animateCenter(wfcLatLng); break; } case R.id.zoom: map.setZoom(15); break; case R.id.animateCenterZoom: { LatLng wfcLatLng = new LatLng(39.918786, 116.459273); map.animateCenterZoom(wfcLatLng, 15); break; } default: break; } if (airMapInterface != null) { map.initialize(getSupportFragmentManager(), airMapInterface); } return super.onOptionsItemSelected(item); } @Override public void onCameraChanged(LatLng latLng, int zoom) { appendLog("Map onCameraChanged triggered with lat: " + latLng.latitude + ", lng: " + latLng.longitude); } @Override public void onMapInitialized() { appendLog("Map onMapInitialized triggered"); if (map.getMapInterface() instanceof LeafletWebViewMapFragment) { // Baidu map is unavailable in the US, so we show points in China. final LatLng wfcLatLng = new LatLng(39.918786, 116.459273); addMarker("WFC", wfcLatLng, 1); addMarker("Chaoyang Gate", new LatLng(39.923823, 116.433666), 2); String image = "<img width=\"25\" height=\"41\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAABSCAMAAAAhFXfZAAAC91BMVEVMaXEzeak2f7I4g7g3g7cua5gzeKg8hJo3grY4g7c3grU0gLI2frE0daAubJc2gbQwd6QzeKk2gLMtd5sxdKIua5g1frA2f7IydaM0e6w2fq41fK01eqo3grgubJgta5cxdKI1f7AydaQydaMxc6EubJgvbJkwcZ4ubZkwcJwubZgubJcydqUydKIxapgubJctbJcubZcubJcvbJYubJcvbZkubJctbJctbZcubJg2f7AubJcrbZcubJcubJcua5g3grY0fq8ubJcubJdEkdEwhsw6i88vhswuhcsuhMtBjMgthMsrg8srgss6is8qgcs8i9A9iMYtg8spgcoogMo7hcMngMonf8olfso4gr8kfck5iM8jfMk4iM8he8k1fro7itAgesk2hs8eecgzfLcofssdeMg0hc4cd8g2hcsxeLQbdsgZdcgxeLImfcszhM0vda4xgckzhM4xg84wf8Yxgs4udKsvfcQucqhUndROmdM1fK0wcZ8vb5w0eqpQm9MzeKhXoNVcpdYydKNWn9VZotVKltJFjsIwcJ1Rms9OlslLmtH///8+kc9epdYzd6dbo9VHkMM2f7FHmNBClM8ydqVcpNY9hro3gLM9hLczealQmcw3fa46f7A8gLMxc6I3eagyc6FIldJMl9JSnNRSntNNl9JPnNJFi75UnM9ZodVKksg8kM45jc09e6ZHltFBk883gbRBh7pDk9EwcaBzn784g7dKkcY2i81Om9M7j85Llc81is09g7Q4grY/j9A0eqxKmdFFltBEjcXf6fFImdBCiLxJl9FGlNFBi78yiMxVndEvbpo6js74+vx+psPP3+o/ks5HkcpGmNCjwdZCkNDM3ehYoNJEls+lxNkxh8xHks0+jdC1zd5Lg6r+/v/H2ufz9/o3jM3t8/edvdM/k89Th61OiLBSjbZklbaTt9BfptdjmL1AicBHj8hGk9FAgK1dkLNTjLRekrdClc/k7fM0icy0y9tgp9c4jc2NtM9Dlc8zicxeXZn3AAAAQ3RSTlMAHDdTb4yPA+LtnEQmC4L2EmHqB7XA0d0sr478x4/Yd5i1zOfyPkf1sLVq4Nh3FvjxopQ2/STNuFzUwFIwxKaejILpIBEV9wAABhVJREFUeF6s1NdyFEcYBeBeoQIhRAkLlRDGrhIgY3BJL8CVeKzuyXFzzjkn5ZxzzuScg3PO8cKzu70JkO0LfxdTU//pM9vTu7Xgf6KqOVTb9X7toRrVEfBf1HTVjZccrT/2by1VV928Yty9ZbVuucdz90frG8DBjl9pVApbOstvmMuvVgaNXSfAAd6pGxpy6yxf5ph43pS/4f3uoaGm2rdu72S9xzOvMymkZFq/ptDrk90mhW7e4zl7HLzhxGWPR20xmSxJ/VqldG5m9XhaVOA1DadsNh3Pu5L2N6QtPO/32JpqQBVVk20oy/Pi2s23WEvyfHbe1thadVQttvm7Llf65gGmXK67XtupyoM7HQhmXdLS8oGWJNeOJ3C5fG5XCEJnkez3/oFdsvgJ4l2ANZwhrJKk/7OSXa+3Vw2WJMlKnGkobouYk6T0TyX30klOUnTD9HJ5qpckL3EW/w4XF3Xd0FGywXUrstrclVsqz5Pd/sXFYyDnPdrLcQODmGOK47IZb4CmibmMn+MYRzFZ5jg33ZL/EJrWcszHmANy3ARBK/IXtciJy8VsitPSdE3uuHxzougojcUdr8/32atnz/ev3f/K5wtpxUTpcaI45zusVDpYtZi+jg0oU9b3x74h7+n9ABvYEZeKaVq0sh0AtLKsFtqNBdeT0MrSzwwlq9+x6xAO4tgOtSzbCjrNQQiNvQUbUEubvzBUeGw26yDCsRHCoLkTHDa7IdOLIThs/gHvChszh2CimE8peRs47cxANI0lYNB5y1DljpOF0IhzBDPOZnDOqYYbeGKECbPzWnXludPphw5c2YBq5zlwXphIbO4VDCZ0gnPfUO1TwZoYwAs2ExPCedAu9DAjfQUjzITQb3jNj0KG2Sgt6BHaQUdYzWz+XmBktOHwanXjaSTcwwziBcuMOtwBmqPrTOxFQR/DRKKPqyur0aiW6cULYsx6tBm0jXpR/AUWR6HRq9WVW6MRhIq5jLyjbaCTDCijyYJNpCajdyobP/eTw0iexBAKkJ3gA5KcQb2zBXsIBckn+xVv8jkZSaEFHE+jFEleAEfayRU0MouNoBmB/L50Ai/HSLIHxcrpCvnhSQAuakKp2C/YbCylJjXRVy/z3+Kv/RrNcCo+WUzlVEhzKffnTQnxeN9fWF88fiNCUdSTsaufaChKWInHeysygfpIqagoakW+vV20J8uyl6TyNKEZWV4oRSPyCkWpgOLSbkCObT8o2r6tlG58HQquf6O0v50tB7JM7F4EORd2dx/K0w/KHsVkLPaoYrwgP/y7krr3SSMA4zj+OBgmjYkxcdIJQyQRKgg2viX9Hddi9UBb29LrKR7CVVEEEXWojUkXNyfTNDE14W9gbHJNuhjDettN3ZvbOvdOqCD3Jp/9l+/wJE+9PkYGjx/fqkys3S2rMozM/o2106rfMUINo6hVqz+eu/hd1c4xTg0TAfy5kV+4UG6+IthHTU9woWmxuKNbTfuCSfovBCxq7EtHqvYL4Sm6F8GVxsSXHMQ07TOi1DKtZxjWaaIyi4CXWjxPccUw8WVbMYY5wxC1mzEyXMJWkllpRloi+Kkoq69sxBTlElF6aAxYUbjXNlhlDZilDnM4U5SlN5biRsRHnbx3mbeWjEh4mEyiuJDl5XcWVmX5GvNkFgLWZM5qwsop4/AWfLhU1cR7k1VVvcYCWRkOI6Xy5gmnphCYIkvzuNYzHzosq2oNk2RtSs8khfUOfHIDgR6ysYBaMpl4uEgk2U/oJTs9AaTSwma7dT69geAE2ZpEjUsn2ieJNHeKfrI3EcAGJ2ZaNgVuC8EBctCLc57P5u5led6IOBkIYkuQMrmmjChs4VkfOerHqSBkPzZlhe06RslZ3zMjk2sscqKwY0RcjKK+LWbzd7KiHhkncs/siFJ+V5eXxD34B8nVuJEpGJNmxN2gH3vSvp7J70tF+D1Ej8qUJD1TkErAND2GZwTFg/LubvmgiBG3SOvdlsqFQrkEzJCL1rstlnVFROixZoDDSuXQFHESwVGlcuQcMb/b42NgjLowh5MTDFE3vNB5qStRIErdCQEh6pLPR92anSUb/wAIhldAaDMpGgAAAABJRU5ErkJggg==\"/>"; addMarker("Dongzhi Gate", new LatLng(39.941823, 116.426319), 3, image, 25, 41); map.animateCenterZoom(wfcLatLng, 11); // Add Polylines LatLng[] latLngs = { new LatLng(39.918786, 116.459273), new LatLng(39.923823, 116.433666), new LatLng(39.919635, 116.448831) }; map.addPolyline(new AirMapPolyline(Arrays.asList(latLngs), 5)); LatLng[] polygonLatLngs = { new LatLng(39.902896, 116.42792), new LatLng(39.902896, 116.43892), new LatLng(39.913896, 116.43892), new LatLng(39.913896, 116.42792) }; map.addPolygon(new AirMapPolygon.Builder().add(polygonLatLngs).strokeWidth(3.f).build()); // Add Circle map.drawCircle(new LatLng(39.919635, 116.448831), 1000); } else { final LatLng airbnbLatLng = new LatLng(37.771883, -122.405224); addMarker("Airbnb HQ", airbnbLatLng, 1); addMarker("Performance Bikes", new LatLng(37.773975, -122.40205), 2); addMarker("REI", new LatLng(37.772127, -122.404411), 3); addMarker("Mapbox", new LatLng(37.77572, -122.41354), 4); map.animateCenterZoom(airbnbLatLng, 10); // Add Polylines LatLng[] latLngs = { new LatLng(37.77977, -122.38937), new LatLng(37.77811, -122.39160), new LatLng(37.77787, -122.38864) }; map.addPolyline(new AirMapPolyline(Arrays.asList(latLngs), 5)); // Add Polygons LatLng[] polygonLatLngs = { new LatLng(37.784, -122.405), new LatLng(37.784, -122.406), new LatLng(37.785, -122.406), new LatLng(37.785, -122.405) }; map.addPolygon(new AirMapPolygon.Builder().add(polygonLatLngs).strokeWidth(3.f).build()); // Add Circle map.drawCircle(new LatLng(37.78443, -122.40805), 1000); // enable my location map.setMyLocationEnabled(false); } } private void addMarker(String title, LatLng latLng, int id) { addMarker(title, latLng, id, null, 0, 0); } private void addMarker(String title, LatLng latLng, int id, String divIconHtml, int iconWidth, int iconHeight) { map.addMarker(new AirMapMarker.Builder() .id(id) .position(latLng) .title(title) .iconId(R.mipmap.icon_location_pin) .divIconHtml(divIconHtml) .divIconWidth(iconWidth) .divIconHeight(iconHeight) .build()); } @Override public void onMapClick(LatLng latLng) { if (latLng != null) { appendLog( "Map onMapClick triggered with lat: " + latLng.latitude + ", lng: " + latLng.longitude); map.getMapInterface().getScreenLocation(latLng, this); } else { appendLog("Map onMapClick triggered with null latLng"); } } @Override public void onCameraMove() { appendLog("Map onCameraMove triggered"); } private void appendLog(String msg) { adapter.addString(msg); logsRecyclerView.smoothScrollToPosition(adapter.getItemCount() - 1); } private void appendBitmap(Bitmap bitmap) { adapter.addBitmap(bitmap); logsRecyclerView.smoothScrollToPosition(adapter.getItemCount() - 1); } @Override public boolean onMapMarkerClick(AirMapMarker<?> airMarker) { appendLog("Map onMapMarkerClick triggered with id " + airMarker.getId()); return false; } @Override public void onInfoWindowClick(AirMapMarker<?> airMarker) { appendLog("Map onInfoWindowClick triggered with id " + airMarker.getId()); } @Override public void onLatLngScreenLocationReady(Point point) { appendLog("LatLng location on screen (x,y): (" + point.x + "," + point.y + ")"); } }