0

I am using Java client library for Google Maps API Web Services to draw routes between two points. it works fine on Android Studio's Emulator but crashes on Blue Stack and my Smartphone.

I have created Maps Activity from project Templates, only edited AppGradle and MapsActivity. App works fine as intended but only on Android Studio's emulator.

Here is the working image in Android Studio Emulator(Android 10) enter image description here

So app crashes at this line(what i found so far) : -- directions.destination(destination).setCallback(new PendingResult.Callback() {

Here is my MapsActivity:

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

private static final String TAG = "TaG";
private GoogleMap mMap;
static final int REQUEST_LOCATION_PERMISSION = 99;
double mUserlatitude, mUserlongitude;
ArrayList<PolylineData> mPolyLinesData = new ArrayList<>();
Marker marker =null;
GeoApiContext mGeoApiContext;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);
    mGeoApiContext = new GeoApiContext.Builder().apiKey("google_maps_api_key").build();
    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
}


/**
 * Manipulates the map once available.
 * This callback is triggered when the map is ready to be used.
 * This is where we can add markers or lines, add listeners or move the camera. In this case,
 * we just add a marker near Sydney, Australia.
 * If Google Play services is not installed on the device, the user will be prompted to install
 * it inside the SupportMapFragment. This method will only be triggered once the user has
 * installed Google Play services and returned to the app.
 */
@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    enableMyLocation();

    mMap.getUiSettings().setZoomControlsEnabled(true);

    // Add a marker in Sydney and move the camera
    LatLng sydney = new LatLng(31.522738, 74.358556);
    marker = mMap.addMarker(new MarkerOptions().position(sydney));
    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 12));

    mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
        @Override
        public boolean onMarkerClick(Marker marker) {
            LatLng start = new LatLng(mUserlatitude,mUserlongitude);
            calculateDirections(start,marker);
            return false;
        }
    });

}

private void enableMyLocation() {
    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_FINE_LOCATION)
            == PackageManager.PERMISSION_GRANTED) {
        mMap.setMyLocationEnabled(true);
        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 0, locationListener);
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5000, 0, locationListener);
    } else {
        ActivityCompat.requestPermissions(this, new String[]
                        {Manifest.permission.ACCESS_FINE_LOCATION},
                REQUEST_LOCATION_PERMISSION);
    }
}



@Override
public void onRequestPermissionsResult(int requestCode,
                                       @NonNull String[] permissions,
                                       @NonNull int[] grantResults) {
    // Check if location permissions are granted and if so enable the
    // location data layer.
    switch (requestCode) {
        case REQUEST_LOCATION_PERMISSION:
            if (grantResults.length > 0
                    && grantResults[0]
                    == PackageManager.PERMISSION_GRANTED) {
                enableMyLocation();

            }else{
                enableMyLocation();
            }
            break;
    }
}

LocationListener locationListener = new LocationListener() {
    @Override
    public void onLocationChanged(Location location) {
        mUserlatitude = location.getLatitude();
        mUserlongitude = location.getLongitude();
        //Toast.makeText(MapsActivity.this, Double.toString(mUserlatitude), Toast.LENGTH_SHORT).show();
        //Toast.makeText(MapsActivity.this, marker.getPosition().toString(), Toast.LENGTH_SHORT).show();
    }
    @Override
    public void onStatusChanged(String s, int i, Bundle bundle) {
    }
    @Override
    public void onProviderEnabled(String s) {
    }
    @Override
    public void onProviderDisabled(String s) {
    }
};



private void calculateDirections(LatLng start, Marker marker){
    Log.d(TAG, "calculateDirections: calculating directions.");

    com.google.maps.model.LatLng destination = new com.google.maps.model.LatLng(
            marker.getPosition().latitude,
            marker.getPosition().longitude
    );
    DirectionsApiRequest directions = new DirectionsApiRequest(mGeoApiContext);

    directions.alternatives(true);
    directions.origin(
            new com.google.maps.model.LatLng(
                    start.latitude,start.longitude
            )
    );
    //Log.d(TAG, "calculateDirections: destination: " + destination.toString());
    directions.destination(destination).setCallback(new PendingResult.Callback<DirectionsResult>() {
        @Override
        public void onResult(DirectionsResult result) {
            Log.d(TAG, "calculateDirections: routes: " + result.routes[0].toString());
            Log.d(TAG, "calculateDirections: duration: " + result.routes[0].legs[0].duration);
            Log.d(TAG, "calculateDirections: distance: " + result.routes[0].legs[0].distance);
            Log.d(TAG, "calculateDirections: geocodedWayPoints: " + result.geocodedWaypoints[0].toString());

            addPolylinesToMap(result);
        }

        @Override
        public void onFailure(Throwable e) {
            Log.e(TAG, "calculateDirections: Failed to get directions: " + e.getMessage() );
            return;
        }
    });
}



private void addPolylinesToMap(final DirectionsResult result){
    new Handler(Looper.getMainLooper()).post(new Runnable() {
        @Override
        public void run() {


            if(mPolyLinesData.size() > 0){
                for(PolylineData polylineData: mPolyLinesData){
                    polylineData.getPolyline().remove();
                }
                mPolyLinesData.clear();
                mPolyLinesData = new ArrayList<>();
            }
            double firstduration = 0;
            for(DirectionsRoute route: result.routes){

                List<com.google.maps.model.LatLng> decodedPath = PolylineEncoding.decode(route.overviewPolyline.getEncodedPath());

                List<LatLng> newDecodedPath = new ArrayList<>();

                // This loops through all the LatLng coordinates of ONE polyline.
                for(com.google.maps.model.LatLng latLng: decodedPath){

                    Log.d(TAG, "run: latlng: " + latLng.toString());

                    newDecodedPath.add(new LatLng(
                            latLng.lat,
                            latLng.lng
                    ));
                }
                Polyline polyline = mMap.addPolyline(new PolylineOptions().addAll(newDecodedPath));
                polyline.setColor(ContextCompat.getColor(getApplicationContext(), R.color.quantum_grey));
                polyline.setClickable(true);
                mPolyLinesData.add(new PolylineData(polyline, route.legs[0]));



                double thisduration = route.legs[0].duration.inSeconds;
                if(firstduration == 0) {
                    firstduration= thisduration;
                    onPolylineClickListener.onPolylineClick(polyline);
                }
                if(thisduration < firstduration){
                    firstduration = thisduration;
                    onPolylineClickListener.onPolylineClick(polyline);
                }
                if(result.routes.length == 1) onPolylineClickListener.onPolylineClick(polyline);



            }
        }
    });
}

GoogleMap.OnPolylineClickListener onPolylineClickListener = new GoogleMap.OnPolylineClickListener() {
    @Override
    public void onPolylineClick(Polyline polyline) {

        int index = 0;
        for(PolylineData polylineData: mPolyLinesData){
            index++;
            //Log.d(TAG, "onPolylineClick: toString: " + polylineData.toString());
            if(polyline.getId().equals(polylineData.getPolyline().getId())){
                polylineData.getPolyline().setColor(ContextCompat.getColor(getApplicationContext(), R.color.quantum_lightblue));
                polylineData.getPolyline().setZIndex(1);

                if(marker != null)marker.remove();
                LatLng endlocation = new LatLng(polylineData.getLeg().endLocation.lat, polylineData.getLeg().endLocation.lng);
                marker = mMap.addMarker(new MarkerOptions().position(endlocation).title("Trip # "+ index).snippet("Duration: "+polylineData.getLeg().duration));
                marker.showInfoWindow();
                zoomRoute(polyline.getPoints());
            }
            else{
                polylineData.getPolyline().setColor(ContextCompat.getColor(getApplicationContext(), R.color.quantum_grey));
                polylineData.getPolyline().setZIndex(0);
            }
        }
    }
};

public void zoomRoute(List<LatLng> lstLatLngRoute) {

    if (mMap == null || lstLatLngRoute == null || lstLatLngRoute.isEmpty()) return;

    LatLngBounds.Builder boundsBuilder = new LatLngBounds.Builder();
    for (LatLng latLngPoint : lstLatLngRoute)
        boundsBuilder.include(latLngPoint);

    int routePadding = 120;
    LatLngBounds latLngBounds = boundsBuilder.build();

    mMap.animateCamera(
            CameraUpdateFactory.newLatLngBounds(latLngBounds, routePadding),
            600,
            null
    );
}


public static class PolylineData {

    private Polyline polyline;
    private DirectionsLeg leg;

    public PolylineData(Polyline polyline, DirectionsLeg leg) {
        this.polyline = polyline;
        this.leg = leg;
    }

    public Polyline getPolyline() {
        return polyline;
    }

    public void setPolyline(Polyline polyline) {
        this.polyline = polyline;
    }

    public DirectionsLeg getLeg() {
        return leg;
    }

    public void setLeg(DirectionsLeg leg) {
        this.leg = leg;
    }

    @Override
    public String toString() {
        return "PolylineData{" +
                "polyline=" + polyline +
                ", leg=" + leg +
                '}';
    }
}

}

Below is the App Gradle:

apply plugin: 'com.android.application' apply plugin: 'com.google.gms.google-services'

android { compileSdkVersion 29 buildToolsVersion "29.0.2"

defaultConfig {
    applicationId "com.example.myapplication"
    minSdkVersion 16
    targetSdkVersion 29
    versionCode 1
    versionName "1.0"

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}
compileOptions {
    targetCompatibility = 1.8
    sourceCompatibility = 1.8
}

}

dependencies { implementation fileTree(dir: 'libs', include: ['*.jar'])

implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.android.gms:play-services-maps:17.0.0'
implementation 'com.google.firebase:firebase-auth:19.3.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'com.google.maps:google-maps-services:0.13.0'
implementation 'org.slf4j:slf4j-simple:1.7.25'
implementation 'com.google.android.libraries.places:places:2.2.0'

}

1 Answers1

0

This solved my problem.

After debugging my app, I found out that adding this to my dependencies in app-level gradle file (build.gradle(app)) helped resolve the issue.

implementation group: 'com.github.seratch', name: 'java-time-backport', version: '1.0.0'