web-dev-qa-db-de.com

Wie Freihand-Polygon in Google Map V2 in Android zu zeichnen?

Ich möchte einen Free Hand Polygon on the Map in Google Map V2 Zeichnen.

Diese Aufgabe war mit Overlay Map V1 möglich, aber Google Map hat diese Klasse aus V2 entfernt. (In diesem Fall Google Map V2 hat die Überlagerungsklasse "Entfernen" ).

Gutes Beispiel für Google Map V1 zum Zeichnen von Freestyle-Polygonen.

In Map V2 können wir mit Hilfe von Google Official Doc ein Polygon programmgesteuert zeichnen. Aber was soll ein Benutzer tun? Ich habe nklare Antwort für Map V2 gefunden

Ich habe mit einfachem Google Map & Draw Polygon angefangen, um dies programmgesteuert zu tun und es funktioniert einwandfrei, aber jetzt suche ich, wie ein Benutzer zeichnen kann? Ich möchte nicht anhand der Markierung auf dem Polygon zeichnen.

// Instantiates a new Polygon object and adds points to define a rectangle
PolygonOptions rectOptions = new PolygonOptions()
              .add(new LatLng(37.35, -122.0),
                   new LatLng(37.45, -122.0),
                   new LatLng(37.45, -122.2),
                   new LatLng(37.35, -122.2),
                   new LatLng(37.35, -122.0));

// Get back the mutable Polygon
Polygon polygon = myMap.addPolygon(rectOptions);

Ich habe viel zu diesem Thema geforscht und entwickelt, aber es gelang mir nicht, so etwas in Map V2 zu implementieren.

Einige Fragen

  • Wie zeichnet man ein Freestyle-Polygon in Map V2 (wie wir es mit Map V1 machen können)?
  • Gibt es einen Trick oder eine Alternative, um dies zu erreichen? Wenn ja wie?
  • Können wir ein Berührungsereignis auf der Karte erhalten und ein Polygon zeichnen?
  • Ist es in Map V2 machbar?
  • Ist es mit einem Berührungsereignis möglich, das eine Reihe von lat-long zurückgibt?
  • Wie kann ich anhand der Bildschirmkoordinaten für setOnDragListener Lat-Long ermitteln?

Jede neue Version hat etwas mehr als die ältere Version, daher erwarte ich, dass ich dasselbe auch in Map v2 erreichen kann.

Ich bitte Sie nicht, mir einen Beispielcode zu geben oder Ihren Code zu posten, sondern nur eine angemessene Anleitung und Dokumentation.

Ich habe alle Dokumente und Nachweise geliefert, die ich während der Forschung und Entwicklung gefunden habe.

53
Chintan Khetiya

Nachdem ich einen ganzen Tag in Rnd verbracht und einige Alternativen getestet habe, habe ich eine Lösung gefunden. Eigentlich habe ich zwei Alternativen für das gleiche Problem gefunden, aber ich möchte die Verwendung von Alternative 2 vorschlagen, da dies im Vergleich zu sehr einfach ist Alternative 1 .

Eigentlich habe ich Alternative 1 mit Hilfe von TheLittleNaruto , AndroidHacker und einigen gefunden andere Entwickler & Alternative 2 mit Hilfe von Khan also danke an alle.

Alternative 1

Wie zeichnet man ein Freestyle-Polygon in Map V2 (wie wir es mit Map V1 machen können)? Ist es in Map V2 machbar?

Ja, das ist machbar, aber Sie können OnTouch() & OnDraw() nicht direkt auf der Karte anzeigen. Wir müssen uns also einen anderen Weg überlegen, um dies zu erreichen.

Gibt es einen Trick oder alternativen Weg, um dieses Ziel zu erreichen, wenn ja wie?

Ja, Google Map V2 unterstützt OnTouch() oder OnDraw() auf einer Karte mit class="com.google.Android.gms.maps.SupportMapFragment" Nicht, daher müssen wir ein benutzerdefiniertes Fragment planen.

Ist es möglich, Array von Lat-Long mit Touch-Ereignis zurückzugeben?

Ja, wenn wir ein benutzerdefiniertes Kartenfragment erstellen und es verwenden, können wir das Touch oder Drag -Ereignis über die Karte ziehen.

Wie kann ich die Lat-Long-Basis für Bildschirmkoordinaten in setOnDragListener ermitteln?

setOnDragListener gibt die Bildschirmkoordinaten (x, y) zurück. Hierfür gibt es einige Techniken, um (x, y) in LatLng umzuwandeln, und sie umfassen Projektion zusammen mit Point & LatLng .

customMapFragment.setOnDragListener(new MapWrapperLayout.OnDragListener() {@Override
    public void onDrag(MotionEvent motionEvent) {
        Log.i("ON_DRAG", "X:" + String.valueOf(motionEvent.getX()));
        Log.i("ON_DRAG", "Y:" + String.valueOf(motionEvent.getY()));

        float x = motionEvent.getX(); // get screen x position or coordinate 
        float y = motionEvent.getY();  // get screen y position or coordinate 

        int x_co = Integer.parseInt(String.valueOf(Math.round(x))); // casting float to int 
        int y_co = Integer.parseInt(String.valueOf(Math.round(y))); // casting float to int 

        projection = mMap.getProjection(); // Will convert your x,y to LatLng
        Point x_y_points = new Point(x_co, y_co);// accept int x,y value
        LatLng latLng = mMap.getProjection().fromScreenLocation(x_y_points); // convert x,y to LatLng
        latitude = latLng.latitude; // your latitude 
        longitude = latLng.longitude; // your longitude 

        Log.i("ON_DRAG", "lat:" + latitude);
        Log.i("ON_DRAG", "long:" + longitude);

        // Handle motion event:
    }
});

Wie funktioniert es ?

Wie ich bereits erwähnt habe, müssen wir eine benutzerdefinierte Root-Ansicht erstellen und mit dieser können wir Touch oder Ziehe Events über die Karte.

Schritt 1: Wir erstellen MySupportMapFragment extends SupportMapFragment Und verwenden dies als XML-Datei

 <fragment
        Android:id="@+id/map"
        Android:layout_width="fill_parent"
        Android:layout_height="fill_parent"
        class="pkg_name.MySupportMapFragment" /> 

Schritt 2: Erstellen Sie einen MapWrapperLayout extends FrameLayout, So dass Sie einen Touch- oder Drag-Listener in die Ansicht einfügen und diese mit der Kartenansicht einbetten können. Wir brauchen also ein Interface, das wir in Root_Map.Java verwenden werden

MySupportMapFragment.Java

public class MySupportMapFragment extends SupportMapFragment {
    public View mOriginalContentView;
    public MapWrapperLayout mMapWrapperLayout;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {

        mOriginalContentView = super.onCreateView(inflater, parent, savedInstanceState);
        mMapWrapperLayout = new MapWrapperLayout(getActivity());
        mMapWrapperLayout.addView(mOriginalContentView);
        return mMapWrapperLayout;
    }

    @Override
    public View getView() {
        return mOriginalContentView;
    }

    public void setOnDragListener(MapWrapperLayout.OnDragListener onDragListener) {
        mMapWrapperLayout.setOnDragListener(onDragListener);
    }
}

MapWrapperLayout.Java

    public class MapWrapperLayout extends FrameLayout {
     private OnDragListener mOnDragListener;

     public MapWrapperLayout(Context context) {
         super(context);
     }

     public interface OnDragListener {
         public void onDrag(MotionEvent motionEvent);
     }

     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
         if (mOnDragListener != null) {
             mOnDragListener.onDrag(ev);
         }
         return super.dispatchTouchEvent(ev);
     }

     public void setOnDragListener(OnDragListener mOnDragListener) {
         this.mOnDragListener = mOnDragListener;
     }

 }

Root_Map.Java

public class Root_Map extends FragmentActivity {

    private GoogleMap mMap;
    public static boolean mMapIsTouched = false;
    MySupportMapFragment customMapFragment;
    Projection projection;
    public double latitude;
    public double longitude;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.root_map);
        MySupportMapFragment customMapFragment = ((MySupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map));
        mMap = customMapFragment.getMap();

        customMapFragment.setOnDragListener(new MapWrapperLayout.OnDragListener() {               @Override
            public void onDrag(MotionEvent motionEvent) {
                Log.i("ON_DRAG", "X:" + String.valueOf(motionEvent.getX()));
                Log.i("ON_DRAG", "Y:" + String.valueOf(motionEvent.getY()));

                float x = motionEvent.getX();
                float y = motionEvent.getY();

                int x_co = Integer.parseInt(String.valueOf(Math.round(x)));
                int y_co = Integer.parseInt(String.valueOf(Math.round(y)));

                projection = mMap.getProjection();
                Point x_y_points = new Point(x_co, y_co);
                LatLng latLng = mMap.getProjection().fromScreenLocation(x_y_points);
                latitude = latLng.latitude;
                longitude = latLng.longitude;

                Log.i("ON_DRAG", "lat:" + latitude);
                Log.i("ON_DRAG", "long:" + longitude);

                // Handle motion event:
            }
        });
    }}

Referenz Link1 , Link2

Bis hierher kann ich LatLong basierend auf X, Y Bildschirmkoordinaten erhalten. Jetzt muss ich es nur noch in Array speichern. Dieses Array wird zum Zeichnen auf der Karte verwendet und sieht schließlich aus wie ein Polygon mit freier Form.

enter image description here

Ich hoffe das wird dir definitiv helfen.

Aktualisieren:

Alternative 2

Wie wir wissen, ist Rahmenlayout ein transparentes Layout, daher habe ich dies mit Rahmenlayout erreicht. In diesem Fall muss kein benutzerdefiniertes Fragment erstellt werden. Ich habe gerade Frame-Layout als Root-Layout verwendet. Im Grunde bekomme ich Touch Events im Root-Layout und das gibt die Bildschirmkoordinaten zurück, wie wir sie zuvor in einem benutzerdefinierten Fragment erhalten haben.

Jetzt habe ich einen Button im "Free Draw" erstellt. Wenn Sie darauf klicken, können Sie Ihre Finger auf der Karte bewegen und ein Freihandpolygon zeichnen. Dadurch wird Ihre Karte auf dem Bildschirm nicht mehr beweglich. Wenn Sie erneut auf dieselbe Schaltfläche klicken, wechselt der Bildschirm in den idealen Modus.

root_map.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent" >

    <fragment
        Android:id="@+id/map"
        Android:layout_width="fill_parent"
        Android:layout_height="fill_parent"
        class="com.google.Android.gms.maps.SupportMapFragment" />

    <FrameLayout
        Android:id="@+id/fram_map"
        Android:layout_width="fill_parent"
        Android:layout_height="fill_parent" >

        <Button
            Android:id="@+id/btn_draw_State"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:text="Free Draw" />
    </FrameLayout>

</FrameLayout>

Root_Map.Java

FrameLayout fram_map = (FrameLayout) findViewById(R.id.fram_map);
Button btn_draw_State = (Button) findViewById(R.id.btn_draw_State);
Boolean Is_MAP_Moveable = false; // to detect map is movable 

// Button ändert den Status der Karte

btn_draw_State.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Is_MAP_Moveable = !Is_MAP_Moveable;
    }
});

Tippen Sie auf Click of Frame Layout und führen Sie mithilfe von eine Aufgabe aus

fram_map.setOnTouchListener(new View.OnTouchListener() {     @Override
    public boolean onTouch(View v, MotionEvent event) {
        float x = event.getX();
        float y = event.getY();

        int x_co = Math.round(x);
        int y_co = Math.round(y);

        projection = mMap.getProjection();
        Point x_y_points = new Point(x_co, y_co);

        LatLng latLng = mMap.getProjection().fromScreenLocation(x_y_points);
        latitude = latLng.latitude;

        longitude = latLng.longitude;

        int eventaction = event.getAction();
        switch (eventaction) {
            case MotionEvent.ACTION_DOWN:
                // finger touches the screen
                val.add(new LatLng(latitude, longitude));

            case MotionEvent.ACTION_MOVE:
                // finger moves on the screen
                val.add(new LatLng(latitude, longitude));

            case MotionEvent.ACTION_UP:
                // finger leaves the screen
                Draw_Map();
                break;
        }

        return Is_MAP_Moveable;

    }
});

// Zeichne deine Karte

public void Draw_Map() {
    rectOptions = new PolygonOptions();
    rectOptions.addAll(val);
    rectOptions.strokeColor(Color.BLUE);
    rectOptions.strokeWidth(7);
    rectOptions.fillColor(Color.CYAN);
    polygon = mMap.addPolygon(rectOptions);
}

Jetzt müssen Sie jedoch Ihre Liste während des Zeichnens beibehalten, damit Sie Ihre vorherigen Listendaten löschen können.

73
Chintan Khetiya

Schauen Sie sich das an. Ich glaube, Sie können Google Map v2 anzeigen

Checken Sie die Methoden "decodePoly" und "drawPath" in AsyncTask aus

Hauptaugenmerk in "drawPath" ..

PolylineOptions options = new PolylineOptions().width(5).color(Color.BLUE).geodesic(true);
for (int z = 0; z < list.size(); z++) {
    LatLng point = list.get(z);
    options.add(point);
}
line = myMap.addPolyline(options);

Komplette Klasse für Ihre Referenz ..

package com.example.androidhackergooglemap;

import Java.io.BufferedReader;
import Java.io.IOException;
import Java.io.InputStream;
import Java.io.InputStreamReader;
import Java.io.UnsupportedEncodingException;
import Java.util.ArrayList;
import Java.util.List;

import org.Apache.http.HttpEntity;
import org.Apache.http.HttpResponse;
import org.Apache.http.client.ClientProtocolException;
import org.Apache.http.client.methods.HttpPost;
import org.Apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;

import com.google.Android.gms.maps.CameraUpdateFactory;
import com.google.Android.gms.maps.GoogleMap;
import com.google.Android.gms.maps.SupportMapFragment;
import com.google.Android.gms.maps.model.BitmapDescriptorFactory;
import com.google.Android.gms.maps.model.LatLng;
import com.google.Android.gms.maps.model.Marker;
import com.google.Android.gms.maps.model.MarkerOptions;
import com.google.Android.gms.maps.model.Polyline;
import com.google.Android.gms.maps.model.PolylineOptions;

import Android.app.ProgressDialog;
import Android.content.Context;
import Android.content.Intent;
import Android.graphics.Color;
import Android.location.Location;
import Android.location.LocationManager;
import Android.os.AsyncTask;
import Android.os.Bundle;
import Android.provider.Settings;
import Android.support.v4.app.FragmentActivity;
import Android.util.Log;
import Android.view.View;
import Android.view.View.OnClickListener;
import Android.widget.Toast;

public class MainActivity extends FragmentActivity implements OnClickListener {

    private GoogleMap myMap;
    Polyline line;
    Context context;

    Location location;
    boolean check_provider_enabled = false;

    // Static LatLng
    LatLng startLatLng = new LatLng(30.707104, 76.690749);
    LatLng endLatLng = new LatLng(30.721419, 76.730017);

    public void onCreate(Bundle bd) {
        super.onCreate(bd);
        setContentView(R.layout.activity_main);
        context = MainActivity.this;

        // GoogleMap myMap
        myMap = ((SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map)).getMap();
        myMap.setMyLocationEnabled(true);
        myMap.moveCamera(CameraUpdateFactory.newLatLng(startLatLng));
        myMap.animateCamera(CameraUpdateFactory.zoomTo(12));

        LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
        boolean enabled = service.isProviderEnabled(LocationManager.GPS_PROVIDER);
        location = service.getLastKnownLocation(LocationManager.GPS_PROVIDER);

        // check if enabled and if not send user to the GSP settings
        // Better solution would be to display a dialog and suggesting to 
        // go to the settings
        if (!enabled) {
            /*Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            startActivity(intent);*/
            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            startActivity(intent);
            Toast.makeText(getApplicationContext(), "Enable GPS servcies to use this app.", Toast.LENGTH_LONG).show();
        } else {
            try {
                String urlTopass = makeURL(startLatLng.latitude,
                    startLatLng.longitude, endLatLng.latitude,
                    endLatLng.longitude);
                new connectAsyncTask(urlTopass).execute();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // Now auto clicking the button
        // btntemp.performClick();
    }


    private class connectAsyncTask extends AsyncTask < Void, Void, String > {
        private ProgressDialog progressDialog;
        String url;

        connectAsyncTask(String urlPass) {
            url = urlPass;
        }

        @Override
        protected void onPreExecute() {
            // TODO Auto-generated method stub
            super.onPreExecute();
            progressDialog = new ProgressDialog(context);
            progressDialog.setMessage("Fetching route, Please wait...");
            progressDialog.setIndeterminate(true);
            progressDialog.show();
        }

        @Override
        protected String doInBackground(Void...params) {
            JSONParser jParser = new JSONParser();
            String json = jParser.getJSONFromUrl(url);
            return json;
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            progressDialog.hide();
            if (result != null) {
                drawPath(result);
            }
        }
    }

    public String makeURL(double sourcelat, double sourcelog, double destlat,
        double destlog) {
        StringBuilder urlString = new StringBuilder();
        urlString.append("http://maps.googleapis.com/maps/api/directions/json");
        urlString.append("?origin="); // from
        urlString.append(Double.toString(sourcelat));
        urlString.append(",");
        urlString.append(Double.toString(sourcelog));
        urlString.append("&destination="); // to
        urlString.append(Double.toString(destlat));
        urlString.append(",");
        urlString.append(Double.toString(destlog));
        urlString.append("&sensor=false&mode=driving&alternatives=true");
        return urlString.toString();
    }

    public class JSONParser {

        InputStream is = null;
        JSONObject jObj = null;
        String json = "";

        // constructor
        public JSONParser() {}

        public String getJSONFromUrl(String url) {

            // Making HTTP request
            try {
                // defaultHttpClient
                DefaultHttpClient httpClient = new DefaultHttpClient();
                HttpPost httpPost = new HttpPost(url);

                HttpResponse httpResponse = httpClient.execute(httpPost);
                HttpEntity httpEntity = httpResponse.getEntity();
                is = httpEntity.getContent();

            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                BufferedReader reader = new BufferedReader(
                    new InputStreamReader(is, "iso-8859-1"), 8);
                StringBuilder sb = new StringBuilder();
                String line = null;
                while ((line = reader.readLine()) != null) {
                    sb.append(line + "\n");
                }

                json = sb.toString();
                is.close();
            } catch (Exception e) {
                Log.e("Buffer Error", "Error converting result " + e.toString());
            }
            return json;
        }
    }

    public void drawPath(String result) {
        if (line != null) {
            myMap.clear();
        }
        myMap.addMarker(new MarkerOptions().position(endLatLng).icon(
            BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher)));
        myMap.addMarker(new MarkerOptions().position(startLatLng).icon(
            BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher)));
        try {
            // Tranform the string into a json object
            final JSONObject json = new JSONObject(result);
            JSONArray routeArray = json.getJSONArray("routes");
            JSONObject routes = routeArray.getJSONObject(0);
            JSONObject overviewPolylines = routes
                .getJSONObject("overview_polyline");
            String encodedString = overviewPolylines.getString("points");
            List < LatLng > list = decodePoly(encodedString);

            PolylineOptions options = new PolylineOptions().width(5).color(Color.BLUE).geodesic(true);
            for (int z = 0; z < list.size(); z++) {
                LatLng point = list.get(z);
                options.add(point);
            }
            line = myMap.addPolyline(options);

            /*for (int z = 0; z < list.size() - 1; z++) {
                LatLng src = list.get(z);
                LatLng dest = list.get(z + 1);
                line = myMap.addPolyline(new PolylineOptions()
                        .add(new LatLng(src.latitude, src.longitude),
                                new LatLng(dest.latitude, dest.longitude))
                        .width(5).color(Color.BLUE).geodesic(true));
            }*/

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private List < LatLng > decodePoly(String encoded) {

        List < LatLng > poly = new ArrayList < LatLng > ();
        int index = 0, len = encoded.length();
        int lat = 0, lng = 0;

        while (index < len) {
            int b, shift = 0, result = 0;
            do {
                b = encoded.charAt(index++) - 63;
                result |= (b & 0x1f) << shift;
                shift += 5;
            } while (b >= 0x20);
            int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
            lat += dlat;

            shift = 0;
            result = 0;
            do {
                b = encoded.charAt(index++) - 63;
                result |= (b & 0x1f) << shift;
                shift += 5;
            } while (b >= 0x20);
            int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
            lng += dlng;

            LatLng p = new LatLng((((double) lat / 1E5)),
                (((double) lng / 1E5)));
            poly.add(p);
        }

        return poly;
    }

    @Override
    public void onClick(View arg0) {
        // TODO Auto-generated method stub
    }
}

Ich hoffe es hilft. Prost!

[~ # ~] Update [~ # ~]

check out this .. Erstellen von OnDragListener für Google Map v2 Fragment

Aktivieren Sie auch dieses Kontrollkästchen. So zeichnen Sie eine Form auf das Kartenfragment, indem Sie es mit Google Map V2 berühren.

Einige weitere Hinweise .. Wie Bildschirmkoordinaten von Marker in Google Maps v2 Android erhalten

3
AndroidHacker

Wir haben also eine Lösung für das freie Zeichnen auf Karte v2. Implementiere GoogleMap.OnMarkerDragListener in Ihrer Kartenaktivität. Die Funktion onMarkerDrag wird überschrieben.

@Override
public void onMarkerDrag(Marker marker) {

   //add the marker's latlng in a arraylist of LatLng and pass it to the loop
    for (int i = 0; i < arraylistoflatlng.size(); i++) {
         myMap.addPolyline(new PolylineOptions()
        .addAll(arraylistoflatlng)
        .width(5)
        .color(Color.RED));
    }
    }

sie können eine Art Hack für freie Hand übergeben, sobald der Benutzer die Karte berührt, müssen Sie diese Koordinaten erkennen und an den onMarkerDrag übergeben. Sie müssen die Informationen des Bereichs für den weiteren Vorgang verwenden. Für Berührungsereignisse können Sie GoogleMap.OnMapClickListener und erhalte die Koordinaten von seinem Parameter. Hoffe das wird helfen :)

2
TheLittleNaruto

dies ist das Tutorial zu Google Maps API V2:

public class MapPane extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.map_activity);
        GoogleMap map = ((MapFragment) getFragmentManager()
                .findFragmentById(R.id.map)).getMap();

        map.moveCamera(CameraUpdateFactory.newLatLngZoom(
                new LatLng(-18.142, 178.431), 2));

        // Polylines are useful for marking paths and routes on the map.
        map.addPolyline(new PolylineOptions().geodesic(true)
                .add(new LatLng(-33.866, 151.195))  // Sydney
                .add(new LatLng(-18.142, 178.431))  // Fiji
                .add(new LatLng(21.291, -157.821))  // Hawaii
                .add(new LatLng(37.423, -122.091))  // Mountain View
        );
    }
}

link: https://developers.google.com/maps/documentation/Android/

1
Nguyen Thanh An