在 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 回调。根据我的观察,留在路线上不会触发任何重新路线。
我正在使用 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 回调。根据我的观察,留在路线上不会触发任何重新路线。