content: 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/STNuFzUwFIwxKaejILpIBEV9wAABhVJREFUeF6s1NdyFEcY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\"/>";
        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 + ")");
    }
  }
  