66
77import android .Manifest ;
88import android .annotation .SuppressLint ;
9+ import android .app .Activity ;
10+ import android .app .Application ;
911import android .content .Context ;
1012import android .content .pm .PackageManager ;
1113import android .graphics .Bitmap ;
1719import androidx .annotation .Nullable ;
1820import androidx .lifecycle .DefaultLifecycleObserver ;
1921import androidx .lifecycle .Lifecycle ;
22+ import androidx .lifecycle .Lifecycle .State ;
2023import androidx .lifecycle .LifecycleOwner ;
2124import com .google .android .gms .maps .CameraUpdate ;
2225import com .google .android .gms .maps .GoogleMap ;
3639import io .flutter .plugin .common .BinaryMessenger ;
3740import io .flutter .plugin .common .MethodCall ;
3841import io .flutter .plugin .common .MethodChannel ;
42+ import io .flutter .plugin .common .PluginRegistry ;
3943import io .flutter .plugin .platform .PlatformView ;
4044import java .io .ByteArrayOutputStream ;
4145import java .util .ArrayList ;
4650
4751/** Controller of a single GoogleMaps MapView instance. */
4852final class GoogleMapController
49- implements DefaultLifecycleObserver ,
53+ implements Application .ActivityLifecycleCallbacks ,
54+ DefaultLifecycleObserver ,
5055 ActivityPluginBinding .OnSaveInstanceStateListener ,
5156 GoogleMapOptionsSink ,
5257 MethodChannel .MethodCallHandler ,
@@ -70,8 +75,12 @@ final class GoogleMapController
7075 private boolean disposed = false ;
7176 private final float density ;
7277 private MethodChannel .Result mapReadyResult ;
78+ @ Nullable private final Lifecycle lifecycle ;
7379 private final Context context ;
74- private final LifecycleProvider lifecycleProvider ;
80+ // Do not use directly, use getApplication() instead to get correct application object for both v1
81+ // and v2 embedding.
82+ @ Nullable private final Application mApplication ;
83+ @ Nullable private final PluginRegistry .Registrar registrar ; // For v1 embedding only.
7584 private final MarkersController markersController ;
7685 private final PolygonsController polygonsController ;
7786 private final PolylinesController polylinesController ;
@@ -85,7 +94,9 @@ final class GoogleMapController
8594 int id ,
8695 Context context ,
8796 BinaryMessenger binaryMessenger ,
88- LifecycleProvider lifecycleProvider ,
97+ @ Nullable Application application ,
98+ @ Nullable Lifecycle lifecycle ,
99+ @ Nullable PluginRegistry .Registrar registrar ,
89100 GoogleMapOptions options ) {
90101 this .id = id ;
91102 this .context = context ;
@@ -94,7 +105,9 @@ final class GoogleMapController
94105 this .density = context .getResources ().getDisplayMetrics ().density ;
95106 methodChannel = new MethodChannel (binaryMessenger , "plugins.flutter.io/google_maps_" + id );
96107 methodChannel .setMethodCallHandler (this );
97- this .lifecycleProvider = lifecycleProvider ;
108+ mApplication = application ;
109+ this .lifecycle = lifecycle ;
110+ this .registrar = registrar ;
98111 this .markersController = new MarkersController (methodChannel );
99112 this .polygonsController = new PolygonsController (methodChannel , density );
100113 this .polylinesController = new PolylinesController (methodChannel , density );
@@ -106,8 +119,30 @@ public View getView() {
106119 return mapView ;
107120 }
108121
109- void init () {
110- lifecycleProvider .getLifecycle ().addObserver (this );
122+ void init (State lifecycleState ) {
123+ switch (lifecycleState ) {
124+ case RESUMED :
125+ mapView .onCreate (null );
126+ mapView .onStart ();
127+ mapView .onResume ();
128+ break ;
129+ case STARTED :
130+ mapView .onCreate (null );
131+ mapView .onStart ();
132+ break ;
133+ case CREATED :
134+ mapView .onCreate (null );
135+ break ;
136+ case DESTROYED :
137+ case INITIALIZED :
138+ // Nothing to do, the activity has been completely destroyed or not yet created.
139+ break ;
140+ }
141+ if (lifecycle != null ) {
142+ lifecycle .addObserver (this );
143+ } else {
144+ getApplication ().registerActivityLifecycleCallbacks (this );
145+ }
111146 mapView .getMapAsync (this );
112147 }
113148
@@ -472,10 +507,7 @@ public void dispose() {
472507 methodChannel .setMethodCallHandler (null );
473508 setGoogleMapListener (null );
474509 destroyMapViewIfNecessary ();
475- Lifecycle lifecycle = lifecycleProvider .getLifecycle ();
476- if (lifecycle != null ) {
477- lifecycle .removeObserver (this );
478- }
510+ getApplication ().unregisterActivityLifecycleCallbacks (this );
479511 }
480512
481513 private void setGoogleMapListener (@ Nullable GoogleMapListener listener ) {
@@ -505,7 +537,64 @@ public void onInputConnectionUnlocked() {
505537 // TODO(mklim): Remove this empty override once https://github.com/flutter/flutter/issues/40126 is fixed in stable.
506538 }
507539
508- // DefaultLifecycleObserver
540+ // Application.ActivityLifecycleCallbacks methods
541+ @ Override
542+ public void onActivityCreated (Activity activity , Bundle savedInstanceState ) {
543+ if (disposed || activity .hashCode () != getActivityHashCode ()) {
544+ return ;
545+ }
546+ mapView .onCreate (savedInstanceState );
547+ }
548+
549+ @ Override
550+ public void onActivityStarted (Activity activity ) {
551+ if (disposed || activity .hashCode () != getActivityHashCode ()) {
552+ return ;
553+ }
554+ mapView .onStart ();
555+ }
556+
557+ @ Override
558+ public void onActivityResumed (Activity activity ) {
559+ if (disposed || activity .hashCode () != getActivityHashCode ()) {
560+ return ;
561+ }
562+ mapView .onResume ();
563+ }
564+
565+ @ Override
566+ public void onActivityPaused (Activity activity ) {
567+ if (disposed || activity .hashCode () != getActivityHashCode ()) {
568+ return ;
569+ }
570+ mapView .onPause ();
571+ }
572+
573+ @ Override
574+ public void onActivityStopped (Activity activity ) {
575+ if (disposed || activity .hashCode () != getActivityHashCode ()) {
576+ return ;
577+ }
578+ mapView .onStop ();
579+ }
580+
581+ @ Override
582+ public void onActivitySaveInstanceState (Activity activity , Bundle outState ) {
583+ if (disposed || activity .hashCode () != getActivityHashCode ()) {
584+ return ;
585+ }
586+ mapView .onSaveInstanceState (outState );
587+ }
588+
589+ @ Override
590+ public void onActivityDestroyed (Activity activity ) {
591+ if (disposed || activity .hashCode () != getActivityHashCode ()) {
592+ return ;
593+ }
594+ destroyMapViewIfNecessary ();
595+ }
596+
597+ // DefaultLifecycleObserver and OnSaveInstanceStateListener
509598
510599 @ Override
511600 public void onCreate (@ NonNull LifecycleOwner owner ) {
@@ -549,7 +638,6 @@ public void onStop(@NonNull LifecycleOwner owner) {
549638
550639 @ Override
551640 public void onDestroy (@ NonNull LifecycleOwner owner ) {
552- owner .getLifecycle ().removeObserver (this );
553641 if (disposed ) {
554642 return ;
555643 }
@@ -760,6 +848,24 @@ private int checkSelfPermission(String permission) {
760848 permission , android .os .Process .myPid (), android .os .Process .myUid ());
761849 }
762850
851+ private int getActivityHashCode () {
852+ if (registrar != null && registrar .activity () != null ) {
853+ return registrar .activity ().hashCode ();
854+ } else {
855+ // TODO(cyanglaz): Remove `getActivityHashCode()` and use a cached hashCode when creating the view for V1 embedding.
856+ // https://github.com/flutter/flutter/issues/69128
857+ return -1 ;
858+ }
859+ }
860+
861+ private Application getApplication () {
862+ if (registrar != null && registrar .activity () != null ) {
863+ return registrar .activity ().getApplication ();
864+ } else {
865+ return mApplication ;
866+ }
867+ }
868+
763869 private void destroyMapViewIfNecessary () {
764870 if (mapView == null ) {
765871 return ;
0 commit comments