Кнопка cancelNavigation не возвращает в mapView из navigationView

В настоящее время мне удалось заставить навигацию работать с NavigationView, и теперь я могу установить маршрут с помощью mapView, а затем запустить navigationView, нажав кнопку на экране. Проблема в том, что я хочу вернуться к mapView, нажав кнопку X в правом нижнем углу navigationView, поскольку с текущим кодом ниже он просто останавливает продвижение навигации (мне нужно вручную закрыть приложение и снова открыть его. чтобы иметь возможность использовать его снова). Я попытался добавить функцию finish() прямо под navigationView.stopNavigation();, но мне все равно приходится вручную закрывать ее вручную.

Теперь я новичок в Java, поэтому я могу ошибаться, но я думаю, что проблема в том, что код в любом случае не восстанавливает 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() {

    }

}

Благодарность!

1
0
591
1

Ответы 1

Вы упомянули, что пытались поместить finish() в navigationView.stopNavigation(), который, как я вижу, вы вызываете внутри своего метода onCancelNavigation(). Вы пытались вместо этого вставить finish() в свой метод onCancelNavigation()?

@Override
public void onCancelNavigation() {
    finish();
}

Я реализовал пользовательский интерфейс навигации Mapbox на прошлой неделе, и это метод, который я использовал, чтобы кнопка с крестиком (X) в правой нижней части пользовательского интерфейса возвращала меня к MapView / предыдущему действию.

Надеюсь, это поможет!

Другие вопросы по теме