How to draw route between two points in MapFragmen

2020-06-06 04:54发布

My target is to complete the following tasks in one single class.

I want to give direction between two pointers (current location & prefixed location in navigation drawer) in Google Android Map API.

  1. Is it possible or do I need Directions API? Can't direction be done in Android Maps API itself?

  2. My goal is to use only one activity or java file for all tasks like fetch current location and show the destination pointer in map (which I have done). Now I want to give the route for these two pointers and the route must change when the prefixed pointer or location is changed by the used.

By prefixed, I mean the location I have already given in the if else in onNavigationItemSelected().

Please refer the below code which is the MainActivity.java - My target is to complete all the tasks in one java class itself.

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, OnMapReadyCallback, LocationListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

private GoogleMap mMap;
private GoogleApiClient client;

Location location;
LocationManager locationManager;

Marker marker;

String title;
String subTitle;
LatLng latLon;

double latitude;
double longitude;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setContentView(R.layout.activity_main);

    isConnectionAvailable();
    isGpsAvailable();

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);

    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);

    // ATTENTION: This was auto-generated to implement the App Indexing API.
    // See https://g.co/AppIndexing/AndroidStudio for more information.
    client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();

}

private boolean isConnectionAvailable() {

    boolean netCon = false;

    try {

        //Internet & network information "Object" initialization
        ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
        //Internet enable & connectivity checking
        if ("WIFI".equals(networkInfo.getTypeName()) || "MOBILE".equals(networkInfo.getTypeName()) && networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnectedOrConnecting()) {
            netCon = true;
        }
    } catch (Exception e) {
        new AlertDialog.Builder(this)
                .setIcon(android.R.drawable.ic_dialog_alert)
                .setTitle("No Network Connection!")
                .setMessage("Please connect your device to either WiFi or switch on Mobile Data, operator charges may apply!")
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.cancel();
                        finish();
                    }
                }).show();
    }
    return netCon;
}

private boolean isGpsAvailable() {

    boolean gpsCon = false;

    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
        Toast.makeText(this, "GPS is Enabled.", Toast.LENGTH_SHORT).show();
        gpsCon = true;
    } else {
        new AlertDialog.Builder(this)
                .setIcon(android.R.drawable.ic_dialog_alert)
                .setTitle("GPS is disabled!")
                .setMessage("Without GPS this application will not work! Would you like to enable the GPS?")
                .setCancelable(false)
                .setPositiveButton("Enable GPS", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        Intent callGpsSetting = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                        startActivity(callGpsSetting);
                    }
                })
                .setNegativeButton("Exit.", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.cancel();
                        finish();
                    }
                })
                .show();
    }
    return gpsCon;
}

@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else {
        client.disconnect();
        super.onBackPressed();
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    int id = item.getItemId();

    if (id == R.id.redBuilding){
        latitude = 13.0827;
        longitude = 80.2707;

        title = "Chennai";
        subTitle = "TN";

        latLon = new LatLng(latitude, longitude);
    }
    mMap.clear();
    mMap.addMarker(new MarkerOptions().position(latLon).title(title).snippet(subTitle)).showInfoWindow();
    CameraPosition cameraPosition = new CameraPosition.Builder().target(latLon).tilt(30).zoom(20).build();
    mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));

    if (id == R.id.nav_share) {
    } else if (id == R.id.nav_send) {
    }

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;
}

@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
    mMap.setMyLocationEnabled(true);
    buildGoogleApiClient();
}

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

public Action getIndexApiAction() {
    Thing object = new Thing.Builder()
            .setName("CEG") // TODO: Define a title for the content shown.
            // TODO: Make sure this auto-generated URL is correct.
            .setUrl(Uri.parse("http://[ENTER-YOUR-URL-HERE]"))
            .build();
    return new Action.Builder(Action.TYPE_VIEW)
            .setObject(object)
            .setActionStatus(Action.STATUS_TYPE_COMPLETED)
            .build();
}

@Override
public void onStart() {
    super.onStart();

    // ATTENTION: This was auto-generated to implement the App Indexing API.
    // See https://g.co/AppIndexing/AndroidStudio for more information.
    client.connect();
    AppIndex.AppIndexApi.start(client, getIndexApiAction());
}

@Override
public void onStop() {
    super.onStop();

    // ATTENTION: This was auto-generated to implement the App Indexing API.
    // See https://g.co/AppIndexing/AndroidStudio for more information.
    if (client.isConnected()) {
        AppIndex.AppIndexApi.end(client, getIndexApiAction());
        client.disconnect();
    }
}

@Override
public void onConnected(Bundle bundle) {
    location = LocationServices.FusedLocationApi.getLastLocation(client);
    if (location != null) {
        latitude = location.getLatitude();
        longitude = location.getLongitude();
    }
    LatLng latLon = new LatLng(latitude, longitude);
    mMap.addMarker(new MarkerOptions().position(latLon)
            .title("You are here.").snippet("Choose destination from menu to navigate.")
            .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA))
    ).showInfoWindow();
    CameraPosition cameraPosition = new CameraPosition.Builder().target(latLon).tilt(30).zoom(20).build();
    mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}

@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onLocationChanged(Location location) {

    location = location;

    //Place current location marker
    LatLng latLon = new LatLng(location.getLatitude(), location.getLongitude());
    mMap.clear();
    mMap.addMarker(new MarkerOptions().position(latLon)
            .title("You are here.").snippet("Choose destination from menu to navigate.")
            .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA))
    ).showInfoWindow();
    CameraPosition cameraPosition = new CameraPosition.Builder().target(latLon).tilt(30).zoom(20).build();
    mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));

    //stop location updates
    if (client != null) {
        LocationServices.FusedLocationApi.removeLocationUpdates(client, this);
    }

}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

}

public static final int MY_PERMISSIONS_REQUEST_LOCATION = 0;

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

        // Asking user if explanation is needed
        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.

            //Prompt the user once explanation has been shown
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_LOCATION);

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

@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. Do the
                // contacts-related task you need to do.
                if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                    if (client == null) {
                        buildGoogleApiClient();
                    }
                    mMap.setMyLocationEnabled(true);
                }
            } else {
                // Permission denied, Disable the functionality that depends on this permission.
                Toast.makeText(this, "Permission denied", Toast.LENGTH_LONG).show();
            }
            return;
        }
        // other 'case' lines to check for other permissions this app might request.
        // You can add here other case statements according to your requirement.
    }
}
}

I would like to iterate the reason from my similar question in spite of available solutions is that - my target is to use only one java class, there are solutions using multiple java classes and files.

2条回答
等我变得足够好
2楼-- · 2020-06-06 05:23

If you are already using the Google Maps Fragment and just want to add lines to the map (i.e. record a route vs plot a route), adding a line (called a poly line) is trivial.

Start by creating a PolyLineOptions (saving the reference allows you to update it later):

PolylineOptions routeLine;
LatLng pos = new LatLng(location.getLatitude(), location.getLongitude());
routeLine = new PolylineOptions().add(pos);

At this point the line won't show, to make it show there are two requirements: Add it to the map and Add at least one more point:

routeLine.add(new LatLng(nextLocation.getLatitude(), nextLocation.getLongitude()));
map.addPolyline(routeLine);
查看更多
虎瘦雄心在
3楼-- · 2020-06-06 05:38

You will need direction api. Here is good tutorial:

https://www.androidtutorialpoint.com/intermediate/google-maps-draw-path-two-points-using-google-directions-google-map-android-api-v2/

You can put all code in one class. But it is better to use multiple class.

查看更多
登录 后发表回答