Skip to content

Commit

Permalink
[google_maps_flutter] supports v2 android embedding. (flutter#2488)
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Yang authored Jan 30, 2020
1 parent a99812b commit af7f798
Show file tree
Hide file tree
Showing 18 changed files with 408 additions and 88 deletions.
6 changes: 6 additions & 0 deletions packages/google_maps_flutter/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 0.5.22

* Support Android v2 embedding.
* Bump the min flutter version to `1.12.13+hotfix.5`.
* Fixes some e2e tests on Android.

## 0.5.21+17

* Fix Swift example in README.md.
Expand Down
29 changes: 3 additions & 26 deletions packages/google_maps_flutter/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -34,31 +34,8 @@ android {

dependencies {
implementation 'com.google.android.gms:play-services-maps:17.0.0'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test:rules:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
}

// TODO(cyanglaz): Remove this hack once androidx.lifecycle is included on stable. https://github.com/flutter/flutter/issues/42348
afterEvaluate {
def containsEmbeddingDependencies = false
for (def configuration : configurations.all) {
for (def dependency : configuration.dependencies) {
if (dependency.group == 'io.flutter' &&
dependency.name.startsWith('flutter_embedding') &&
dependency.isTransitive())
{
containsEmbeddingDependencies = true
break
}
}
}
if (!containsEmbeddingDependencies) {
android {
dependencies {
def lifecycle_version = "1.1.1"
compileOnly "android.arch.lifecycle:runtime:$lifecycle_version"
compileOnly "android.arch.lifecycle:common:$lifecycle_version"
compileOnly "android.arch.lifecycle:common-java8:$lifecycle_version"
}
}
}
}
3 changes: 3 additions & 0 deletions packages/google_maps_flutter/android/gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@

package io.flutter.plugins.googlemaps;

import android.app.Application;
import android.content.Context;
import android.graphics.Rect;
import androidx.lifecycle.Lifecycle;
import com.google.android.gms.maps.GoogleMapOptions;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLngBounds;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.PluginRegistry;
import java.util.concurrent.atomic.AtomicInteger;

Expand All @@ -27,9 +30,25 @@ class GoogleMapBuilder implements GoogleMapOptionsSink {
private Rect padding = new Rect(0, 0, 0, 0);

GoogleMapController build(
int id, Context context, AtomicInteger state, PluginRegistry.Registrar registrar) {
int id,
Context context,
AtomicInteger state,
BinaryMessenger binaryMessenger,
Application application,
Lifecycle lifecycle,
PluginRegistry.Registrar registrar,
int activityHashCode) {
final GoogleMapController controller =
new GoogleMapController(id, context, state, registrar, options);
new GoogleMapController(
id,
context,
state,
binaryMessenger,
application,
lifecycle,
registrar,
activityHashCode,
options);
controller.init();
controller.setMyLocationEnabled(myLocationEnabled);
controller.setMyLocationButtonEnabled(myLocationButtonEnabled);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMapOptions;
Expand All @@ -34,6 +38,8 @@
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.Polygon;
import com.google.android.gms.maps.model.Polyline;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.PluginRegistry;
Expand All @@ -48,6 +54,8 @@
/** Controller of a single GoogleMaps MapView instance. */
final class GoogleMapController
implements Application.ActivityLifecycleCallbacks,
DefaultLifecycleObserver,
ActivityPluginBinding.OnSaveInstanceStateListener,
GoogleMap.OnCameraIdleListener,
GoogleMap.OnCameraMoveListener,
GoogleMap.OnCameraMoveStartedListener,
Expand All @@ -68,7 +76,6 @@ final class GoogleMapController
private final int id;
private final AtomicInteger activityState;
private final MethodChannel methodChannel;
private final PluginRegistry.Registrar registrar;
private final MapView mapView;
private GoogleMap googleMap;
private boolean trackCameraPosition = false;
Expand All @@ -80,8 +87,13 @@ final class GoogleMapController
private boolean disposed = false;
private final float density;
private MethodChannel.Result mapReadyResult;
private final int registrarActivityHashCode;
private final int
activityHashCode; // Do not use directly, use getActivityHashCode() instead to get correct hashCode for both v1 and v2 embedding.
private final Lifecycle lifecycle;
private final Context context;
private final Application
mApplication; // Do not use direclty, use getApplication() instead to get correct application object for both v1 and v2 embedding.
private final PluginRegistry.Registrar registrar; // For v1 embedding only.
private final MarkersController markersController;
private final PolygonsController polygonsController;
private final PolylinesController polylinesController;
Expand All @@ -95,18 +107,23 @@ final class GoogleMapController
int id,
Context context,
AtomicInteger activityState,
BinaryMessenger binaryMessenger,
Application application,
Lifecycle lifecycle,
PluginRegistry.Registrar registrar,
int registrarActivityHashCode,
GoogleMapOptions options) {
this.id = id;
this.context = context;
this.activityState = activityState;
this.registrar = registrar;
this.mapView = new MapView(context, options);
this.density = context.getResources().getDisplayMetrics().density;
methodChannel =
new MethodChannel(registrar.messenger(), "plugins.flutter.io/google_maps_" + id);
methodChannel = new MethodChannel(binaryMessenger, "plugins.flutter.io/google_maps_" + id);
methodChannel.setMethodCallHandler(this);
this.registrarActivityHashCode = registrar.activity().hashCode();
mApplication = application;
this.lifecycle = lifecycle;
this.registrar = registrar;
this.activityHashCode = registrarActivityHashCode;
this.markersController = new MarkersController(methodChannel);
this.polygonsController = new PolygonsController(methodChannel);
this.polylinesController = new PolylinesController(methodChannel, density);
Expand Down Expand Up @@ -152,7 +169,11 @@ void init() {
throw new IllegalArgumentException(
"Cannot interpret " + activityState.get() + " as an activity state");
}
registrar.activity().getApplication().registerActivityLifecycleCallbacks(this);
if (lifecycle != null) {
lifecycle.addObserver(this);
} else {
getApplication().registerActivityLifecycleCallbacks(this);
}
mapView.getMapAsync(this);
}

Expand Down Expand Up @@ -368,6 +389,10 @@ public void onMethodCall(MethodCall call, MethodChannel.Result result) {
result.success(googleMap.isBuildingsEnabled());
break;
}
case "map#getZoomLevel":
{
result.success(googleMap.getCameraPosition().zoom);
}
case "map#setStyle":
{
String mapStyle = (String) call.arguments;
Expand Down Expand Up @@ -472,7 +497,7 @@ public void dispose() {
disposed = true;
methodChannel.setMethodCallHandler(null);
mapView.onDestroy();
registrar.activity().getApplication().unregisterActivityLifecycleCallbacks(this);
getApplication().unregisterActivityLifecycleCallbacks(this);
}

// @Override
Expand All @@ -489,62 +514,129 @@ public void onInputConnectionUnlocked() {
// TODO(mklim): Remove this empty override once https://github.com/flutter/flutter/issues/40126 is fixed in stable.
};

// Application.ActivityLifecycleCallbacks methods
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
if (disposed || activity.hashCode() != registrarActivityHashCode) {
if (disposed || activity.hashCode() != getActivityHashCode()) {
return;
}
mapView.onCreate(savedInstanceState);
}

@Override
public void onActivityStarted(Activity activity) {
if (disposed || activity.hashCode() != registrarActivityHashCode) {
if (disposed || activity.hashCode() != getActivityHashCode()) {
return;
}
mapView.onStart();
}

@Override
public void onActivityResumed(Activity activity) {
if (disposed || activity.hashCode() != registrarActivityHashCode) {
if (disposed || activity.hashCode() != getActivityHashCode()) {
return;
}
mapView.onResume();
}

@Override
public void onActivityPaused(Activity activity) {
if (disposed || activity.hashCode() != registrarActivityHashCode) {
if (disposed || activity.hashCode() != getActivityHashCode()) {
return;
}
mapView.onPause();
}

@Override
public void onActivityStopped(Activity activity) {
if (disposed || activity.hashCode() != registrarActivityHashCode) {
if (disposed || activity.hashCode() != getActivityHashCode()) {
return;
}
mapView.onStop();
}

@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
if (disposed || activity.hashCode() != registrarActivityHashCode) {
if (disposed || activity.hashCode() != getActivityHashCode()) {
return;
}
mapView.onSaveInstanceState(outState);
}

@Override
public void onActivityDestroyed(Activity activity) {
if (disposed || activity.hashCode() != registrarActivityHashCode) {
if (disposed || activity.hashCode() != getActivityHashCode()) {
return;
}
mapView.onDestroy();
}

// DefaultLifecycleObserver and OnSaveInstanceStateListener

@Override
public void onCreate(@NonNull LifecycleOwner owner) {
if (disposed) {
return;
}
mapView.onCreate(null);
}

@Override
public void onStart(@NonNull LifecycleOwner owner) {
if (disposed) {
return;
}
mapView.onStart();
}

@Override
public void onResume(@NonNull LifecycleOwner owner) {
if (disposed) {
return;
}
mapView.onResume();
}

@Override
public void onPause(@NonNull LifecycleOwner owner) {
if (disposed) {
return;
}
mapView.onResume();
}

@Override
public void onStop(@NonNull LifecycleOwner owner) {
if (disposed) {
return;
}
mapView.onStop();
}

@Override
public void onDestroy(@NonNull LifecycleOwner owner) {
if (disposed) {
return;
}
mapView.onDestroy();
}

@Override
public void onRestoreInstanceState(Bundle bundle) {
if (disposed) {
return;
}
mapView.onCreate(bundle);
}

@Override
public void onSaveInstanceState(Bundle bundle) {
if (disposed) {
return;
}
mapView.onSaveInstanceState(bundle);
}

// GoogleMapOptionsSink methods

@Override
Expand Down Expand Up @@ -716,6 +808,22 @@ private int checkSelfPermission(String permission) {
permission, android.os.Process.myPid(), android.os.Process.myUid());
}

private int getActivityHashCode() {
if (registrar != null && registrar.activity() != null) {
return registrar.activity().hashCode();
} else {
return activityHashCode;
}
}

private Application getApplication() {
if (registrar != null && registrar.activity() != null) {
return registrar.activity().getApplication();
} else {
return mApplication;
}
}

public void setIndoorEnabled(boolean indoorEnabled) {
this.indoorEnabled = indoorEnabled;
}
Expand Down
Loading

0 comments on commit af7f798

Please sign in to comment.