Skip to main content

Draw Polyline on GoogleMap of Google Maps Android API v2

This exercise will help to draw a line on Google map between two or more co-ordinates.

Like in an Screenshot below.

Let's see how to do this:

Important-
Generate SHA1 certificate for your Google map from google developer account from below link-
https://code.google.com/apis/

Add the dependency:
implementation 'com.google.android.gms:play-services:8.3.0'

1. activity_main.xml
<fragment
        android:id="@+id/map"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:name="com.google.android.gms.maps.SupportMapFragment" />

2. MainAction.java
public class MainAction extends AppCompatActivity
        implements OnMapReadyCallback,
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        LocationListener {

    GoogleMap mGoogleMap;
    SupportMapFragment mapFrag;
    LocationRequest mLocationRequest;
    GoogleApiClient mGoogleApiClient;
    Location mLastLocation;
    Marker mCurrLocationMarker;
    Context context;
    String strAddress, strSetAddress;
    Double latitude = 8.174, longitude = 77.434;
    LatLng latlngNew;

    Polyline polyline=null;
    ArrayList directionList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initComp();

    }

    private void initComp() {
        context = this;
        mapFrag = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFrag.getMapAsync(this);

        directionList = new ArrayList();
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mGoogleMap = googleMap;
        mGoogleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
        mGoogleMap.getUiSettings().setMyLocationButtonEnabled(false);

        //Initialize Google Play Services
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(this,
                    Manifest.permission.ACCESS_FINE_LOCATION)
                    == PackageManager.PERMISSION_GRANTED) {
                //Location Permission already granted
                buildGoogleApiClient();
                mGoogleMap.setMyLocationEnabled(true);
            } else {
                //Request Location Permission
                checkLocationPermission();
            }
        } else {
            buildGoogleApiClient();
            mGoogleMap.setMyLocationEnabled(true);
        }
    }

    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        mGoogleApiClient.connect();
    }

    @Override
    public void onConnected(Bundle bundle) {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(1000);
        mLocationRequest.setFastestInterval(1000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
    }

    @Override
    public void onLocationChanged(Location location) {

        if (mCurrLocationMarker != null) {
            mCurrLocationMarker.remove();
        }

        if(location!=null){
            mLastLocation = location;
            strAddress = getAddress(context, location.getLatitude(), location.getLongitude());
            strSetAddress = strAddress;
        }else{
            strAddress = getAddress(context, mLastLocation.getLatitude(), mLastLocation.getLongitude());
            strSetAddress = strAddress;
        }

        //Place current location marker
        LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
        directionList.add(latLng);
        /*for second point*/
        latlngNew = new LatLng(latitude, longitude);
        MarkerOptions markerOptionx = new MarkerOptions();
        markerOptionx.position(latlngNew);
        mGoogleMap.addMarker(markerOptionx);
        directionList.add(latlngNew);
        //end//
        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(latLng);

        mCurrLocationMarker = mGoogleMap.addMarker(markerOptions);

        /*call_draw_fn*/
        drawRouteOnMap(mGoogleMap, directionList);

        //move map camera
        mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15.0f));
    }

    private void drawRouteOnMap(GoogleMap map, List<LatLng> positions){
        PolylineOptions options = new PolylineOptions().width(5).color(Color.BLUE).geodesic(true);
        options.addAll(positions);

        if(polyline!=null){
            polyline.remove();
            polyline = map.addPolyline(options);
        }else{
            polyline = map.addPolyline(options);
        }
        CameraPosition cameraPosition = new CameraPosition.Builder()
                .target(new LatLng(positions.get(1).latitude, positions.get(1).longitude))
                .zoom(17)
                .build();
        map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
    }

    public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;

    private void checkLocationPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {

            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.ACCESS_FINE_LOCATION)) {

                // Show an explanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.
                new AlertDialog.Builder(this)
                        .setTitle("Location Permission Needed")
                        .setMessage("This app needs the Location permission, please accept to use location functionality")
                        .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                //Prompt the user once explanation has been shown
                                ActivityCompat.requestPermissions(MainAction.this,
                                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                                        MY_PERMISSIONS_REQUEST_LOCATION);
                            }
                        })
                        .create()
                        .show();

            } else {
                // No explanation needed, we can request the permission.
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_REQUEST_LOCATION);
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_LOCATION: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    // permission was granted, yay! Do the
                    // location-related task you need to do.
                    if (ContextCompat.checkSelfPermission(this,
                            Manifest.permission.ACCESS_FINE_LOCATION)
                            == PackageManager.PERMISSION_GRANTED) {

                        if (mGoogleApiClient == null) {
                            buildGoogleApiClient();
                        }
                        mGoogleMap.setMyLocationEnabled(true);
                    }
                } else {
                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                    Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
                }
                return;
            }
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        //stop location updates when Activity is no longer active
        if (mGoogleApiClient != null) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
        }
    }

}

Add the function getAddress() from util class
public static String getAddress(Context context, double latitude, double longitude) {
        String addressx = "";
        try {
            Geocoder geocoder = new Geocoder(context, Locale.getDefault());
            List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
            if (addresses != null && addresses.size() > 0) {

                String address = addresses.get(0).getAddressLine(0); // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex()
                addressx = address;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return addressx;

    }


_________________________________________________________________________________

Happy Coding

Comments

Popular posts from this blog

Zoom Image - Android Tutorial

Here we are going to see how to zoom an image in Imageview Will see it through a sample 1. Create xml with an ImageView <? xml version="1.0" encoding="utf-8" ?> < androidx.constraintlayout.widget.ConstraintLayout       xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="match_parent"     android:layout_height="match_parent"     tools:context=".MainActivity" >     < LinearLayout         android:layout_width="200dp"         android:layout_height="200dp"         app:layout_constraintBottom_toBottomOf="parent"         app:layout_constraintLeft_toLeftOf="parent"         app:layout_constraintRight_toRightOf="parent"    ...

Spinner with Search on DropDown - Android Tutorial

If you have more values on Dropdown of Spinner its hard to select the last item by making a long scroll. To overcome this issue Android introduced a component called  AutoCompleteTextView Yes it is!!! Then why Spinner with Search? There may be some requirement even though gave much knowledge about it. There is a simple and good library that helps us to achieve this -  SearchableSpinner Gradle dependencies {     ...     implementation 'com.toptoche.searchablespinner:searchablespinnerlibrary:1.3.1' } Usage Now replace your Normal Android Spinner on XML with the following < com.toptoche.searchablespinnerlibrary.SearchableSpinner     android:id="@+id/id_city"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:background="@android:color/transparent"     android:padding="5dp" /> ______________________________________...

Bluetooth Chat Application - Android Tutorial

In this tutorial, we will see about how to design an Android layout for chat application using Chat Bubbles  and the main part is chat via Bluetooth . Main objective of this post is to give an idea about how to allow two-way text chat over Bluetooth in android. Bubbles: Chat bubbles are background image that expands horizontally and vertically as required based on the message posted. Bubbles are Nine-patch Images. Image Nine-patch Image In creating Android chat bubbles, nine-patch image plays a crucial role.  Nine-patch image  is a bitmap which stretches to fit the content posted in the View where it is applied as a background. A NinePatch drawable is a standard PNG image that includes an extra 1-pixel-wide border. It must be saved with the extension  .9.png , and saved into the  res/drawable/  directory of your project. The border is used to define the stretchable and static areas of the image. You indicate a stretchable section ...