我目前设法使用NavigationView
进行导航,现在我可以使用mapView
设置路线,然后通过按屏幕上的按钮来启动navigationView
。
问题是当我想通过按mapView
右下角的X按钮返回到navigationView
时,因为使用下面的当前代码,它只是阻止了导航的进行(我必须手动强制关闭应用程序,然后重新打开即可使用。)我试图在finish()
下方添加navigationView.stopNavigation();
函数,但仍然必须手动强制关闭它。
现在,我是Java的初学者,所以我可能会弄错了,但是我认为问题在于,在终止导航UI之后,无论如何mapView
都无法恢复代码。 (为什么我在navigationLauncher
上没有遇到这样的问题?)
显然在我的代码中我没有使用片段,所以我想知道是否有一种方法可以不使用那些片段(恐怕我将不得不重写代码以实现片段)。
请不要介意所有垃圾和编写不好的代码,因为我只需要它来构建快速的功能原型!
package com.bpnavi.backpacknavigator;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.mapbox.api.directions.v5.DirectionsCriteria;
import com.mapbox.api.directions.v5.MapboxDirections;
import com.mapbox.api.directions.v5.models.BannerInstructions;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.location.modes.RenderMode;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.MapView;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
// 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.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.CompoundButton;
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 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.OnNavigationReadyCallback;
import com.mapbox.services.android.navigation.ui.v5.listeners.BannerInstructionsListener;
import com.mapbox.services.android.navigation.ui.v5.listeners.NavigationListener;
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.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.StepMilestone;
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.NavigationEventListener;
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.navigation.MapboxNavigation;
import com.mapbox.services.android.navigation.v5.navigation.MapboxNavigationOptions;
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.routeprogress.RouteProgressState;
import com.mapbox.services.android.navigation.v5.utils.RouteUtils;
import io.reactivex.Observable;
import io.reactivex.disposables.Disposable;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import timber.log.Timber;
// classes needed to launch navigation UI
import android.view.View;
import android.widget.Button;
import com.mapbox.services.android.navigation.ui.v5.NavigationLauncher;
import com.mapbox.services.android.navigation.v5.offroute.OffRouteListener;
import com.mapbox.services.android.navigation.v5.routeprogress.ProgressChangeListener;
import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress;
import com.polidea.rxandroidble2.RxBleClient;
import com.polidea.rxandroidble2.RxBleConnection;
import com.polidea.rxandroidble2.RxBleDevice;
import com.polidea.rxandroidble2.internal.RxBleLog;
import com.polidea.rxandroidble2.scan.ScanSettings;
import android.util.Log;
import android.widget.ToggleButton;
import java.util.List;
import java.util.UUID;
public class MainActivity extends AppCompatActivity implements PermissionsListener, MapboxMap.OnMapClickListener, OnNavigationReadyCallback, BannerInstructionsListener,
MilestoneEventListener, OffRouteListener, ProgressChangeListener, NavigationListener {
private MapView mapView;
private NavigationView navigationView;
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 MapboxDirections client;
private Button startButton;
public static final String BACKPACK_DEVICE_ADDRESS = "321";
public static final String TEST_DEVICE_ADDRESS = "123";
private static final UUID WRITE_CHARACTERISTIC = UUID.fromString("abc123");
private Disposable disposable;
private RxBleDevice device;
private BannerInstructions BannerInstructionMilestone;
private MapboxNavigation navigation;
private static final int INSTR_MILESTONE = 1001;
private boolean noRe = false;
private boolean simActive = true;
private int activationDistance = 15;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
RxBleClient rxBleClient = RxBleClient.create(this);
device = rxBleClient.getBleDevice(TEST_DEVICE_ADDRESS);
Disposable disposable = device.establishConnection(false) // <-- autoConnect flag
.subscribe(
rxBleConnection -> {
// All GATT operations are done through the rxBleConnection.
},
throwable -> {
// Handle an error here.
}
);
// disposable.dispose();
Mapbox.getInstance(this, getString(R.string.access_token));
setContentView(R.layout.activity_main);
mapView = (MapView) findViewById(R.id.mapView);
startButton = findViewById(R.id.startButton);
startButton.setOnClickListener(v -> {
setTheme(R.style.Theme_AppCompat_NoActionBar);
setContentView(R.layout.activity_navigation);
navigationView = findViewById(R.id.navigationView);
navigationView.onCreate(savedInstanceState);
navigationView.initialize(this);
// boolean simulateRoute = true;
// NavigationLauncherOptions options = NavigationLauncherOptions.builder()
// .directionsRoute(currentRoute)
// .shouldSimulateRoute(simulateRoute)
// .build();
// // Call this method with Context from within an Activity
// NavigationLauncher.startNavigation(MainActivity.this, options);
});
MapboxNavigationOptions navOptions = MapboxNavigationOptions.builder().isDebugLoggingEnabled(true).build();
navigation = new MapboxNavigation(getApplicationContext(), getString(R.string.access_token), navOptions);
navigation.addMilestoneEventListener(this);
navigation.addMilestone(new StepMilestone.Builder()
.setIdentifier(INSTR_MILESTONE)
.setInstruction(this.myInstruction)
.setTrigger(
Trigger.all(
Trigger.lt(TriggerProperty.STEP_DISTANCE_REMAINING_METERS, 10)))
.build()
);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(mapboxMap -> {
MainActivity.this.mapboxMap = mapboxMap;
enableLocationComponent();
originCoord = new LatLng(originLocation.getLatitude(), originLocation.getLongitude());
mapboxMap.addOnMapClickListener(this);
//Set stuff here
mapboxMap.addMarker(new MarkerOptions()
.position(new LatLng(45.506833, 9.163333))
.title("Politecnico di Milano")
.snippet("Dipartimento di Design")
);
});
}
@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_GPS);
locationComponent.setRenderMode(RenderMode.GPS);
originLocation = locationComponent.getLastKnownLocation();
} else {
permissionsManager = new PermissionsManager(this);
permissionsManager.requestLocationPermissions(this);
}
}
@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);
}
private void getRoute(Point origin, Point destination) {
Toast.makeText(this, "Calculating route...", Toast.LENGTH_SHORT).show();
MapboxDirections.builder()
.origin(origin)
.destination(destination)
.accessToken(getString(R.string.access_token))
.profile(DirectionsCriteria.PROFILE_CYCLING)
.bannerInstructions(true)
.steps(true)
.roundaboutExits(true)
.build();
NavigationRoute.builder(this)
.accessToken(getString(R.string.access_token))
.origin(origin)
.destination(destination)
.profile(DirectionsCriteria.PROFILE_CYCLING)
.voiceUnits("metric")
.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(null, mapView, mapboxMap, R.style.NavigationMapRoute);
startButton.setVisibility(View.VISIBLE);
startButton.setBackgroundResource(R.color.colorPrimary);
ToggleButton toggleSim = findViewById(R.id.toggleSimButton);
toggleSim.setVisibility(View.VISIBLE);
}
navigationMapRoute.addRoute(currentRoute);
}
@Override
public void onFailure(Call<DirectionsResponse> call, Throwable throwable) {
Log.e(TAG, "Error: " + throwable.getMessage());
}
});
}
@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();
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
int REQUEST_ENABLE_BT = 1;
this.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mapView.onPause();
}
@Override
protected void onStop() {
super.onStop();
mapView.onStop();
if (disposable != null) {
disposable.dispose();
disposable = null;
}
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
if (disposable != null) {
disposable.dispose();
disposable = null;
}
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
@Override
public void onBackPressed() {
// If the navigation view didn't need to do anything, call super
if (!navigationView.onBackPressed()) {
super.onBackPressed();
}
}
@Override
public void onNavigationReady(boolean isRunning) {
NavigationViewOptions options = NavigationViewOptions.builder()
.directionsRoute(currentRoute)
.shouldSimulateRoute(simActive)
.bannerInstructionsListener(this)
.milestoneEventListener(MainActivity.this)
.navigationListener(MainActivity.this)
.progressChangeListener(MainActivity.this)
.build();
navigationView.startNavigation(options);
}
@Override
public void onProgressChange(Location location, RouteProgress routeProgress) {
if (routeProgress.currentLegProgress().currentStepProgress().distanceRemaining()>20) {
noRe = false;
}
Context context = getApplicationContext();
String instr = myInstruction.buildInstruction(routeProgress).replaceAll(" ", "");
int duration = Toast.LENGTH_SHORT;
if (instr.length() < 20 &&
!noRe &&
routeProgress.currentLegProgress().currentStepProgress().distanceRemaining() < activationDistance
) {
noRe = true;
Toast.makeText(context, instr, duration).show();
RxBleClient rxBleClient = RxBleClient.create(this);
device = rxBleClient.getBleDevice(TEST_DEVICE_ADDRESS);
Disposable disposable = device.establishConnection(false) // <-- autoConnect flag
.flatMapSingle(rxBleConnection -> rxBleConnection.writeCharacteristic(WRITE_CHARACTERISTIC, instr.getBytes()))
.subscribe(
characteristicValue -> {
// Characteristic value confirmed.
},
throwable -> {
// Handle an error here.
}
);
}
}
@Override
public void userOffRoute(Location location) {
Toast.makeText(this, "offRoute", Toast.LENGTH_LONG).show();
}
@Override
public void onMilestoneEvent(RouteProgress routeProgress, String instruction, Milestone milestone) {
}
Instruction myInstruction = new Instruction() {
@Override
public String buildInstruction(RouteProgress routeProgress) {
return routeProgress.currentLegProgress().upComingStep().maneuver().type() + routeProgress.currentLegProgress().upComingStep().maneuver().modifier();
}
};
@Override
public BannerInstructions willDisplay(BannerInstructions instructions) {
return instructions;
}
@Override
public void onCancelNavigation() {
navigationView.stopNavigation();
}
@Override
public void onNavigationFinished() {
}
@Override
public void onNavigationRunning() {
}
}
谢谢!
答案 0 :(得分:0)
您提到您曾尝试将finish()
放在navigationView.stopNavigation()
内,我可以看到您正在onCancelNavigation()
方法内调用。您是否尝试过将finish()
放入您的onCancelNavigation()
方法中?
@Override
public void onCancelNavigation() {
finish();
}
我在过去一周中实现了Mapbox导航UI,这是我用来在UI右下角使用十字(X)按钮的方法,使我回到MapView /上一个活动
希望对您有帮助!