Navigation SDK는 현재 일부 고객만 사용할 수 있습니다. 자세한 내용은 영업팀에 문의하세요.
새로운 지도 스타일 지정 기능이 곧 Google Maps Platform에 도입될 예정입니다. 이번 지도 스타일 지정 업데이트에는 새로운 기본 색상 팔레트가 추가되었으며 지도 환경 및 사용성이 개선되었습니다. 모든 지도 스타일은 2025년 3월에 자동으로 업데이트됩니다. 사용 가능 여부 및 이전에 선택한 방법에 대한 자세한 내용은 Google Maps Platform의 새 지도 스타일을 참고하세요.
지도 UI 컨트롤은 탐색 뷰 상단에 있습니다. 이
Android용 Navigation SDK가 맞춤 컨트롤의 위치를 자동으로 변경합니다.
기본 제공 레이아웃이 변경될 때 레이아웃의 각 위치에 대해
만들 수 있습니다. 맞춤 컨트롤은 하나의 UI 요소일 수 있습니다. 또는 디자인이 자체 디자인인 경우
더 많이 필요하다면 여러 UI 요소와 함께 ViewGroup를 사용할 수 있습니다.
예를 들어 아래 이미지는 UI 컨트롤의 다양한 위치의 예를 보여줍니다.
승차 중에 차량 공유 운전사에게 탑승자의 위치를 알립니다.
맞춤 보조 헤더 추가
기본적으로 탐색 모드의 화면 레이아웃은 보조 화면의 위치를 제공합니다.
헤더 아래에 있습니다. 이 보조 헤더는
사용할 수 있습니다. 앱에서 이 보조 헤더를 사용할 수 있습니다.
레이아웃을 지정할 수 있습니다. 이 기능을 사용하면
컨트롤은 기본 보조 헤더 콘텐츠를 모두 다룹니다. 내비게이션 뷰에
해당 배경은 보조 헤더로 덮인 제자리에 유지됩니다.
앱에서 맞춤 컨트롤을 삭제하면 모든 기본 보조 헤더에서
표시됩니다.
맞춤 보조 헤더 위치는 상단 가장자리를
사용할 수 있습니다 이 위치는 portrait mode에서만 지원됩니다. 포함
landscape mode, 보조 헤더를 사용할 수 없고 레이아웃은 사용할 수 없음
있습니다.
탐색 뷰 또는 프래그먼트에서 setCustomControl 메서드를 호출합니다.
컨트롤과 사용할 위치를 지정합니다.
를 통해 개인정보처리방침을 정의할 수 있습니다.
다음 예는ViewSupportNavigationFragment:
private SupportNavigationFragment mNavFragment;
mNavFragment = (SupportNavigationFragment)
getFragmentManager().findFragmentById(R.id.navigation_fragment);
// Create the custom control view.
MyCustomView myCustomView = new MyCustomView();
// Add the custom control to the bottom end corner of the layout.
mNavFragment.setCustomControl(myCustomView, CustomControlPosition.
BOTTOM_END_BELOW);
맞춤 컨트롤 삭제
맞춤 컨트롤을 삭제하려면 setCustomControl 메서드를 사용하고
위치를 변경합니다.
Android용 Navigation SDK는 설정 중에 표시되는 UI 액세서리를 제공합니다.
Android용 Google 지도 애플리케이션 탐색과 유사한 탐색 기능을 제공합니다.
컨트롤의 공개 상태나 시각적 모양을 다음과 같이 조정할 수 있습니다.
이 섹션에 설명되어 있습니다. 여기에서 변경하면
탐색 세션입니다.
package com.example.navsdkcustomization;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import com.google.android.libraries.navigation.Camera;
import com.google.android.libraries.navigation.LatLng;
import com.google.android.libraries.navigation.ListenableResultFuture;
import com.google.android.libraries.navigation.Marker;
import com.google.android.libraries.navigation.MarkerOptions;
import com.google.android.libraries.navigation.NavigationApi;
import com.google.android.libraries.navigation.NavigationMap;
import com.google.android.libraries.navigation.Navigator;
import com.google.android.libraries.navigation.SimulationOptions;
import com.google.android.libraries.navigation.StylingOptions;
import com.google.android.libraries.navigation.SupportNavigationFragment;
import com.google.android.libraries.navigation.Waypoint;
/**
* An activity that displays a map and a customized navigation UI.
*/
public class NavigationActivityCustomization extends AppCompatActivity {
private static final String TAG = NavigationActivityCustomization.class.getSimpleName();
private Navigator mNavigator;
private SupportNavigationFragment mNavFragment;
private NavigationMap mMap;
// Define the Sydney Opera House by specifying its place ID.
private static final String SYDNEY_OPERA_HOUSE = "ChIJ3S-JXmauEmsRUcIaWtf4MzE";
// Set fields for requesting location permission.
private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
private boolean mLocationPermissionGranted;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize the Navigation SDK.
initializeNavigationSdk();
}
/**
* Starts the Navigation SDK and sets the camera to follow the device's location.
* Calls the navigateToPlace() method when the navigator is ready.
*/
private void initializeNavigationSdk() {
/*
* Request location permission, so that we can get the location of the
* device. The result of the permission request is handled by a callback,
* onRequestPermissionsResult.
*/
if (ContextCompat.checkSelfPermission(this.getApplicationContext(),
android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
} else {
ActivityCompat.requestPermissions(this,
new String[] { android.Manifest.permission.ACCESS_FINE_LOCATION },
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
}
if (!mLocationPermissionGranted) {
displayMessage("Error loading Navigation SDK: "
+ "The user has not granted location permission.");
return;
}
// Get a navigator.
NavigationApi.getNavigator(this, new NavigationApi.NavigatorListener() {
/**
* Sets up the navigation UI when the navigator is ready for use.
*/
@Override
public void onNavigatorReady(Navigator navigator) {
displayMessage("Navigator ready.");
mNavigator = navigator;
mNavFragment = (SupportNavigationFragment) getFragmentManager()
.findFragmentById(R.id.navigation_fragment);
// Navigate to a place, specified by Place ID.
navigateToPlace(SYDNEY_OPERA_HOUSE);
}
/**
* Handles errors from the Navigation SDK.
* @param errorCode The error code returned by the navigator.
*/
@Override
public void onError(@NavigationApi.ErrorCode int errorCode) {
switch (errorCode) {
case NavigationApi.ErrorCode.NOT_AUTHORIZED:
displayMessage("Error loading Navigation SDK: Your API key is "
+ "invalid or not authorized to use the Navigation SDK.");
break;
case NavigationApi.ErrorCode.TERMS_NOT_ACCEPTED:
displayMessage("Error loading Navigation SDK: User did not accept "
+ "the Navigation Terms of Use.");
break;
case NavigationApi.ErrorCode.NETWORK_ERROR:
displayMessage("Error loading Navigation SDK: Network error.");
break;
case NavigationApi.ErrorCode.LOCATION_PERMISSION_MISSING:
displayMessage("Error loading Navigation SDK: Location permission "
+ "is missing.");
break;
default:
displayMessage("Error loading Navigation SDK: " + errorCode);
}
}
});
}
/**
* Customizes the navigation UI and the map.
*/
private void customizeNavigationUI() {
// Set custom colors for the navigator.
mNavFragment.setStylingOptions(new StylingOptions()
.primaryDayModeThemeColor(0xff1A237E)
.secondaryDayModeThemeColor(0xff3F51B5)
.primaryNightModeThemeColor(0xff212121)
.secondaryNightModeThemeColor(0xff424242)
.headerLargeManeuverIconColor(0xffffff00)
.headerSmallManeuverIconColor(0xffffa500)
.headerNextStepTypefacePath("/system/fonts/NotoSerif-BoldItalic.ttf")
.headerNextStepTextColor(0xff00ff00)
.headerNextStepTextSize(20f)
.headerDistanceTypefacePath("/system/fonts/NotoSerif-Italic.ttf")
.headerDistanceValueTextColor(0xff00ff00)
.headerDistanceUnitsTextColor(0xff0000ff)
.headerDistanceValueTextSize(20f)
.headerDistanceUnitsTextSize(18f)
.headerInstructionsTypefacePath("/system/fonts/NotoSerif-BoldItalic.ttf")
.headerInstructionsTextColor(0xffffff00)
.headerInstructionsFirstRowTextSize(24f)
.headerInstructionsSecondRowTextSize(20f)
.headerGuidanceRecommendedLaneColor(0xffffa500));
// Get the map.
mMap = mNavFragment.getMap();
// Turn off the traffic layer on the map.
mMap.setTrafficEnabled(false);
// Place a marker at the final destination.
if (mNavigator.getCurrentRouteSegment() != null) {
LatLng destinationLatLng = mNavigator.getCurrentRouteSegment()
.getDestinationLatLng();
Bitmap destinationMarkerIcon = BitmapFactory.decodeResource(
getResources(), R.drawable.ic_person_pin_48dp);
mMap.addMarker(new MarkerOptions()
.position(destinationLatLng)
.icon(destinationMarkerIcon)
.title("Destination marker"));
// Listen for a tap on the marker.
mMap.setOnMarkerClickListener(new NavigationMap.OnMarkerClickListener() {
@Override
public void onMarkerClick(Marker marker) {
displayMessage("Marker tapped: "
+ marker.getTitle() + ", at location "
+ marker.getPosition().latitude + ", "
+ marker.getPosition().longitude);
}
});
}
// Set the camera to follow the device location with 'TILTED' driving view.
mNavFragment.getCamera().followMyLocation(Camera.Perspective.TILTED);
}
/**
* Requests directions from the user's current location to a specific place (provided
* by the Google Places API).
*/
private void navigateToPlace(String placeId) {
Waypoint destination;
try {
destination = Waypoint.fromPlaceId(placeId, null);
} catch (Waypoint.UnsupportedPlaceIdException e) {
displayMessage("Error starting navigation: Place ID is not supported.");
return;
}
// Create a future to await the result of the asynchronous navigator task.
ListenableResultFuture<Navigator.RouteStatus> pendingRoute =
mNavigator.setDestination(destination);
// Define the action to perform when the SDK has determined the route.
pendingRoute.setOnResultListener(
new ListenableResultFuture.OnResultListener<Navigator.RouteStatus>() {
@Override
public void onResult(Navigator.RouteStatus code) {
switch (code) {
case OK:
// Hide the toolbar to maximize the navigation UI.
if (getActionBar() != null) {
getActionBar().hide();
}
// Customize the navigation UI.
customizeNavigationUI();
// Enable voice audio guidance (through the device speaker).
mNavigator.setAudioGuidance(
Navigator.AudioGuidance.VOICE_ALERTS_AND_GUIDANCE);
// Simulate vehicle progress along the route for demo/debug builds.
if (BuildConfig.DEBUG) {
mNavigator.getSimulator().simulateLocationsAlongExistingRoute(
new SimulationOptions().speedMultiplier(5));
}
// Start turn-by-turn guidance along the current route.
mNavigator.startGuidance();
break;
// Handle error conditions returned by the navigator.
case NO_ROUTE_FOUND:
displayMessage("Error starting navigation: No route found.");
break;
case NETWORK_ERROR:
displayMessage("Error starting navigation: Network error.");
break;
case ROUTE_CANCELED:
displayMessage("Error starting navigation: Route canceled.");
break;
default:
displayMessage("Error starting navigation: "
+ String.valueOf(code));
}
}
});
}
/**
* Handles the result of the request for location permissions.
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[],
@NonNull int[] grantResults) {
mLocationPermissionGranted = false;
switch (requestCode) {
case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
// If request is canceled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
}
}
}
}
/**
* Shows a message on screen and in the log. Used when something goes wrong.
* @param errorMessage The message to display.
*/
private void displayMessage(String errorMessage) {
Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();
Log.d(TAG, errorMessage);
}
}
private SupportNavigationFragment mNavFragment;
mNavFragment = (SupportNavigationFragment) getFragmentManager()
.findFragmentById(R.id.navigation_fragment);
// Set the styling options on the fragment.
mNavFragment.setStylingOptions(new StylingOptions()
.primaryDayModeThemeColor(0xff1A237E)
.secondaryDayModeThemeColor(0xff3F51B5)
.primaryNightModeThemeColor(0xff212121)
.secondaryNightModeThemeColor(0xff424242)
.headerLargeManeuverIconColor(0xffffff00)
.headerSmallManeuverIconColor(0xffffa500)
.headerNextStepTypefacePath("/system/fonts/NotoSerif-BoldItalic.ttf")
.headerNextStepTextColor(0xff00ff00)
.headerNextStepTextSize(20f)
.headerDistanceTypefacePath("/system/fonts/NotoSerif-Italic.ttf")
.headerDistanceValueTextColor(0xff00ff00)
.headerDistanceUnitsTextColor(0xff0000ff)
.headerDistanceValueTextSize(20f)
.headerDistanceUnitsTextSize(18f)
.headerInstructionsTypefacePath("/system/fonts/NotoSerif-BoldItalic.ttf")
.headerInstructionsTextColor(0xffffff00)
.headerInstructionsFirstRowTextSize(24f)
.headerInstructionsSecondRowTextSize(20f)
.headerGuidanceRecommendedLaneColor(0xffffa500));
교통정보 레이어 사용 중지
사용
GoogleMap.setTrafficEnabled() 드림
지도의 교통정보 레이어를 사용 설정 또는 사용 중지합니다. 이 설정은
지도에 표시되는 교통량의 밀도를 나타냅니다. 하지만
네비게이터가 표시한 경로의 교통정보 표시에 영향을 미칠 수 있습니다.
private GoogleMap mMap;
// Get the map, and when the async call returns, setTrafficEnabled
// (callback will be on the UI thread)
mMap = mNavFragment.getMapAsync(navMap -> navMap.setTrafficEnabled(false));
신호등 및 정지 표지판 켜기
지도 UI에서 신호등을 활성화하고 표지판을 정지할 수 있습니다. 이 기능을 사용하면
사용자는 기기의 방향에 신호등 또는 정지 표지판 아이콘을
더 효율적이고 정확한 이동을 위해 더 나은 상황 정보를 제공합니다.
기본적으로 신호등과 정지 표지판은
Navigation SDK를 지원합니다. 이 기능을 사용 설정하려면 다음을 호출합니다.
DisplayOptions 드림
하나씩 살펴보겠습니다
DisplayOptions displayOptions =
new DisplayOptions().showTrafficLights(true).showStopSigns(true);
맞춤 마커 추가
Android용 Navigation SDK에서 이제 마커에 Google Maps API를 사용합니다. 다음으로 이동:
Maps API 문서
를 참조하세요.
플로팅 텍스트
플로팅 텍스트는 앱의 어느 위치에나 플로팅 텍스트를 추가할 수 있습니다. 단, 텍스트가
Google 기여 분석 Navigation SDK는 텍스트 고정을 지원하지 않습니다.
지도의 위도/경도나 라벨에 추가합니다. 정보로 이동
Windows에 대해 자세히 알아보기
확인할 수 있습니다
AUTO Navigation SDK가
기기 위치와 현지 시간에 따라 적절한 모드로 전환합니다.
FORCE_NIGHT: 야간 모드가 강제로 사용 설정됩니다.
FORCE_DAY: 주간 모드를 강제로 사용 설정합니다.
다음 예는 내비게이션 내에서 야간 모드를 강제로 사용 설정하는 방법을 보여줍니다.
프래그먼트:
// Force night mode on.
mNavFragment.setForceNightMode(FORCE_NIGHT);
경로 목록 표시
먼저 뷰를 만들어 계층 구조에 추가합니다.
void setupDirectionsListView() {
// Create the view.
DirectionsListView directionsListView = new DirectionsListView(getApplicationContext());
// Add the view to your view hierarchy.
ViewGroup group = findViewById(R.id.directions_view);
group.addView(directionsListView);
// Add a button to your layout to close the directions list view.
ImageButton button = findViewById(R.id.close_directions_button); // this button is part of the container we hide in the next line.
button.setOnClickListener(
v -> findViewById(R.id.directions_view_container).setVisibility(View.GONE));
}
수명 주기 이벤트를 이와 마찬가지로 DirectionsListView에 전달해야 합니다.
NavigationView와(과) 함께합니다. 예를 들면 다음과 같습니다.
사용자 인터페이스가 너무 많은 정보로 복잡해지면
기본값 (2개)보다 적은 대체 경로를 표시하여 혼잡성 감소
대체 경로가 아예 표시되지 않도록 합니다. 이 옵션은
RoutingOptions.alternateRoutesStrategy()를 호출하여 경로를 가져옵니다.
메서드를 다음 열거 값 중 하나로 대체합니다.
열거형 값
설명
AlternateRoutesStrategy.SHOW_ALL
기본값입니다. 최대 2개의 대체 경로를 표시합니다.
AlternateRoutesStrategy.SHOW_ONE
1개의 대체 경로를 표시합니다 (사용 가능한 경우).
AlternateRoutesStrategy.SHOW_NONE
대체 경로를 숨깁니다.
다음 코드 예는 대체 경로를 모두 숨기는 방법을 보여줍니다.
RoutingOptions routingOptions = new RoutingOptions();
routingOptions.alternateRoutesStrategy(AlternateRoutesStrategy.SHOW_NONE);
navigator.setDestinations(destinations, routingOptions, displayOptions);
이동 진행률 표시줄
이동 진행률 표시줄은 오른쪽 후행 가장자리에 표시되는 세로 막대입니다.
을 표시해야 합니다. 이 기능을 사용 설정하면
사용자의 목적지 및 현재 위치와 함께 전체 이동 경로가 표시됩니다.
사용자는 이 서비스를 통해 향후 발생할 수 있는 문제(예:
교통체증으로 파악할 수 있습니다. 그런 다음 다음과 같은 경우 이동 경로를 다시 지정할 수 있습니다.
있습니다. 사용자가 경로를 다시 변경하면 진행률 표시줄이 새 경로처럼
여행이 시작되었음을 알 수 있습니다.