Перемещение и отображение вида камеры вождения на картах Google - PullRequest
2 голосов
/ 18 октября 2019

Я добавил текущее местоположение через карту маршрутизации Google с помощью

        Routing routing = new Routing.Builder()
            .travelMode(Routing.TravelMode.DRIVING)
            .key(getResources().getString(R.string.google_maps_api))
            .withListener(this)
            .waypoints(new LatLng(mLastKnownLocation.getLatitude(), mLastKnownLocation.getLongitude()), site_location)
            .alternativeRoutes(false)
            .build();
    routing.execute();



   @Override
public void onRoutingSuccess(ArrayList<Route> route, int shortestRouteIndex) {

    if (polylines.size() > 0) {
        for (Polyline poly : polylines) {
            poly.remove();
        }
    }

    polylines = new ArrayList<>();
    //add route(s) to the map.
    for (int i = 0; i < route.size(); i++) {

        //In case of more than 5 alternative routes
        int colorIndex = i % COLORS.length;

        PolylineOptions polyOptions = new PolylineOptions();
        polyOptions.color(getResources().getColor(COLORS[colorIndex]));
        polyOptions.width(10 + i * 13);
        polyOptions.addAll(route.get(i).getPoints());
        Polyline polyline = googleMap.addPolyline(polyOptions);
        polylines.add(polyline);

        int distance = route.get(i).getDistanceValue();
        if (distance < 1000){
            totalKm.setText( distance+" Metres");
        }else {
            totalKm.setText( (distance/1000) +" km");

        }
    }

    LatLngBounds.Builder builder = new LatLngBounds.Builder();
    builder.include(new LatLng(mLastKnownLocation.getLatitude(), mLastKnownLocation.getLongitude()));
    builder.include(site_marker.getPosition());
    LatLngBounds bounds = builder.build();
    CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 100);
    googleMap.animateCamera(cu);

}

Это показывает направление движения, например

enter image description here

Ноя пытаюсь отобразить значок вождения карты Google по умолчанию в увеличенном виде, например

enter image description here

Как мне добавить такую ​​карту, сохраняя при этом полилинии впоказать вид вождения.

Ответы [ 3 ]

3 голосов
/ 25 октября 2019

Android не предоставляет View, как Directional View (изображение 2) для разработки. Если вы хотите использовать тот же View, вы можете запустить приложение карты по умолчанию из своего приложения, передав исходное местоположение иместо назначения, как это.

Intent intent = new Intent(android.content.Intent.ACTION_VIEW, 
    Uri.parse("http://maps.google.com/maps?saddr=20.344,34.34&daddr=20.5666,45.345"));
startActivity(intent);

Используя Android по умолчанию MapView, Вы можете добавлять полилинии только между двумя местоположениями с маркерами (Вы можете видеть это во многих известных приложениях доставки). Масштабирование камерыподдерживается MapView, и вы также можете наклонять (наклонять) карту, но это не даст точного результата.

2 голосов
/ 25 октября 2019

Джинеш Фрэнсис совершенно прав в своем ответе: вы должны либо запустить приложение Google Maps по умолчанию с намерением, либо изменить стандарт MapView (или MapFragment).

TLDR;

Если вы выбрали второй способ - самый простой подход - использовать стандартные классы API Google Карт Google для создания представления, как в вашем примере (другой способсоздать MapView пользовательское представление на основе ).

Сначала внимательно прочитайте стр. 3.2.4 Ограничения в отношении неправомерного использования служб (d) из Условия использования Google Maps Platform :

(d) Нет ReСоздание продуктов или функций Google. Заказчик не будет использовать Сервисы для создания продукта или сервиса с функциями, которые по существу похожи или воссоздают функции другого продукта или сервиса Google. Продукт или услуга клиента должны содержать существенную, независимую ценность и функции, выходящие за рамки продуктов или услуг Google. Например, Клиент не будет: (i) повторно распространять Основные услуги Карт Google или выдавать их, как если бы они были услугами Клиента;(ii) создать замену базовых сервисов Google Maps, Google Maps или мобильных приложений Google Maps или их функций;(iii) использовать основные службы Карт Google в списках или службе каталогов или для создания или дополнения рекламного продукта;(iv) объединить данные из API направлений, API геолокации и SDK Maps для Android для создания функций навигации в реальном времени, практически аналогичных функциональности, предоставляемой мобильным приложением Google Maps для Android.

иесли вы не нарушаете Условия предоставления услуг, вы можете делать то, что вы хотите, с помощью следующих шагов / задач:

1) получить текущее местоположение пользователя;

2) получить сегмент маршрута маршрута, ближайший к текущему местоположению пользователя(поскольку местоположение пользователя редко бывает точно на дороге);

3) получить азимут (азимут) этого сегмента;

4) показать карту с маршрутом маршрута и маркером текущего положения пользователя с соответствующим наклоном ивращение в зависимости от направления сегмента пути.

Задача 1 может быть решена, как в this ответе Axxiss :

private final LocationListener mLocationListener = new LocationListener() {
    @Override
    public void onLocationChanged(final Location location) {
        //your code here
    }
};

Задача 2 может быть решена с помощью PolyUtil.isLocationOnPath(), как в этот ответ :

private LatLng getMarkerProjectionOnSegment(LatLng carPos, List<LatLng> segment, Projection projection) {
    LatLng markerProjection = null;

    Point carPosOnScreen = projection.toScreenLocation(carPos);
    Point p1 = projection.toScreenLocation(segment.get(0));
    Point p2 = projection.toScreenLocation(segment.get(1));
    Point carPosOnSegment = new Point();

    float denominator = (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y);
    // p1 and p2 are the same
    if (Math.abs(denominator) <= 1E-10) {
        markerProjection = segment.get(0);
    } else {
        float t = (carPosOnScreen.x * (p2.x - p1.x) - (p2.x - p1.x) * p1.x
                + carPosOnScreen.y * (p2.y - p1.y) - (p2.y - p1.y) * p1.y) / denominator;
        carPosOnSegment.x = (int) (p1.x + (p2.x - p1.x) * t);
        carPosOnSegment.y = (int) (p1.y + (p2.y - p1.y) * t);
        markerProjection = projection.fromScreenLocation(carPosOnSegment);
    }    
    return markerProjection;
}

Задача 3 может быть решена с помощью кода, подобногочто:

private float getBearing(LatLng begin, LatLng end) {
    double dLon = (end.longitude - begin.longitude);
    double x = Math.sin(Math.toRadians(dLon)) * Math.cos(Math.toRadians(end.latitude));
    double y = Math.cos(Math.toRadians(begin.latitude))*Math.sin(Math.toRadians(end.latitude))
            - Math.sin(Math.toRadians(begin.latitude))*Math.cos(Math.toRadians(end.latitude)) * Math.cos(Math.toRadians(dLon));
    double bearing = Math.toDegrees((Math.atan2(x, y)));
    return (float) bearing;
}

, где begin иend - начало и конец текущего отрезка пути.

Задача 4 может быть решена с помощью кода, подобного следующему:

, в качестве маркера вы можете использовать вектор, нарисованный из ориентированной на север стрелки, например:

User location marker

ic_up_arrow_circle.xml (также вы можете настроить прозрачность и цвета):

<vector android:height="24dp" android:viewportHeight="93.934"
    android:viewportWidth="93.934"
    android:width="24dp"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <path
        android:fillColor="#8fFF0000"
        android:pathData="m0,46.9666c0,25.939 21.028,46.967 46.967,46.967c25.939,-0 46.967,-21.028 46.967,-46.967c0,-25.939 -21.027,-46.967 -46.967,-46.967c-25.939,-0 -46.967,21.028 -46.967,46.967zM78.262,67.4396l-31.295,-16.845l-31.295,16.845l31.295,-51.614l31.295,51.614z"
    />

    <path
        android:fillColor="#FFFFFF"
        android:pathData="M78.262,67.4396l-31.295,-16.845l-31.295,16.845l31.295,-51.614l31.295,51.614z"
        />
</vector>

, и вы можете разместить его на карте с помощьюкод такой:

public Marker addDirectionMarker(LatLng latLng, float angle) {
    Drawable circleDrawable = ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_up_arrow_in_circle);
    BitmapDescriptor markerIcon = getMarkerIconFromDrawable(circleDrawable, 150, 150);

    return mGoogleMap.addMarker(new MarkerOptions()
            .position(latLng)
            .anchor(0.5f, 0.5f)
            .rotation(angle)
            .flat(true)
            .icon(markerIcon)
    );
}

где 150 - размер маркера в пикселях. NB! Вам нужен маркер flat для его поворота и наклона с картой и 0.5f для перемещения маркера точно по его центральной точке.

, тогда вы можете показать все это на карте:

...
CameraPosition cameraPosition = new CameraPosition.Builder()
        .target(userPosition)
        .tilt(tilt)
        .zoom(zoom)
        .bearing(bearing)
        .build();
mGoogleMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
...

Но если вы сделаете только то, что маркер текущей позиции пользователя появился в центре экрана (потому что GoogleMap.moveCamera() устанавливает центрточно на .target()). Поэтому, чтобы избежать этого, вам нужно слегка сместить карту вниз - в этом случае в нижней части экрана должен появиться маркер местоположения пользователя. Для смещения центра карты необходимо получить координаты экрана текущего центра карты, затем изменить y координату и получить новый центр экрана. Примерно так:

...
LatLng mapCenter = mGoogleMap.getCameraPosition().target;
Projection projection = mGoogleMap.getProjection();
Point centerPoint = projection.toScreenLocation(mapCenter);

DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int displayHeight = displayMetrics.heightPixels;

centerPoint.y = centerPoint.y - (int) (displayHeight / 4.5);  // move center down for approx 22%

LatLng newCenterPoint = projection.fromScreenLocation(centerPoint);

mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(newCenterPoint, zoom));
...

И со всем этим, для вашего маршрута (с zoom = 15 и tilt = 50) вы должны получить что-то вроде этого:

Directions view

Как видите, путь маршрута не совсем на дороге, поэтому вам нужно получить точки маршрута более точно, чем ответ API Directions. Вы можете получить это, например, через API Карт Google для дорог деталь Привязка к дороге , которая

возвращает наиболее подходящую геометрию дороги для заданного набора координат GPS,Эта услуга берет до 100 точек GPS, собранных по маршруту, и повторноповорачивает аналогичный набор данных с точками, привязанными к наиболее вероятным дорогам, по которым ехал автомобиль.

, как в , что отвечает. Если ваш маршрут содержит больше точек, вам нужно разделить на части по 100 точек и обработать их отдельно (также API привязки к дороге имеет 2500 запросов в день на пользователя (IP) и ограничение 10 запросов в секунду).

И как Джасвант Сингх ответил вам:

необходимо установить пользовательский маркер (со значком такой же, как у синей стрелки) на вашем текущем местоположении и переместить егов новое местоположение каждый раз, когда вызывается обратный вызов onLocationChanged () (также анимируйте камеру в этом новом местоположении).

Кроме того, вам нужно выбрать zoom и tilt свойства в соответствии снапример, текущая скорость пользователя: когда пользователь едет быстрее tilt -> 0. И так далее. Это не простая задача.

0 голосов
/ 25 октября 2019

В дополнение к ответу Джинеша, если вы все еще хотите добавить этот маркер для разработки, вам нужно установить пользовательский маркер (со значком такой же, как у синей стрелки) на вашем текущем местоположении и перемещать его на новое место каждый раз, когда тамвызывается обратный вызов onLocationChanged () (также анимирует камеру в этом новом месте). И немного наклоните карту, чтобы получить точный вид навигационного представления карт Google, хотя вы не сможете использовать все функциональные возможности, но стоит попробовать.

...