java 如何使用 Google Maps Android API 在 MapFragment 中绘制两点之间的路线

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43467062/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 07:26:48  来源:igfitidea点击:

How to draw route between two points in MapFragment using Google Maps Android API

javaandroidgoogle-mapsmap-directions

提问by Isaac

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.

我想在 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.

  1. 是否可能或我需要 Directions API?不能在 Android Maps API 本身中完成方向吗?

  2. 我的目标是只使用一个活动或 java 文件来完成所有任务,例如获取当前位置并在地图中显示目标指针(我已经完成了)。现在我想给出这两个指针的路由,当前缀指针或位置被使用更改时,路由必须更改。

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

通过前缀,我的意思是我已经在 onNavigationItemSelected() 的 if else 中给出的位置。

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

请参考以下 MainActivity.java 代码 - 我的目标是在一个 java 类本身中完成所有任务。

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.

尽管有可用的解决方案,但我想从我的类似问题中迭代原因是 - 我的目标是只使用一个 java 类,有使用多个 java 类和文件的解决方案。

回答by Firoz Jaroli

You will need direction api. Here is good tutorial:

您将需要方向 api。这是很好的教程:

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

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.

您可以将所有代码放在一个类中。但是最好使用多个类。

回答by Nick Cardoso

If you are already using the Google Maps Fragmentand 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.

如果您已经在使用Google Maps Fragment并且只想在地图上添加线(即记录路线与绘制路线),添加一条线(称为折线)是微不足道的。

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

首先创建一个 PolyLineOptions(保存引用允许您稍后更新它):

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);