Как нарисовать маршрут, выбрав маркеры с автозаполнением мест?

Я хочу нарисовать маршрут на карте, когда я помещаю маркер пункта назначения из панели поиска Места AutoComplete. Как только я выбираю место доставки из автозаполнения, мне нужен маршрут. Я видел несколько примеров пути рисования, но не могу найти их через Места Autocomplete. Моя карта и Места Autocomplete работают правильно. Как мне это сделать?

MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);



    if (!Places.isInitialized()) {
        Places.initialize(getApplicationContext(), "my_api_ke");
    }


    /*Map Initialisation*/
    mv = findViewById(R.id.Gmapview);
    mv.onCreate(savedInstanceState);
    mv.getMapAsync(this);


    lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    provider = lm.getBestProvider(new Criteria(), false);


    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.addDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);

    checkLocationPermission();
    enableMyLocationIfPermitted();


    //Initialize AutoCompleteSupportFragment

    //Pickup Search Bar
    supportFragment = (AutocompleteSupportFragment)
            getSupportFragmentManager().findFragmentById(R.id.pickup);


    supportFragment1 = (AutocompleteSupportFragment) getSupportFragmentManager()
            .findFragmentById(R.id.drop);

    //Initialize the Fields to get Latitude and Langitude and name of the selected place.
    supportFragment.setPlaceFields(Arrays.asList(Place.Field.LAT_LNG, Place.Field.NAME));
    supportFragment1.setPlaceFields(Arrays.asList(Place.Field.LAT_LNG, Place.Field.NAME));

    //Placing Pickup Marker
    supportFragment.setOnPlaceSelectedListener(newPlaceSelectionListener(){
        @Override
        public void onPlaceSelected(@NonNull Place pickup) {

            Log.i("PickUP", "Place: " + pickup.getName() + ", ");
            String name = pickup.getName();
            LatLng latLng = pickup.getLatLng();

            MarkerOptions markerOptions = new MarkerOptions();
            markerOptions.position(latLng);
            markerOptions.title(name);
            markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
            gm.addMarker(markerOptions);

            gm.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 11));

        }


        @Override
        public void onError(@NonNull Status status) {
            Log.i("pickup", "An error occurred: " + status);

        }
    });

    //Placing Drop Marker
    supportFragment1.setOnPlaceSelectedListener(new PlaceSelectionListener() {
        @Override
        public void onPlaceSelected(@NonNull Place drop) {
            Log.i("Drop", "Place: " + drop.getName() + ", ");

            String name = drop.getName();
            LatLng latLng = drop.getLatLng();

            MarkerOptions markerOptions = new MarkerOptions();
            markerOptions.position(latLng);
            markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
            gm.addMarker(markerOptions);

            gm.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 11));

        }

        @Override
        public void onError(@NonNull Status status) {
        Log.i("drop", "An error occurred: " + status);

        }
    });
}

Вам все еще нужен ответ?

Amine 02.04.2019 16:19

@Амин, да, знаю

trickster 02.04.2019 16:25

Итак, текущий код для получения маркера захвата и сброса работает?

Amine 02.04.2019 16:38

Проверить ответ

Amine 02.04.2019 17:11

@Amine Извините, что не ответила раньше. Я был занят и даже не мог открыть stackoverflow. Я попробую и дам вам знать

trickster 03.04.2019 18:35

Не торопитесь и примите ответ, если он вам поможет :)

Amine 03.04.2019 18:41
0
6
698
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Предположим, что ваши LatLng объекты правильные и вам нужно только рисовать маршруты, вот что вам нужно сделать

Создайте вспомогательный класс с именем DirectionsJSONParser, который позже расшифрует вашу полилинию и предоставит вам список объектов широты и долготы.

Вот ссылка на этот класс НаправленияJSONParser

Для RetrofitClient это импорт, убедитесь, что вы добавили их

import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory; 

Добавьте это в свой файл build.gradle(app)

compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-scalars:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'

Создать модифицированный клиент

//this is a singleton of Retrofit
public class RetrofitClient {
private static Retrofit retrofit = null;

public static Retrofit getClient(String baseUrl) {
    if (retrofit == null) {
        retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(ScalarsConverterFactory.create())
                .build();
    }
 //return retrofit object
    return retrofit;
 }
}

Затем создайте интерфейс Google API.

public interface IGoogleAPI {

@GET
Call<String> getPath(@Url String url);
}

Создать общий класс

public class Common {
   public static String baseURL = "https://maps.googleapis.com/";
   public static IGoogleAPI getGoogleAPI() {
        return RetrofitClient.getClient(baseURL).create(IGoogleAPI.class);
    }
}

И последнее, но не менее важное: объявите переменную в своей деятельности.

IGoogleAPI mService;

Инициализируйте эту переменную в onCreate

mService = Common.getGoogleAPI();

Создайте метод для рисования маршрутов

private void getDirection() {

  String requestAPI;
    try {

        requestAPI = "https://maps.googleapis.com/maps/api/directions/json?" +
                "mode=driving&" +
                "transit_routing_preference=less_driving&" +
                "origin = " + pickupMarker.getLatitude() + "," + pickupMarker.getLongitude() +
                "&destination = " + dropMarker.getLatitude() + "," + dropMarker.getLongitude() + "&" +
                "key = " + getResources().getString(R.string.google_direction_apis);


        mService.getPath(requestAPI)
                .enqueue(new Callback<String>() {
                    @Override
                    public void onResponse(Call<String> call, retrofit2.Response<String> response) {
                        try {
                            new ParserTask().execute(response.body().toString());

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }

                    @Override
                    public void onFailure(Call<String> call, Throwable t) {

                    }
                });


    } catch (Exception e) {
        e.printStackTrace();
    }


}

Не забывайте

  1. Чтобы добавить модернизированные зависимости в ваш build.gradle
  2. Чтобы изменить свой API_KEY в файле requestString.

Это длинный код, поэтому, если у вас возникнут проблемы, сообщите мне.

Вызовите эту функцию getDirection() после того, как получите место перетаскивания.

РЕДАКТИРОВАТЬ

private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {

    ProgressDialog mDialog = new ProgressDialog(NavigationTracking.this);

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mDialog.setMessage("Executing...");
        mDialog.show();
    }

    @Override
    protected List<List<HashMap<String, String>>> doInBackground(String... strings) {
        JSONObject jObject;
        List<List<HashMap<String, String>>> routes = null;
        try {
            jObject = new JSONObject(strings[0]);
            DirectionJsonParser parser = new DirectionJsonParser();
            routes = parser.parse(jObject);
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return routes;
    }

    @Override
    protected void onPostExecute(List<List<HashMap<String, String>>> lists) {
        mDialog.dismiss();

        ArrayList points = null;
        PolylineOptions polylineOptions = null;

        Toast.makeText(NavigationTracking.this, "" + lists.size(), Toast.LENGTH_SHORT).show();

        for (int i = 0; i < lists.size(); i++) {

            points = new ArrayList();
            polylineOptions = new PolylineOptions();

            List<HashMap<String, String>> path = lists.get(i);

            for (int j = 0; j < path.size(); j++) {
                HashMap<String, String> point = path.get(j);

                double lat = Double.parseDouble(point.get("lat"));
                double lng = Double.parseDouble(point.get("lng"));

                LatLng position = new LatLng(lat, lng);

                points.add(position);

            }

            polylineOptions.addAll(points);
            polylineOptions.width(10);
            polylineOptions.color(Color.RED);
            // the shortest line between two points
            polylineOptions.geodesic(true);
        }

        if (polylineOptions != null) {
            direction = mMap.addPolyline(polylineOptions);
        }


    }
}

Объявить

private Polyline direction;

И добавьте этот тест перед звонком getDirection()

if (direction != null)
    direction.remove();

РЕДАКТИРОВАТЬ 2

Объявите 2 переменные LatLng перед onCreate() следующим образом:

LatLng pickupLoc;
LatLng dropLoc;

Затем, когда вы выбираете места, ваш код становится таким

//Placing Pickup Marker
supportFragment.setOnPlaceSelectedListener(newPlaceSelectionListener(){
    @Override
    public void onPlaceSelected(@NonNull Place pickup) {

        Log.i("PickUP", "Place: " + pickup.getName() + ", ");
        String name = pickup.getName();
        pickupLoc = pickup.getLatLng();

        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(pickupLoc );
        markerOptions.title(name);
        markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
        gm.addMarker(markerOptions);

        gm.moveCamera(CameraUpdateFactory.newLatLngZoom(pickupLoc, 11));

    }


    @Override
    public void onError(@NonNull Status status) {
        Log.i("pickup", "An error occurred: " + status);

    }
});


//Placing Drop Marker
supportFragment1.setOnPlaceSelectedListener(new PlaceSelectionListener() {
    @Override
    public void onPlaceSelected(@NonNull Place drop) {
        Log.i("Drop", "Place: " + drop.getName() + ", ");

        String name = drop.getName();
        dropLoc = drop.getLatLng();

        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(dropLoc );
        markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
        gm.addMarker(markerOptions);

        gm.moveCamera(CameraUpdateFactory.newLatLngZoom(dropLoc, 11));

        //here you test if your locations aren't null call getDirection() like this

        if (pickupLoc != null && dropLoc != null) {
            if (direction != null)
               direction.remove();

            getDirection();
        }

    }

    @Override
    public void onError(@NonNull Status status) {
    Log.i("drop", "An error occurred: " + status);

    }
});

Что такое ScalarsConverterFactory в RetrofitClient, выдает ошибку? Также pickupmarker и dropmarker в getDirection() являются полем AutocompleteSupportFragment? Я изменил их на свои ссылки, но getLatitude() и долгота стали красными.

trickster 04.04.2019 09:54

Какую ошибку вы получаете для ScalarsConverterFactory? pickupmarker и dropmarker — это типы Marker

Amine 04.04.2019 11:06

Я добавил зависимости, которые вы должны добавить, и импорт класса, посмотрите.

Amine 04.04.2019 11:09

RetrofitClient теперь не имеет ошибок. Я уже импортировал «com.squareup.retrofit2:retrofit:2.5.0», но не знал о двух других. Но я все еще получаю ошибки в supportFragment1.getLatitude() и долготе. Также ParserTask() тоже неразрешим.

trickster 04.04.2019 12:11

Где вы видите supportFragment1.getLatitude() в моем коде или даже в вашем?

Amine 04.04.2019 12:14

Вы правы насчет ParserTask Извините, я забыл добавить этот метод, потому что мой проект такой большой, что я отредактировал свой ответ.

Amine 04.04.2019 12:16

В моем проекте нет пикапмаркера. Я думал, что pickupmarker - это объявление AutoCompleteFragment.

trickster 04.04.2019 12:27

Вот ваш код, который у вас есть supportFragment.setOnPlaceSelectedListener, внутри этой функции у вас есть LatLng latLng = pickup.getLatLng(); и LatLng latLng = drop.getLatLng();, верно? Сделайте их глобальными переменными и используйте вот так latLng.getLatitude(), понятно? Если нет, я отредактирую весь код для вас.

Amine 04.04.2019 12:30

только часть об объявлении их как глобальной переменной

trickster 04.04.2019 12:55

Ошибка все еще существует даже после объявления их глобальными

trickster 04.04.2019 13:20

Извините, что беспокою вас, Амин, но не могли бы вы помочь мне с этим, поскольку у него все еще та же проблема?

trickster 15.04.2019 10:50

В чем проблема брат?

Amine 15.04.2019 15:39

Проблема getLatitude() в droploc.getLatitude() и pickuploc красного цвета в getdirection. Я не могу сослаться droploc и pickuploc на getLatitude() и getLongitude(). Я могу видеть только getClass(), latitude и longitude.

trickster 16.04.2019 07:36

В коде нет функции dropLoc.getLatitude(), внимательно прочитайте. Это drop.getLatitude(), в который вставляется экземпляр типа Place.

Amine 16.04.2019 11:05

В Редактировании 2, которое вы дали, вы назначили droploc и pickuploc глобальными переменными, которые являются маркерами, верно? Я сослался на те, что в String requestAPI в методе getDirection(), как вы и указали.

trickster 16.04.2019 11:20

Таким образом, ответ @Amine в основном правильный, но требуются небольшие изменения, которые я даю здесь:

private void getDirection() {

String requestAPI;
try {

    requestAPI = "https://maps.googleapis.com/maps/api/directions/json?" +
            "mode=driving&" +
            "transit_routing_preference=less_driving&" +
            "origin = " + pickuploc.latitude() + "," + 
             pickuploc.longitude() +
            "&destination = " + droploc.latitude() + "," + 
             droploc.longitude() + "&" +
            "key = " + getResources().getString(R.string.google_direction_apis);

             /*If you get "PolylineOptions cannot be null" error and app crashes 
             while trying to draw polyline then try pasting your API 
             key in string directly like this "key=somekey". Though only for testing. */

             mService.getPath(requestAPI)
            .enqueue(new Callback<String>() {
                @Override
                public void onResponse(Call<String> call, retrofit2.Response<String> 
             response) {
                    try {
                        new ParserTask().execute(response.body().toString());

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onFailure(Call<String> call, Throwable t) {

                }
            });


               } catch (Exception e) {
                 e.printStackTrace();
}


}

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