首页 > 解决方案 > Mapbox导航useroffroute功能覆盖不起作用

问题描述

未触发偏离路线

我正在使用导航启动器。我也尝试过使用导航视图。但是 useroffroute 功能没有被触发。

package com.example.lenovo.offroutetest;

import java.io.File;
import java.io.FileOutputStream;
import java.util.List;
import android.os.Bundle;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
// classes needed to initialize map
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.maps.MapView;
// classes needed to add the location component
import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import android.location.Location;
import android.widget.Toast;
import com.mapbox.mapboxsdk.geometry.LatLng;
import android.support.annotation.NonNull;
import com.mapbox.mapboxsdk.location.LocationComponent;
import com.mapbox.mapboxsdk.location.modes.CameraMode;
import com.mapbox.services.android.navigation.ui.v5.NavigationLauncherOptions;
import com.mapbox.android.core.permissions.PermissionsListener;
import com.mapbox.android.core.permissions.PermissionsManager;
// classes needed to add a marker
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
// classes to calculate a route
import com.mapbox.services.android.navigation.ui.v5.NavigationView;
import com.mapbox.services.android.navigation.ui.v5.NavigationViewOptions;
import com.mapbox.services.android.navigation.ui.v5.route.NavigationMapRoute;
import com.mapbox.services.android.navigation.v5.instruction.Instruction;
import com.mapbox.services.android.navigation.v5.milestone.BannerInstructionMilestone;
import com.mapbox.services.android.navigation.v5.milestone.Milestone;
import com.mapbox.services.android.navigation.v5.milestone.MilestoneEventListener;
import com.mapbox.services.android.navigation.v5.milestone.RouteMilestone;
import com.mapbox.services.android.navigation.v5.milestone.Trigger;
import com.mapbox.services.android.navigation.v5.milestone.TriggerProperty;
import com.mapbox.services.android.navigation.v5.navigation.MapboxNavigation;
import com.mapbox.services.android.navigation.v5.navigation.MapboxNavigationOptions;
import com.mapbox.services.android.navigation.v5.navigation.NavigationRoute;
import com.mapbox.api.directions.v5.models.DirectionsResponse;
import com.mapbox.api.directions.v5.models.DirectionsRoute;
import com.mapbox.services.android.navigation.v5.offroute.OffRouteListener;
import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress;
import com.mapbox.services.android.navigation.v5.routeprogress.ProgressChangeListener;
import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress;
import com.mapbox.services.android.navigation.v5.navigation.NavigationEventListener;

import okhttp3.Route;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import android.util.Log;
// classes needed to launch navigation UI
import android.view.View;
import android.widget.Button;
import com.mapbox.services.android.navigation.ui.v5.NavigationLauncher;

import org.intellij.lang.annotations.Identifier;

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback, MapboxMap.OnMapClickListener, OffRouteListener,PermissionsListener,MilestoneEventListener, ProgressChangeListener,NavigationEventListener{
    private MapView mapView;
    // variables for adding location layer
    private MapboxMap mapboxMap;
    private PermissionsManager permissionsManager;
    private Location originLocation;
    // variables for adding a marker
    private Marker destinationMarker;
    private LatLng originCoord;
    private LatLng destinationCoord;
    // variables for calculating and drawing a route
    private Point originPosition;
    private Point destinationPosition;
    private DirectionsRoute currentRoute;
    private static final String TAG = "DirectionsActivity";
    private NavigationMapRoute navigationMapRoute;
    private Button button;
    private MapboxNavigation navigation;
    private NavigationView navigationView;
    private CoordinatorLayout coordinatorLayout;
    private boolean running;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Mapbox.getInstance(this,"pk.eyJ1IjoicHJpeWFuZ2EiLCJhIjoiY2pwYzQ1OGxpMGgybTNscGhsbjA0cXlvcSJ9.MJD97KhqBQifpKRrPGtomg");
        //MapboxNavigationOptions options = MapboxNavigationOptions.builder().isDebugLoggingEnabled(true).build();
        //MapboxNavigationOptions opt=MapboxNavigationOptions.builder().build()
        navigation=new MapboxNavigation(MainActivity.this,"pk.eyJ1IjoicHJpeWFuZ2EiLCJhIjoiY2pwYzQ1OGxpMGgybTNscGhsbjA0cXlvcSJ9.MJD97KhqBQifpKRrPGtomg");
        //navigation.addOffRouteListener(offRouteListener);
        //navigation.addMilestoneEventListener(this);
        navigation.addMilestone(new BannerInstructionMilestone.Builder().setIdentifier(1).setTrigger(Trigger.all(Trigger.eq(TriggerProperty.LAST_STEP, TriggerProperty.TRUE))).setInstruction(new Instruction() {
            @Override
            public String buildInstruction(RouteProgress routeProgress) {

                return "I AM HERE";
            }
        }).build());
        setContentView(R.layout.activity_main);
        mapView = findViewById(R.id.mapView);
        //navigationView=findViewById(R.id.navigationView);
        //navigationView.onCreate(savedInstanceState);
        //navigationView.initialize(this);
        mapView.onCreate(savedInstanceState);
        mapView.getMapAsync(this);
    }

    @Override
    public void onMilestoneEvent(RouteProgress routeProgress, String instruction, Milestone milestone) {
        //exampleInstructionPlayer.play(instruction);
        Log.e("milestone","reached");
        Toast.makeText(getApplicationContext(),"Milestone triggered",Toast.LENGTH_SHORT).show();
    }
    @Override
    public void onMapReady(MapboxMap mapboxMap) {
        this.mapboxMap = mapboxMap;
        enableLocationComponent();
        originCoord = new LatLng(originLocation.getLatitude(), originLocation.getLongitude());
        mapboxMap.addOnMapClickListener(this);
        button = findViewById(R.id.startButton);
        /*navigation.addOffRouteListener(new OffRouteListener() {
            @Override
            public void userOffRoute(Location location) {
                Snackbar snackbar = Snackbar
                        .make(coordinatorLayout, "User rerouting", Snackbar.LENGTH_LONG);
                snackbar.show();
                Toast.makeText(getApplicationContext(), "Off route", Toast.LENGTH_SHORT).show();
                //File path = getApplicationContext().getFilesDir();
                //File path=getApplicationContext().getExternalFilesDir(null);
                try {
                    File path=getApplicationContext().getFilesDir();
                    Toast.makeText(getApplicationContext(),String.valueOf(path),Toast.LENGTH_SHORT).show();
                    File file = new File(path, "off_route.txt");
                    FileOutputStream stream = new FileOutputStream(file);
                    stream.write(("Offroute"+location.toString()).getBytes());
                    stream.close();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
            }
        });*/
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //NavigationViewOptions navopt=NavigationViewOptions.builder().directionsRoute(currentRoute).shouldSimulateRoute(false).build();
                boolean simulateRoute = false;
                NavigationLauncherOptions options = NavigationLauncherOptions.builder()
                        .directionsRoute(currentRoute)
                        .shouldSimulateRoute(simulateRoute)
                        .build();
                // Call this method with Context from within an Activity
                NavigationLauncher.startNavigation(MainActivity.this, options);
                //navigation.startNavigation(currentRoute);
                //navigation.startNavigation(currentRoute);
                //navigationView.startNavigation(navopt);
            }
        });
    }

    @Override
    public void onProgressChange(Location location, RouteProgress routeProgress)
    {

    }

    @Override
    public void onMapClick(@NonNull LatLng point){
        if (destinationMarker != null) {
            mapboxMap.removeMarker(destinationMarker);
        }
        destinationCoord = point;
        destinationMarker = mapboxMap.addMarker(new MarkerOptions()
                .position(destinationCoord)
        );
        destinationPosition = Point.fromLngLat(destinationCoord.getLongitude(), destinationCoord.getLatitude());
        originPosition = Point.fromLngLat(originCoord.getLongitude(), originCoord.getLatitude());
        getRoute(originPosition, destinationPosition);
        button.setEnabled(true);
        button.setBackgroundResource(R.color.mapboxBlue);
        /*try {
            //File path=getApplicationContext().getFilesDir();
            File path=getApplicationContext().getExternalFilesDir(null);
            Toast.makeText(getApplicationContext(),String.valueOf(path.getAbsolutePath()),Toast.LENGTH_SHORT).show();
            //File path = getApplicationContext().getExternalFilesDir(null);
            File file = new File(path, "off_route.txt");
            //Log.e("Writing to file","file");
            FileOutputStream stream = new FileOutputStream(file);
            stream.write("Offroute am there".getBytes());
            Toast.makeText(getApplicationContext(),"I ma here",Toast.LENGTH_LONG).show();
            stream.close();
        }
        catch (Exception e)
        {
            Toast.makeText(getApplicationContext(),e.toString(),Toast.LENGTH_LONG).show();
            e.printStackTrace();
        }*/

    }

    @Override
    public void userOffRoute(Location location) {
        //Snackbar snackbar = Snackbar
          //      .make(coordinatorLayout, "User rerouting", Snackbar.LENGTH_LONG);
        //snackbar.show();
        Toast.makeText(getApplicationContext(), "Off route detected.........", Toast.LENGTH_SHORT).show();
        //File path = getApplicationContext().getFilesDir();
        //File path=getApplicationContext().getExternalFilesDir(null);
        try {
            File path=getApplicationContext().getExternalFilesDir(null);
            Toast.makeText(getApplicationContext(),String.valueOf(path),Toast.LENGTH_SHORT).show();
            File file = new File(path, "useroff.txt");
            FileOutputStream stream = new FileOutputStream(file);
            stream.write(("Offroute"+location.toString()).getBytes());
            stream.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
    @Override

    public void onRunning(boolean running)
    {
        this.running=running;
        if(running)
        {
            //navigation.addOffRouteListener(this);
            //navigation.addProgressChangeListener(this);
        }
    }



    private void getRoute(Point origin, Point destination) {
        NavigationRoute.builder(this)
                .accessToken(Mapbox.getAccessToken())
                .origin(origin)
                .destination(destination)
                .build()
                .getRoute(new Callback<DirectionsResponse>() {
                    @Override
                    public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
                        // You can get the generic HTTP info about the response
                        Log.d(TAG, "Response code: " + response.code());
                        if (response.body() == null) {
                            Log.e(TAG, "No routes found, make sure you set the right user and access token.");
                            return;
                        } else if (response.body().routes().size() < 1) {
                            Log.e(TAG, "No routes found");
                            return;
                        }

                        currentRoute = response.body().routes().get(0);

                        // Draw the route on the map
                        if (navigationMapRoute != null) {
                            navigationMapRoute.removeRoute();
                        } else {
                            navigationMapRoute = new NavigationMapRoute(navigation, mapView, mapboxMap, R.style.NavigationMapRoute);
                        }
                        navigationMapRoute.addRoute(currentRoute);
                    }

                    @Override
                    public void onFailure(Call<DirectionsResponse> call, Throwable throwable) {
                        Log.e(TAG, "Error: " + throwable.getMessage());
                    }
                });
    }

    @SuppressWarnings( {"MissingPermission"})
    private void enableLocationComponent() {
        // Check if permissions are enabled and if not request
        if (PermissionsManager.areLocationPermissionsGranted(this)) {
            // Activate the MapboxMap LocationComponent to show user location
            // Adding in LocationComponentOptions is also an optional parameter
            LocationComponent locationComponent = mapboxMap.getLocationComponent();
            locationComponent.activateLocationComponent(this);
            locationComponent.setLocationComponentEnabled(true);
            // Set the component's camera mode
            locationComponent.setCameraMode(CameraMode.TRACKING);
            originLocation = locationComponent.getLastKnownLocation();

        } else {
            permissionsManager = new PermissionsManager(this);
            permissionsManager.requestLocationPermissions(this);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    public void onExplanationNeeded(List<String> permissionsToExplain) {
        Toast.makeText(this, R.string.user_location_permission_explanation, Toast.LENGTH_LONG).show();
    }

    @Override
    public void onPermissionResult(boolean granted) {
        if (granted) {
            enableLocationComponent();
        } else {
            Toast.makeText(this, R.string.user_location_permission_not_granted, Toast.LENGTH_LONG).show();
            finish();
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        mapView.onStart();
    }

    @Override
    protected void onResume() {
        super.onResume();
        mapView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mapView.onPause();
    }

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

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mapView.onSaveInstanceState(outState);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mapView.onDestroy();
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mapView.onLowMemory();
    }




}

我希望我覆盖的函数 useroffroute 被触发。但是没有触发发生,因为当用户离开路由时,我无法看到 toast 消息和文件创建。

标签: javaandroidnavigationmapbox

解决方案


所以这里要解决的第一件事是,这绝对不适用于NavigationLauncher. 该对象实际上是一个功能齐全的解决方案,可以通过最少的自定义快速启动和运行导航。所以它不是那么灵活,并且不允许你修改你的offRoute听众。这只有在NavigationView.

很容易错过,但地图匹配文档中实际上概述了如何覆盖默认重新路由行为的文档:https ://docs.mapbox.com/android/navigation/overview/map-matching/#map-matching-带地图框导航

考虑到这一点,您的代码中似乎缺少了一个关键步骤。当您offRouteListener向对象添加一个navigation对象时,您需要执行并覆盖该userOffRoute功能。最终看起来像这样:

navigation.addOffRouteListener(new OffRouteListener() {
    @Override
    public void userOffRoute(Location location) {
        Toast.makeText(getApplicationContext(), "Off route detected.........", Toast.LENGTH_SHORT).show();
        // Make sure you call for a new DirectionsRoute object
        // and end by calling MapboxNavigation#startNavigation on a successful
    }
});

推荐阅读