packagecom.example.navsdkmultidestination;importandroid.content.pm.PackageManager;importandroid.location.Location;importandroid.os.Bundle;importandroid.util.Log;importandroid.widget.Toast;importandroidx.annotation.NonNull;importandroidx.appcompat.app.AppCompatActivity;importandroidx.core.app.ActivityCompat;importandroidx.core.content.ContextCompat;importcom.google.android.gms.maps.GoogleMap.CameraPerspective;importcom.google.android.libraries.navigation.ArrivalEvent;importcom.google.android.libraries.navigation.ListenableResultFuture;importcom.google.android.libraries.navigation.NavigationApi;importcom.google.android.libraries.navigation.Navigator;importcom.google.android.libraries.navigation.RoadSnappedLocationProvider;importcom.google.android.libraries.navigation.SimulationOptions;importcom.google.android.libraries.navigation.SupportNavigationFragment;importcom.google.android.libraries.navigation.TimeAndDistance;importcom.google.android.libraries.navigation.Waypoint;importjava.util.ArrayList;importjava.util.List;/***AnactivitythatdisplaysamapandanavigationUI,guidingtheuserfromtheircurrentlocation*tomultipledestinations,alsoknownaswaypoints.*/publicclassNavigationActivityMultiDestinationextendsAppCompatActivity{privatestaticfinalStringTAG=NavigationActivityMultiDestination.class.getSimpleName();privatestaticfinalStringDISPLAY_BOTH="both";privatestaticfinalStringDISPLAY_TOAST="toast";privatestaticfinalStringDISPLAY_LOG="log";privateNavigatormNavigator;privateRoadSnappedLocationProvidermRoadSnappedLocationProvider;privateSupportNavigationFragmentmNavFragment;privatefinalList<Waypoint>mWaypoints=newArrayList<>();privateNavigator.ArrivalListenermArrivalListener;privateNavigator.RouteChangedListenermRouteChangedListener;privateNavigator.RemainingTimeOrDistanceChangedListenermRemainingTimeOrDistanceChangedListener;privateRoadSnappedLocationProvider.LocationListenermLocationListener;privateBundlemSavedInstanceState;privatestaticfinalStringKEY_JOURNEY_IN_PROGRESS="journey_in_progress";privatebooleanmJourneyInProgress=false;//Setfieldsforrequestinglocationpermission.privatestaticfinalintPERMISSIONS_REQUEST_ACCESS_FINE_LOCATION=1;privatebooleanmLocationPermissionGranted;/***Setsupthenavigatorwhentheactivityiscreated.**@paramsavedInstanceStateTheactivitystatebundle.*/@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);//Savethenavigatorstate,usedtodeterminewhetherajourneyisinprogress.mSavedInstanceState=savedInstanceState;if(mSavedInstanceState!=null && mSavedInstanceState.containsKey(KEY_JOURNEY_IN_PROGRESS)){mJourneyInProgress=(mSavedInstanceState.getInt(KEY_JOURNEY_IN_PROGRESS)!=0);}setContentView(R.layout.activity_main);//InitializetheNavigationSDK.initializeNavigationSdk();}/**Releasesnavigationlistenerswhentheactivityisdestroyed.*/@OverrideprotectedvoidonDestroy(){super.onDestroy();if((mJourneyInProgress) && (this.isFinishing())){mNavigator.removeArrivalListener(mArrivalListener);mNavigator.removeRouteChangedListener(mRouteChangedListener);mNavigator.removeRemainingTimeOrDistanceChangedListener(mRemainingTimeOrDistanceChangedListener);if(mRoadSnappedLocationProvider!=null){mRoadSnappedLocationProvider.removeLocationListener(mLocationListener);}displayMessage("OnDestroy: Released navigation listeners.",DISPLAY_LOG);}}/**Savesthestateoftheappwhentheactivityispaused.*/@OverrideprotectedvoidonSaveInstanceState(BundleoutState){super.onSaveInstanceState(outState);if(mJourneyInProgress){outState.putInt(KEY_JOURNEY_IN_PROGRESS,1);}else{outState.putInt(KEY_JOURNEY_IN_PROGRESS,0);}}/***StartstheNavigationSDKandsetsthecameratofollowthedevice's location. Calls the*navigateToPlaces()methodwhenthenavigatorisready.*/privatevoidinitializeNavigationSdk(){/**Requestlocationpermission,sothatwecangetthelocationofthe*device.Theresultofthepermissionrequestishandledbyacallback,*onRequestPermissionsResult.*/if(ContextCompat.checkSelfPermission(this.getApplicationContext(),android.Manifest.permission.ACCESS_FINE_LOCATION)==PackageManager.PERMISSION_GRANTED){mLocationPermissionGranted=true;}else{ActivityCompat.requestPermissions(this,newString[]{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.",DISPLAY_BOTH);return;}//Getanavigator.NavigationApi.getNavigator(this,newNavigationApi.NavigatorListener(){/**SetsupthenavigationUIwhenthenavigatorisreadyforuse.*/@OverridepublicvoidonNavigatorReady(Navigatornavigator){displayMessage("Navigator ready.",DISPLAY_BOTH);mNavigator=navigator;mNavFragment=(SupportNavigationFragment)getSupportFragmentManager().findFragmentById(R.id.navigation_fragment);//Setthecameratofollowthedevicelocationwith'TILTED'drivingview.mNavFragment.getMapAsync(googleMap-> googleMap.followMyLocation(CameraPerspective.TILTED));//Navigatetothespecifiedplaces.navigateToPlaces();}/***HandleserrorsfromtheNavigationSDK.**@paramerrorCodeTheerrorcodereturnedbythenavigator.*/@OverridepublicvoidonError(@NavigationApi.ErrorCodeinterrorCode){switch(errorCode){caseNavigationApi.ErrorCode.NOT_AUTHORIZED:displayMessage("Error loading Navigation SDK: Your API key is "+"invalid or not authorized to use the Navigation SDK.",DISPLAY_BOTH);break;caseNavigationApi.ErrorCode.TERMS_NOT_ACCEPTED:displayMessage("Error loading Navigation SDK: User did not accept "+"the Navigation Terms of Use.",DISPLAY_BOTH);break;caseNavigationApi.ErrorCode.NETWORK_ERROR:displayMessage("Error loading Navigation SDK: Network error.",DISPLAY_BOTH);break;caseNavigationApi.ErrorCode.LOCATION_PERMISSION_MISSING:displayMessage("Error loading Navigation SDK: Location permission "+"is missing.",DISPLAY_BOTH);break;default:displayMessage("Error loading Navigation SDK: "+errorCode,DISPLAY_BOTH);}}});}/**Requestsdirectionsfromtheuser's current location to a list of waypoints. */privatevoidnavigateToPlaces(){//Setupawaypointforeachplacethatwewanttogoto.createWaypoint("ChIJq6qq6jauEmsRJAf7FjrKnXI","Sydney Star");createWaypoint("ChIJ3S-JXmauEmsRUcIaWtf4MzE","Sydney Opera House");createWaypoint("ChIJLwgLFGmuEmsRzpDhHQuyyoU","Sydney Conservatorium of Music");//Ifthisjourneyisalreadyinprogress,noneedtorestartnavigation.//Thiscanhappenwhentheuserrotatesthedevice,orsendstheapptothebackground.if(mSavedInstanceState!=null
&& mSavedInstanceState.containsKey(KEY_JOURNEY_IN_PROGRESS)
&& mSavedInstanceState.getInt(KEY_JOURNEY_IN_PROGRESS)==1){return;}//Createafuturetoawaittheresultoftheasynchronousnavigatortask.ListenableResultFuture<Navigator.RouteStatus> pendingRoute=mNavigator.setDestinations(mWaypoints);//DefinetheactiontoperformwhentheSDKhasdeterminedtheroute.pendingRoute.setOnResultListener(newListenableResultFuture.OnResultListener<Navigator.RouteStatus>(){@OverridepublicvoidonResult(Navigator.RouteStatuscode){switch(code){caseOK:mJourneyInProgress=true;//HidethetoolbartomaximizethenavigationUI.if(getActionBar()!=null){getActionBar().hide();}//Registersomelistenersfornavigationevents.registerNavigationListeners();//Displaythetimeanddistancetoeachwaypoint.displayTimesAndDistances();//Enablevoiceaudioguidance(throughthedevicespeaker).mNavigator.setAudioGuidance(Navigator.AudioGuidance.VOICE_ALERTS_AND_GUIDANCE);//Simulatevehicleprogressalongtheroutefordemo/debugbuilds.if(BuildConfig.DEBUG){mNavigator.getSimulator().simulateLocationsAlongExistingRoute(newSimulationOptions().speedMultiplier(5));}//Startturn-by-turnguidancealongthecurrentroute.mNavigator.startGuidance();break;//Handleerrorconditionsreturnedbythenavigator.caseNO_ROUTE_FOUND:displayMessage("Error starting navigation: No route found.",DISPLAY_BOTH);break;caseNETWORK_ERROR:displayMessage("Error starting navigation: Network error.",DISPLAY_BOTH);break;caseROUTE_CANCELED:displayMessage("Error starting navigation: Route canceled.",DISPLAY_BOTH);break;default:displayMessage("Error starting navigation: "+String.valueOf(code),DISPLAY_BOTH);}}});}/***CreatesawaypointfromagivenplaceIDandtitle.**@paramplaceIdTheIDoftheplacetobeconvertedtoawaypoint.*@paramtitleAdescriptivetitleforthewaypoint.*/privatevoidcreateWaypoint(StringplaceId,Stringtitle){try{mWaypoints.add(Waypoint.builder().setPlaceIdString(placeId).setTitle(title).build());}catch(Waypoint.UnsupportedPlaceIdExceptione){displayMessage("Error starting navigation: Place ID is not supported: "+placeId,DISPLAY_BOTH);}}/**Displaysthecalculatedtraveltimeanddistancetoeachwaypoint.*/privatevoiddisplayTimesAndDistances(){List<TimeAndDistance>timesAndDistances=mNavigator.getTimeAndDistanceList();intleg=1;Stringmessage="You're on your way!";for(TimeAndDistancetimeAndDistance:timesAndDistances){message=message+"\nRoute leg: "+leg+++": Travel time (seconds): "+timeAndDistance.getSeconds()+". Distance (meters): "+timeAndDistance.getMeters();}displayMessage(message,DISPLAY_BOTH);}/***Registerssomeeventlistenerstoshowamessageandtakeothernecessarystepswhenspecific*navigationeventsoccur.*/privatevoidregisterNavigationListeners(){mArrivalListener=newNavigator.ArrivalListener(){@OverridepublicvoidonArrival(ArrivalEventarrivalEvent){displayMessage("onArrival: You've arrived at a waypoint: "+mNavigator.getCurrentRouteSegment().getDestinationWaypoint().getTitle(),DISPLAY_BOTH);//Startturn-by-turnguidanceforthenextlegoftheroute.if(arrivalEvent.isFinalDestination()){displayMessage("onArrival: You've arrived at the final destination.",DISPLAY_BOTH);}else{mNavigator.continueToNextDestination();mNavigator.startGuidance();}}};//Listensforarrivalatawaypoint.mNavigator.addArrivalListener(mArrivalListener);mRouteChangedListener=newNavigator.RouteChangedListener(){@OverridepublicvoidonRouteChanged(){displayMessage("onRouteChanged: The driver's route has changed. Current waypoint: "+mNavigator.getCurrentRouteSegment().getDestinationWaypoint().getTitle(),DISPLAY_LOG);}};//Listensforchangesintheroute.mNavigator.addRouteChangedListener(mRouteChangedListener);//Listensforroad-snappedlocationupdates.mRoadSnappedLocationProvider=NavigationApi.getRoadSnappedLocationProvider(getApplication());mLocationListener=newRoadSnappedLocationProvider.LocationListener(){@OverridepublicvoidonLocationChanged(Locationlocation){displayMessage("onLocationUpdated: Navigation engine has provided a new"+" road-snapped location: "+location.toString(),DISPLAY_LOG);}@OverridepublicvoidonRawLocationUpdate(Locationlocation){displayMessage("onLocationUpdated: Navigation engine has provided a new"+" raw location: "+location.toString(),DISPLAY_LOG);}};if(mRoadSnappedLocationProvider!=null){mRoadSnappedLocationProvider.addLocationListener(mLocationListener);}else{displayMessage("ERROR: Failed to get a location provider",DISPLAY_LOG);}mRemainingTimeOrDistanceChangedListener=newNavigator.RemainingTimeOrDistanceChangedListener(){@OverridepublicvoidonRemainingTimeOrDistanceChanged(){displayMessage("onRemainingTimeOrDistanceChanged: Time or distance estimate"+" has changed.",DISPLAY_LOG);}};//Listensforchangesintimeordistance.mNavigator.addRemainingTimeOrDistanceChangedListener(60,100,mRemainingTimeOrDistanceChangedListener);}/**Handlestheresultoftherequestforlocationpermissions.*/@OverridepublicvoidonRequestPermissionsResult(intrequestCode,@NonNullString[]permissions,@NonNullint[]grantResults){mLocationPermissionGranted=false;switch(requestCode){casePERMISSIONS_REQUEST_ACCESS_FINE_LOCATION:{//Ifrequestiscanceled,theresultarraysareempty.if(grantResults.length > 0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){mLocationPermissionGranted=true;}}}}/***Showsamessageonscreenandinthelog.Usedwhensomethinggoeswrong.**@paramerrorMessageThemessagetodisplay.*/privatevoiddisplayMessage(StringerrorMessage,StringdisplayMedium){if(displayMedium.equals(DISPLAY_BOTH)||displayMedium.equals(DISPLAY_TOAST)){Toast.makeText(this,errorMessage,Toast.LENGTH_LONG).show();}if(displayMedium.equals(DISPLAY_BOTH)||displayMedium.equals(DISPLAY_LOG)){Log.d(TAG,errorMessage);}}}
เพิ่มข้อมูลโค้ดที่ใช้ในการนําทาง
SupportNavigationFragment คือคอมโพเนนต์ UI ที่แสดงผลลัพธ์ภาพของการนําทาง รวมถึงแผนที่แบบอินเทอร์แอกทีฟและเส้นทางแบบเลี้ยวต่อเลี้ยว คุณสามารถประกาศข้อมูลโค้ดในไฟล์เลย์เอาต์ XML ดังที่แสดงด้านล่าง
if(ContextCompat.checkSelfPermission(this.getApplicationContext(),android.Manifest.permission.ACCESS_FINE_LOCATION)==PackageManager.PERMISSION_GRANTED){mLocationPermissionGranted=true;}else{ActivityCompat.requestPermissions(this,newString[]{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.",DISPLAY_BOTH);return;}
NavigationApi.getNavigator(this,newNavigationApi.NavigatorListener(){/***SetsupthenavigationUIwhenthenavigatorisreadyforuse.*/@OverridepublicvoidonNavigatorReady(Navigatornavigator){displayMessage("Navigator ready.",DISPLAY_BOTH);mNavigator=navigator;mNavFragment=(SupportNavigationFragment)getFragmentManager().findFragmentById(R.id.navigation_fragment);//Setthecameratofollowthedevicelocationwith'TILTED'drivingview.mNavFragment.getCamera().followMyLocation(Camera.Perspective.TILTED);//Navigatetothespecifiedplaces.navigateToPlaces();}/***HandleserrorsfromtheNavigationSDK.*@paramerrorCodeTheerrorcodereturnedbythenavigator.*/@OverridepublicvoidonError(@NavigationApi.ErrorCodeinterrorCode){switch(errorCode){caseNavigationApi.ErrorCode.NOT_AUTHORIZED:displayMessage("Error loading Navigation SDK: Your API key is "+"invalid or not authorized to use the Navigation SDK.",DISPLAY_BOTH);break;caseNavigationApi.ErrorCode.TERMS_NOT_ACCEPTED:displayMessage("Error loading Navigation SDK: User did not accept "+"the Navigation Terms of Use.",DISPLAY_BOTH);break;caseNavigationApi.ErrorCode.NETWORK_ERROR:displayMessage("Error loading Navigation SDK: Network error.",DISPLAY_BOTH);break;caseNavigationApi.ErrorCode.LOCATION_PERMISSION_MISSING:displayMessage("Error loading Navigation SDK: Location permission "+"is missing.",DISPLAY_BOTH);break;default:displayMessage("Error loading Navigation SDK: "+errorCode,DISPLAY_BOTH);}}});
[null,null,["อัปเดตล่าสุด 2024-12-22 UTC"],[[["The Google Maps Navigation SDK for Android enables turn-by-turn navigation with multiple destinations (waypoints) within your app."],["Integrate the SDK by setting up your project, adding UI elements, and initializing the Navigation API."],["Create waypoints using place IDs, set them as destinations for the navigator, and start guidance to begin navigation."],["The SDK provides features for simulating progress, handling errors, and customizing the user interface."],["Request location permissions and ensure users accept Google Navigation Terms of Service for a smooth user experience."]]],[]]