1919import androidx .lifecycle .Observer ;
2020import com .facebook .react .bridge .Arguments ;
2121import com .facebook .react .bridge .CatalystInstance ;
22+ import com .facebook .react .bridge .LifecycleEventListener ;
2223import com .facebook .react .bridge .NativeArray ;
2324import com .facebook .react .bridge .Promise ;
2425import com .facebook .react .bridge .ReactApplicationContext ;
5859 * This exposes a series of methods that can be called diretly from the React Native code. They have
5960 * been implemented using promises as it's not recommended for them to be synchronous.
6061 */
61- public class NavModule extends ReactContextBaseJavaModule implements INavigationCallback {
62+ public class NavModule extends ReactContextBaseJavaModule
63+ implements INavigationCallback , LifecycleEventListener {
6264 public static final String REACT_CLASS = "NavModule" ;
6365 private static final String TAG = "NavModule" ;
6466 private static NavModule instance ;
@@ -73,6 +75,12 @@ public class NavModule extends ReactContextBaseJavaModule implements INavigation
7375 private final CopyOnWriteArrayList <NavigationReadyListener > mNavigationReadyListeners =
7476 new CopyOnWriteArrayList <>();
7577 private boolean mIsListeningRoadSnappedLocation = false ;
78+ private LocationListener mLocationListener ;
79+ private Navigator .ArrivalListener mArrivalListener ;
80+ private Navigator .RouteChangedListener mRouteChangedListener ;
81+ private Navigator .TrafficUpdatedListener mTrafficUpdatedListener ;
82+ private Navigator .ReroutingListener mReroutingListener ;
83+ private Navigator .RemainingTimeOrDistanceChangedListener mRemainingTimeOrDistanceChangedListener ;
7684
7785 private HashMap <String , Object > tocParamsMap ;
7886 private @ Navigator .TaskRemovedBehavior int taskRemovedBehaviour ;
@@ -87,19 +95,22 @@ public interface NavigationReadyListener {
8795
8896 public NavModule (ReactApplicationContext reactContext , NavViewManager navViewManager ) {
8997 super (reactContext );
90- this .reactContext = reactContext ;
91- mNavViewManager = navViewManager ;
92- instance = this ;
98+ setReactContext (reactContext );
99+ setViewManager (navViewManager );
93100 if (moduleReadyListener != null ) {
94101 moduleReadyListener .onModuleReady ();
95102 }
96103 }
97104
98- public static void setModuleReadyListener (ModuleReadyListener listener ) {
99- moduleReadyListener = listener ;
100- if (instance != null && moduleReadyListener != null ) {
101- moduleReadyListener .onModuleReady ();
105+ public static synchronized NavModule getInstance (
106+ ReactApplicationContext reactContext , NavViewManager navViewManager ) {
107+ if (instance == null ) {
108+ instance = new NavModule (reactContext , navViewManager );
109+ } else {
110+ instance .setReactContext (reactContext );
111+ instance .setViewManager (navViewManager );
102112 }
113+ return instance ;
103114 }
104115
105116 public static synchronized NavModule getInstance () {
@@ -109,6 +120,22 @@ public static synchronized NavModule getInstance() {
109120 return instance ;
110121 }
111122
123+ public void setReactContext (ReactApplicationContext reactContext ) {
124+ this .reactContext = reactContext ;
125+ this .reactContext .addLifecycleEventListener (this );
126+ }
127+
128+ public void setViewManager (NavViewManager navViewManager ) {
129+ mNavViewManager = navViewManager ;
130+ }
131+
132+ public static void setModuleReadyListener (ModuleReadyListener listener ) {
133+ moduleReadyListener = listener ;
134+ if (instance != null && moduleReadyListener != null ) {
135+ moduleReadyListener .onModuleReady ();
136+ }
137+ }
138+
112139 public Navigator getNavigator () {
113140 return mNavigator ;
114141 }
@@ -124,85 +151,10 @@ public Map<String, Object> getConstants() {
124151 return constants ;
125152 }
126153
127- private Navigator .ArrivalListener mArrivalListener =
128- new Navigator .ArrivalListener () {
129- @ Override
130- public void onArrival (ArrivalEvent arrivalEvent ) {
131- WritableMap map = Arguments .createMap ();
132- map .putMap (
133- "waypoint" , ObjectTranslationUtil .getMapFromWaypoint (arrivalEvent .getWaypoint ()));
134- map .putBoolean ("isFinalDestination" , arrivalEvent .isFinalDestination ());
135-
136- WritableNativeArray params = new WritableNativeArray ();
137- params .pushMap (map );
138-
139- sendCommandToReactNative ("onArrival" , params );
140- }
141- };
142-
143- private LocationListener mLocationListener =
144- new LocationListener () {
145- @ Override
146- public void onLocationChanged (final Location location ) {
147- WritableNativeArray params = new WritableNativeArray ();
148- params .pushMap (ObjectTranslationUtil .getMapFromLocation (location ));
149-
150- sendCommandToReactNative ("onLocationChanged" , params );
151- }
152-
153- @ Override
154- public void onRawLocationUpdate (final Location location ) {
155- WritableNativeArray params = new WritableNativeArray ();
156- params .pushMap (ObjectTranslationUtil .getMapFromLocation (location ));
157-
158- sendCommandToReactNative ("onRawLocationChanged" , params );
159- }
160- };
161-
162- private Navigator .RouteChangedListener mRouteChangedListener =
163- new Navigator .RouteChangedListener () {
164- @ Override
165- public void onRouteChanged () {
166- sendCommandToReactNative ("onRouteChanged" , (NativeArray ) null );
167- }
168- };
169-
170- private Navigator .TrafficUpdatedListener mTrafficUpdatedListener =
171- new Navigator .TrafficUpdatedListener () {
172- @ Override
173- public void onTrafficUpdated () {
174- sendCommandToReactNative ("onTrafficUpdated" , (NativeArray ) null );
175- }
176- };
177-
178- private Navigator .ReroutingListener mReroutingListener =
179- new Navigator .ReroutingListener () {
180- @ Override
181- public void onReroutingRequestedByOffRoute () {
182- sendCommandToReactNative ("onReroutingRequestedByOffRoute" , (NativeArray ) null );
183- }
184- };
185-
186- private Navigator .RemainingTimeOrDistanceChangedListener mRemainingTimeOrDistanceChangedListener =
187- new Navigator .RemainingTimeOrDistanceChangedListener () {
188- @ Override
189- public void onRemainingTimeOrDistanceChanged () {
190- sendCommandToReactNative ("onRemainingTimeOrDistanceChanged" , (NativeArray ) null );
191- }
192- };
193-
194154 @ ReactMethod
195155 private void cleanup () {
196- if (mIsListeningRoadSnappedLocation ) {
197- mRoadSnappedLocationProvider .removeLocationListener (mLocationListener );
198- }
199- mNavigator .unregisterServiceForNavUpdates ();
200- mNavigator .removeArrivalListener (mArrivalListener );
201- mNavigator .removeReroutingListener (mReroutingListener );
202- mNavigator .removeRouteChangedListener (mRouteChangedListener );
203- mNavigator .removeTrafficUpdatedListener (mTrafficUpdatedListener );
204- mNavigator .removeRemainingTimeOrDistanceChangedListener (
205- mRemainingTimeOrDistanceChangedListener );
156+ stopUpdatingLocation ();
157+ removeNavigationListeners ();
206158 mWaypoints .clear ();
207159
208160 for (NavigationReadyListener listener : mNavigationReadyListeners ) {
@@ -276,8 +228,12 @@ public void onNavigatorReady(Navigator navigator) {
276228 // Keep a reference to the Navigator (used to configure and start nav)
277229 mNavigator = navigator ;
278230 mNavigator .setTaskRemovedBehavior (taskRemovedBehaviour );
279- mRoadSnappedLocationProvider =
280- NavigationApi .getRoadSnappedLocationProvider (getCurrentActivity ().getApplication ());
231+ if (mRoadSnappedLocationProvider == null ) {
232+ mRoadSnappedLocationProvider =
233+ NavigationApi .getRoadSnappedLocationProvider (
234+ getCurrentActivity ().getApplication ());
235+ }
236+ registerNavigationListeners ();
281237 onNavigationReady ();
282238 }
283239
@@ -330,21 +286,80 @@ public void setTurnByTurnLoggingEnabled(boolean isEnabled) {
330286 * navigation events occur (e.g. the driver's route changes or the destination is reached).
331287 */
332288 private void registerNavigationListeners () {
289+ removeNavigationListeners ();
290+
291+ mArrivalListener =
292+ new Navigator .ArrivalListener () {
293+ @ Override
294+ public void onArrival (ArrivalEvent arrivalEvent ) {
295+ WritableMap map = Arguments .createMap ();
296+ map .putMap (
297+ "waypoint" , ObjectTranslationUtil .getMapFromWaypoint (arrivalEvent .getWaypoint ()));
298+ map .putBoolean ("isFinalDestination" , arrivalEvent .isFinalDestination ());
299+
300+ WritableNativeArray params = new WritableNativeArray ();
301+ params .pushMap (map );
302+
303+ sendCommandToReactNative ("onArrival" , params );
304+ }
305+ };
333306 mNavigator .addArrivalListener (mArrivalListener );
307+
308+ mRouteChangedListener =
309+ new Navigator .RouteChangedListener () {
310+ @ Override
311+ public void onRouteChanged () {
312+ sendCommandToReactNative ("onRouteChanged" , (NativeArray ) null );
313+ }
314+ };
334315 mNavigator .addRouteChangedListener (mRouteChangedListener );
316+
317+ mTrafficUpdatedListener =
318+ new Navigator .TrafficUpdatedListener () {
319+ @ Override
320+ public void onTrafficUpdated () {
321+ sendCommandToReactNative ("onTrafficUpdated" , (NativeArray ) null );
322+ }
323+ };
335324 mNavigator .addTrafficUpdatedListener (mTrafficUpdatedListener );
325+
326+ mReroutingListener =
327+ new Navigator .ReroutingListener () {
328+ @ Override
329+ public void onReroutingRequestedByOffRoute () {
330+ sendCommandToReactNative ("onReroutingRequestedByOffRoute" , (NativeArray ) null );
331+ }
332+ };
336333 mNavigator .addReroutingListener (mReroutingListener );
334+
335+ mRemainingTimeOrDistanceChangedListener =
336+ new Navigator .RemainingTimeOrDistanceChangedListener () {
337+ @ Override
338+ public void onRemainingTimeOrDistanceChanged () {
339+ sendCommandToReactNative ("onRemainingTimeOrDistanceChanged" , (NativeArray ) null );
340+ }
341+ };
337342 mNavigator .addRemainingTimeOrDistanceChangedListener (
338343 0 , 0 , mRemainingTimeOrDistanceChangedListener );
339344 }
340345
341346 private void removeNavigationListeners () {
342- mNavigator .removeArrivalListener (mArrivalListener );
343- mNavigator .removeRouteChangedListener (mRouteChangedListener );
344- mNavigator .removeTrafficUpdatedListener (mTrafficUpdatedListener );
345- mNavigator .removeReroutingListener (mReroutingListener );
346- mNavigator .removeRemainingTimeOrDistanceChangedListener (
347- mRemainingTimeOrDistanceChangedListener );
347+ if (mArrivalListener != null ) {
348+ mNavigator .removeArrivalListener (mArrivalListener );
349+ }
350+ if (mRouteChangedListener != null ) {
351+ mNavigator .removeRouteChangedListener (mRouteChangedListener );
352+ }
353+ if (mTrafficUpdatedListener != null ) {
354+ mNavigator .removeTrafficUpdatedListener (mTrafficUpdatedListener );
355+ }
356+ if (mReroutingListener != null ) {
357+ mNavigator .removeReroutingListener (mReroutingListener );
358+ }
359+ if (mRemainingTimeOrDistanceChangedListener != null ) {
360+ mNavigator .removeRemainingTimeOrDistanceChangedListener (
361+ mRemainingTimeOrDistanceChangedListener );
362+ }
348363 }
349364
350365 private void createWaypoint (Map map ) {
@@ -468,14 +483,6 @@ private void setOnResultListener(IRouteStatusResult listener) {
468483 @ Override
469484 public void onResult (Navigator .RouteStatus code ) {
470485 listener .onResult (code );
471- switch (code ) {
472- case OK :
473- removeNavigationListeners ();
474- registerNavigationListeners ();
475- break ;
476- default :
477- break ;
478- }
479486 }
480487 });
481488 }
@@ -725,14 +732,54 @@ public void resetTermsAccepted() {
725732
726733 @ ReactMethod
727734 public void startUpdatingLocation () {
728- mRoadSnappedLocationProvider . addLocationListener ( mLocationListener );
735+ registerLocationListener ( );
729736 mIsListeningRoadSnappedLocation = true ;
730737 }
731738
732739 @ ReactMethod
733740 public void stopUpdatingLocation () {
734741 mIsListeningRoadSnappedLocation = false ;
735- mRoadSnappedLocationProvider .removeLocationListener (mLocationListener );
742+ removeLocationListener ();
743+ }
744+
745+ private void registerLocationListener () {
746+ // Unregister existing location listener if available.
747+ removeLocationListener ();
748+
749+ if (mRoadSnappedLocationProvider != null ) {
750+ mLocationListener =
751+ new LocationListener () {
752+ @ Override
753+ public void onLocationChanged (final Location location ) {
754+ if (mIsListeningRoadSnappedLocation ) {
755+ WritableNativeArray params = new WritableNativeArray ();
756+ params .pushMap (ObjectTranslationUtil .getMapFromLocation (location ));
757+
758+ sendCommandToReactNative ("onLocationChanged" , params );
759+ }
760+ }
761+
762+ @ Override
763+ public void onRawLocationUpdate (final Location location ) {
764+ if (mIsListeningRoadSnappedLocation ) {
765+ WritableNativeArray params = new WritableNativeArray ();
766+ params .pushMap (ObjectTranslationUtil .getMapFromLocation (location ));
767+
768+ sendCommandToReactNative ("onRawLocationChanged" , params );
769+ }
770+ }
771+ };
772+
773+ mRoadSnappedLocationProvider .resetFreeNav ();
774+ mRoadSnappedLocationProvider .addLocationListener (mLocationListener );
775+ }
776+ }
777+
778+ private void removeLocationListener () {
779+ if (mRoadSnappedLocationProvider != null && mLocationListener != null ) {
780+ mRoadSnappedLocationProvider .removeLocationListener (mLocationListener );
781+ mLocationListener = null ;
782+ }
736783 }
737784
738785 private void showNavInfo (NavInfo navInfo ) {
@@ -781,6 +828,23 @@ public boolean canOverrideExistingModule() {
781828 return true ;
782829 }
783830
831+ @ Override
832+ public void onHostResume () {
833+ // Re-register listeners on resume.
834+ if (mNavigator != null ) {
835+ registerNavigationListeners ();
836+ if (mIsListeningRoadSnappedLocation ) {
837+ registerLocationListener ();
838+ }
839+ }
840+ }
841+
842+ @ Override
843+ public void onHostPause () {}
844+
845+ @ Override
846+ public void onHostDestroy () {}
847+
784848 private interface IRouteStatusResult {
785849 void onResult (Navigator .RouteStatus code );
786850 }
0 commit comments