Search code examples
javaandroidgoogle-mapsgoogle-polylineon-location-changed

How to add line which shows route you passed on Google Map


I'm quite new in Android and I need a help. I'm developing an app like Runkeeper, Nike Running Club etc. So I want to know how to add line which shows route you passed on Google Map.Like that. I have already tried many methods from here, here and here , but I can't understand them. I know that I have to use onLocationChanged drawpolyline, but I don't know how and I can't find anywhere explanation of it.

Here is how I was trying to do it, but it always crashes

GoogleApiClient mGoogleApiClient;
LocationRequest mLocationRequest;
TextView textAutoUpdateLocation;

private static final String FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;
private static final String COARSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION;
private Boolean mLocationPermissionGranted = false;
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1234;
private GoogleMap mMap;
private FusedLocationProviderClient mFusedLocationProviderClient;
private static final float DEFAULT_ZOOM = 15f;
private PolylineOptions polylineOptions;
private ArrayList<LatLng> arrayPoints;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textAutoUpdateLocation = (TextView) findViewById(R.id.autoupdatelocation);

    mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(5000);
    mLocationRequest.setFastestInterval(5000);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
    getLocationPermission();
}

private void initMap() {
    SupportMapFragment mapFragment =
            (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
    mapFragment.getMapAsync((OnMapReadyCallback) this);
}

private void getDeviceLocation() {
    mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
    try {
        if (mLocationPermissionGranted) {
            final Task location = mFusedLocationProviderClient.getLastLocation();
            location.addOnCompleteListener(new OnCompleteListener() {
                @Override
                public void onComplete(@NonNull Task task) {
                    if (task.isSuccessful()) {
                        Location currentLocation = (Location) task.getResult();
                        moveCamera(new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude()), DEFAULT_ZOOM);
                    } else {
                    }
                }

            });
        }
    } catch (SecurityException e) {

    }
}

private void moveCamera(LatLng latLng, float zoom) {
    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, zoom));
}



@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    if (mLocationPermissionGranted) {
        getDeviceLocation();
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        mMap.setMyLocationEnabled(true);


    }
    this.init();
}
private void init() {

    String coordinates[] = { "37.517180", "127.041268" };
    double lat = Double.parseDouble(coordinates[0]);
    double lng = Double.parseDouble(coordinates[1]);

    LatLng position = new LatLng(lat, lng);
    GooglePlayServicesUtil.isGooglePlayServicesAvailable(
            MainActivity.this);

    // 맵 위치이동.
    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(position, 15));


}








private void getLocationPermission() {
    String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};

    if (ContextCompat.checkSelfPermission(this.getApplicationContext(), FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
        if (ContextCompat.checkSelfPermission(this.getApplicationContext(), COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            mLocationPermissionGranted = true;
            initMap();
        } else {
            ActivityCompat.requestPermissions(this, permissions, LOCATION_PERMISSION_REQUEST_CODE);
        }

    } else {
        ActivityCompat.requestPermissions(this, permissions, LOCATION_PERMISSION_REQUEST_CODE);
    }
}


public void RequestPermissionResult(int requestCode, @NonNull String[]permissions, @NonNull int[]grantResults) {
    switch (requestCode){
        case LOCATION_PERMISSION_REQUEST_CODE:{
            if (grantResults.length > 0) {
                for (int i = 0; i<grantResults.length;i++){
                    if(grantResults[i] != PackageManager.PERMISSION_GRANTED){
                        mLocationPermissionGranted=false;
                        return;
                    }
                }
                mLocationPermissionGranted=true;
                initMap();
            }
        }
    }
}
@Override
protected void onStart() {
    mGoogleApiClient.connect();
    super.onStart();
}

@Override
protected void onStop() {
    mGoogleApiClient.disconnect();
    super.onStop();
}

@Override
public void onLocationChanged(Location location) {
    if (location != null) {

        LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
        MarkerOptions marker = new MarkerOptions();
        marker.position(latLng);
        mMap.addMarker(marker);


        polylineOptions = new PolylineOptions();
        polylineOptions.color(Color.RED);
        polylineOptions.width(5);
        arrayPoints.add(latLng);
        polylineOptions.addAll(arrayPoints);
        mMap.addPolyline(polylineOptions);
    }
}

@Override
public void onConnected(@Nullable Bundle bundle) {

    if (ActivityCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_COARSE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
        // TODO: Consider calling
        //    ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.
        ActivityCompat.requestPermissions(MainActivity.this,
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                LOCATION_PERMISSION_REQUEST_CODE);

        return;
    }
    LocationServices.FusedLocationApi.requestLocationUpdates(
            mGoogleApiClient, mLocationRequest, this);

}



@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    Toast.makeText(MainActivity.this,
            "onConnectionFailed: \n" + connectionResult.toString(),
            Toast.LENGTH_LONG).show();
}

}

Please help and explain it to me. Thanks beforehand.

LOGCAT 08-03 13:51:02.605 20065-20065/? E/Zygote: isWhitelistProcess - Process is Whitelisted 08-03 13:51:03.125 20065-20065/com.mcarrow.myapplication E/zygote64: The String#value field is not present on Android versions >= 6.0 08-03 13:51:03.810 20065-20065/com.mcarrow.myapplication E/AndroidRuntime: FATAL EXCEPTION: main Process: com.mcarrow.myapplication, PID: 20065 java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.util.ArrayList.add(java.lang.Object)' on a null object reference at com.mcarrow.myapplication.MainActivity.onLocationChanged(MainActivity.java:209) at com.google.android.gms.internal.location.zzay.notifyListener(Unknown Source:4) at com.google.android.gms.common.api.internal.ListenerHolder.notifyListenerInternal(Unknown Source:8) at com.google.android.gms.common.api.internal.ListenerHolder$zza.handleMessage(Unknown Source:16) at android.os.Handler.dispatchMessage(Handler.java:105) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6938) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)


Solution

  • You have NOT initialized arrayPoints. In your code, change arrayPoints declaration to this

    private ArrayList<LatLng> arrayPoints; = new ArrayList<LatLng>();