Я хочу нарисовать маршрут на карте, когда я помещаю маркер пункта назначения из панели поиска Места 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 Извините, что не ответила раньше. Я был занят и даже не мог открыть stackoverflow. Я попробую и дам вам знать
Не торопитесь и примите ответ, если он вам поможет :)
Предположим, что ваши 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();
}
}
Не забывайте
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() и долгота стали красными.
Какую ошибку вы получаете для ScalarsConverterFactory? pickupmarker и dropmarker — это типы Marker
Я добавил зависимости, которые вы должны добавить, и импорт класса, посмотрите.
RetrofitClient теперь не имеет ошибок. Я уже импортировал «com.squareup.retrofit2:retrofit:2.5.0», но не знал о двух других. Но я все еще получаю ошибки в supportFragment1.getLatitude() и долготе. Также ParserTask() тоже неразрешим.
Где вы видите supportFragment1.getLatitude() в моем коде или даже в вашем?
Вы правы насчет ParserTask Извините, я забыл добавить этот метод, потому что мой проект такой большой, что я отредактировал свой ответ.
В моем проекте нет пикапмаркера. Я думал, что pickupmarker - это объявление AutoCompleteFragment.
Вот ваш код, который у вас есть supportFragment.setOnPlaceSelectedListener, внутри этой функции у вас есть LatLng latLng = pickup.getLatLng(); и LatLng latLng = drop.getLatLng();, верно? Сделайте их глобальными переменными и используйте вот так latLng.getLatitude(), понятно? Если нет, я отредактирую весь код для вас.
только часть об объявлении их как глобальной переменной
Ошибка все еще существует даже после объявления их глобальными
Извините, что беспокою вас, Амин, но не могли бы вы помочь мне с этим, поскольку у него все еще та же проблема?
В чем проблема брат?
Проблема getLatitude() в droploc.getLatitude() и pickuploc красного цвета в getdirection. Я не могу сослаться droploc и pickuploc на getLatitude() и getLongitude(). Я могу видеть только getClass(), latitude и longitude.
В коде нет функции dropLoc.getLatitude(), внимательно прочитайте. Это drop.getLatitude(), в который вставляется экземпляр типа Place.
В Редактировании 2, которое вы дали, вы назначили droploc и pickuploc глобальными переменными, которые являются маркерами, верно? Я сослался на те, что в String requestAPI в методе getDirection(), как вы и указали.
Таким образом, ответ @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();
}
}
Вам все еще нужен ответ?