在 Here Map Android SDK 中重新路由

Rerouting in Here Map Android SDK

我正在使用 Here Map Android SDK 来实现导航功能。目前我的应用程序可以计算路线并通过 NavigationManager 绘制路线。但是即使我将 RerouteListener 添加到 NavigationManager 中,重新路由功能也无法工作。我的代码如下:

public class Navigation extends ActionBarActivity {

private GeoCoordinate destinationGeo;
private GeoCoordinate originGeo;

private static Map mMap = null;

private static MapFragment mMapFragment = null;

private static MapRoute mMapRoute = null;

private static RouteManager mRouteManager = null;

private static PositioningManager mPositoningManager = null;

private static NavigationManager mNavigationManager = null;



private static boolean mPositioningListenerPaused = true;

RouteCalculationTask mRouteCalculationTask;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_navigation);

    /*
    //get destination geo passed from CarParkingActivity
    Intent intent = getIntent();
    Bundle extras = intent.getExtras();
    String lat = extras.getString("lat");
    String lng = extras.getString("lng");
    */
    //destinationGeo = new GeoCoordinate(Double.parseDouble(lat), Double.parseDouble(lng));
    destinationGeo = new GeoCoordinate(1.37374, 103.9707);

    mMapFragment = (MapFragment)getFragmentManager().findFragmentById(R.id.navigation_nokia);
    if (mMapFragment == null){
        System.out.println("mapfragment null");
    }

    mMapFragment.init(new OnEngineInitListener() {
        @Override
        public void onEngineInitializationCompleted(Error error) {
            if (error == Error.NONE){
                System.out.println("map engine init no error");
                mMap = mMapFragment.getMap();
                mMapFragment.getView().setVisibility(View.INVISIBLE);
                mMap.setZoomLevel(mMap.getMaxZoomLevel());
                mMap.setCenter(destinationGeo, Map.Animation.NONE);

                //set destination marker on map
                Image image = new Image();
                try{
                    image.setImageResource(R.drawable.carpark4);
                }
                catch (IOException e){
                    e.printStackTrace();
                }
                MapMarker mapMarker = new MapMarker(destinationGeo, image);
                mMap.addMapObject(mapMarker);

                //set navigation marker on map
                try{
                    image.setImageResource(R.drawable.gnavigation);
                }catch (IOException e){
                    e.printStackTrace();
                }
                mMap.getPositionIndicator().setMarker(image);
                mMap.getPositionIndicator().setVisible(true);

                //set traffic information
                mMap.setTrafficInfoVisible(true);

                //set map scheme
                mMap.setMapScheme(Map.Scheme.CARNAV_DAY);


                mRouteManager = RouteManager.getInstance();

                mPositoningManager = PositioningManager.getInstance();
                mPositoningManager.addListener(new WeakReference<PositioningManager.OnPositionChangedListener>(mPositioningListener));
                // start positioning manager
                if (mPositoningManager.start(PositioningManager.LocationMethod.GPS_NETWORK)){
                    MapEngine.getInstance().onResume();
                    mPositioningListenerPaused = false;
                    mRouteCalculationTask = new RouteCalculationTask(RouteOptions.Type.FASTEST);
                    mRouteCalculationTask.execute("hello");
                }

                mNavigationManager = NavigationManager.getInstance();
                mNavigationManager.setMap(mMap);

                //set map update mode when movement
                mNavigationManager.setMapUpdateMode(NavigationManager.MapUpdateMode.ROADVIEW);

                //set up road view in navigation
                NavigationManager.RoadView roadView = mNavigationManager.getRoadView();
                roadView.addListener(new WeakReference<NavigationManager.RoadView.Listener>(mNavigationManagerRoadViewListener));
                roadView.setOrientation(NavigationManager.RoadView.Orientation.DYNAMIC);  //heading is at the top of the screen

                //set up route recalculation in navigation
                mNavigationManager.addRerouteListener(new WeakReference<NavigationManager.RerouteListener>(mNavigaionRerouteListener));


            }else {
                System.out.println("ERROR: cannot init MapFragment");
            }
        }
    });
}

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

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

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

    if (mPositoningManager != null){
        // start positioning manager
        if (mPositoningManager.start(PositioningManager.LocationMethod.GPS_NETWORK)){
            mPositioningListenerPaused = false;
            mRouteCalculationTask = new RouteCalculationTask(RouteOptions.Type.FASTEST);
            mRouteCalculationTask.execute("hello");
        }
    }
}

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

    //stop positioning manager
    mPositoningManager.stop();
    mPositioningListenerPaused = true;
    MapEngine.getInstance().onPause();

}


//RouteManager
private RouteManager.Listener mRouteMangerListener = new RouteManager.Listener() {
    @Override
    public void onProgress(int i) {

    }

    @Override
    public void onCalculateRouteFinished(RouteManager.Error error, List<RouteResult> list) {
        if (error == RouteManager.Error.NONE && list.get(0).getRoute() != null){
            //create a map route and place it on the map
            Route route = list.get(0).getRoute();
            mMapRoute = new MapRoute(route);
            mMap.addMapObject(mMapRoute);

            //begin navigation
            NavigationManager.Error navigationError = mNavigationManager.startNavigation(route);
            if (navigationError != NavigationManager.Error.NONE)
            {
                System.out.println(navigationError);
            }
            else {
                System.out.println("start navigation no error");
                mNavigationManager.addNavigationManagerEventListener(new WeakReference< NavigationManager.NavigationManagerEventListener>(mNavigationManagerEventListener));
            }
            //get boundingbox containing the route and zoom in (no animation)
            GeoBoundingBox gbb = route.getBoundingBox();
            mMap.zoomTo(gbb, Map.Animation.NONE, Map.MOVE_PRESERVE_ORIENTATION);
        }
    }
};

private NavigationManager.NavigationManagerEventListener mNavigationManagerEventListener = new NavigationManager.NavigationManagerEventListener() {
    @Override
    public void onRunningStateChanged() {
        super.onRunningStateChanged();
        System.out.println("onRunningStateChanged");
    }

    @Override
    public void onNavigationModeChanged(){
        super.onNavigationModeChanged();
        System.out.println("onNavigationModeChanged");
    }
};

private NavigationManager.RoadView.Listener mNavigationManagerRoadViewListener = new NavigationManager.RoadView.Listener() {
    @Override
    public void onPositionChanged(GeoCoordinate geoCoordinate) {
        Log.d("Roadview pos", geoCoordinate.toString());
    }
};

private class RouteCalculationTask extends AsyncTask<String, String, String> {
    private RouteOptions.Type routeType;

    private ProgressDialog progressDialog = new ProgressDialog(Navigation.this);

    public RouteCalculationTask(RouteOptions.Type type) {
        /*
        FASTEST(0),
        SHORTEST(1),
        ECONOMIC(2);
         */

        routeType = type;
    }

    @Override
    protected String doInBackground(String... url){
        //clear previous results
        if (mMap != null && mMapRoute != null){
            mMap.removeMapObject(mMapRoute);
            mMapRoute = null;
        }

        //select routing opitions
        RoutePlan routePlan = new RoutePlan();

        RouteOptions routeOptions = new RouteOptions();
        routeOptions.setTransportMode(RouteOptions.TransportMode.PEDESTRIAN);
        routeOptions.setRouteType(routeType);
        routePlan.setRouteOptions(routeOptions);

        //set start point
        for(int i = 0; i < 100; i++)
        {
            if(mPositoningManager.hasValidPosition())
                break;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        originGeo = mPositoningManager.getPosition().getCoordinate();
        routePlan.addWaypoint(originGeo);
        System.out.println("get originGeo");

        //set end point
        routePlan.addWaypoint(destinationGeo);

        //retrieve routing information via RouteManagerEventListener
        RouteManager.Error error = mRouteManager.calculateRoute(routePlan, mRouteMangerListener);
        if (error != RouteManager.Error.NONE)
        {
            /*
            NONE(0),
            UNKNOWN(1),
            OUT_OF_MEMORY(2),
            INVALID_PARAMETERS(3),
            INVALID_OPERATION(4),
            GRAPH_DISCONNECTED(5),
            GRAPH_DISCONNECTED_CHECK_OPTIONS(6),
            NO_START_POINT(7),
            NO_END_POINT(8),
            NO_END_POINT_CHECK_OPTIONS(9),
            CANNOT_DO_PEDESTRIAN(10),
            ROUTING_CANCELLED(11),
            VIOLATES_OPTIONS(12),
            ROUTE_CORRUPTED(13),
            INVALID_CREDENTIALS(14),
            REQUEST_TIMEOUT(15),
            PT_ROUTING_UNAVAILABLE(16),
            OPERATION_NOT_ALLOWED(17),
            NO_CONNECTIVITY(18);
             */

            System.out.println(error);
        }

        String data = "";
        return data;
    }

    @Override
    protected void onPreExecute(){
        super.onPreExecute();
        progressDialog.show();
    }

    @Override
    protected void onPostExecute(String result){
        super.onPostExecute(result);
        mMapFragment.getView().setVisibility(View.VISIBLE);
        if (progressDialog.isShowing())
            progressDialog.dismiss();
    }

}

//define positoning listener
private PositioningManager.OnPositionChangedListener mPositioningListener = new PositioningManager.OnPositionChangedListener() {
    @Override
    public void onPositionUpdated(PositioningManager.LocationMethod locationMethod, GeoPosition geoPosition, boolean b) {
        if (!mPositioningListenerPaused && geoPosition.isValid()){
            //originGeo = geoPosition.getCoordinate();
            mMap.setCenter(geoPosition.getCoordinate(), Map.Animation.NONE);

            Double speed = geoPosition.getSpeed();
            Double heading = geoPosition.getHeading();

            originGeo = geoPosition.getCoordinate();


            System.out.println(originGeo.toString());
            System.out.println(speed);
        }
    }

    @Override
    public void onPositionFixChanged(PositioningManager.LocationMethod locationMethod, PositioningManager.LocationStatus locationStatus) {

        //determine if tunnel extrapolation is active
        if (locationMethod == PositioningManager.LocationMethod.GPS){
            boolean isExtrapolated = ((mPositoningManager.getRoadElement() != null)
                                    && (mPositoningManager.getRoadElement().getAttributes().contains(RoadElement.Attribute.TUNNEL)));
            boolean hasGPS = (locationStatus == locationStatus.AVAILABLE);
        }
    }
};

//Route recalculation
private NavigationManager.RerouteListener mNavigaionRerouteListener = new NavigationManager.RerouteListener() {
    @Override
    public void onRerouteBegin() {
        super.onRerouteBegin();
        Toast.makeText(getApplicationContext(), "reroute begin", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onRerouteEnd(Route route){
        super.onRerouteEnd(route);
        Toast.makeText(getApplicationContext(), "reroute end", Toast.LENGTH_SHORT).show();
    }
};
}

根据我的理解,当您的位置偏离计算的路线时,应该会触发路线(重新)计算。我试过了,我收到了 onRerouteBegin 和 onReRouteEnd 回调。根据我的观察,留在路线上不会触发任何重新路线。