Commit 20a64699 authored by nightfallsad's avatar nightfallsad Committed by GitHub

Merge pull request #4 from alibaba/feature/flutter_1.9_androidx_upgrade

Feature/flutter 1.9 androidx upgrade
parents 484f9d68 35b9977f
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.idlefish.flutterboost"> package="com.idlefish.flutterboost">
<application>
<activity android:name="com.idlefish.flutterboost.containers.BoostFlutterDefaultActivity" />
</application>
</manifest> </manifest>
package com.idlefish.flutterboost; package com.idlefish.flutterboost;
import android.app.Activity;
import android.content.Context; import io.flutter.Log;
import androidx.annotation.Nullable;
import com.idlefish.flutterboost.interfaces.IContainerRecord;
import io.flutter.app.FlutterPluginRegistry;
import io.flutter.embedding.engine.FlutterEngine; import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.plugins.shim.ShimPluginRegistry; import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.BinaryMessenger; import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.PluginRegistry; import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.platform.PlatformViewRegistry;
import io.flutter.view.FlutterView;
import io.flutter.view.TextureRegistry;
import java.lang.ref.WeakReference; import java.util.*;
public class BoostPluginRegistry extends ShimPluginRegistry {
protected WeakReference<Activity> mCurrentActivityRef;
private FlutterEngine mEngine; public class BoostPluginRegistry implements PluginRegistry {
private Context mContext; private static final String TAG = "ShimPluginRegistry";
public BoostPluginRegistry(FlutterEngine engine, Context context) { private final FlutterEngine flutterEngine;
super(engine); private final Map<String, Object> pluginMap = new HashMap();
mEngine = engine; private final BoostRegistrarAggregate shimRegistrarAggregate;
mContext=context;
}
public BoostRegistrarAggregate getRegistrarAggregate() {
return shimRegistrarAggregate;
}
public BoostPluginRegistry(FlutterEngine flutterEngine) {
this.flutterEngine = flutterEngine;
this.shimRegistrarAggregate = new BoostRegistrarAggregate();
this.flutterEngine.getPlugins().add(this.shimRegistrarAggregate);
}
public PluginRegistry.Registrar registrarFor(String pluginKey) { public Registrar registrarFor(String pluginKey) {
return new BoostRegistrar(mEngine, super.registrarFor(pluginKey)); Log.v("ShimPluginRegistry", "Creating plugin Registrar for '" + pluginKey + "'");
if (this.pluginMap.containsKey(pluginKey)) {
throw new IllegalStateException("Plugin key " + pluginKey + " is already in use");
} else {
this.pluginMap.put(pluginKey, (Object) null);
BoostRegistrar registrar = new BoostRegistrar(pluginKey, this.pluginMap);
this.shimRegistrarAggregate.addPlugin(registrar);
return registrar;
} }
}
public void currentActivity(@Nullable Activity activity) { public boolean hasPlugin(String pluginKey) {
mCurrentActivityRef = new WeakReference<>(activity); return this.pluginMap.containsKey(pluginKey);
} }
public class BoostRegistrar implements PluginRegistry.Registrar { public Object valuePublishedByPlugin(String pluginKey) {
return this.pluginMap.get(pluginKey);
}
private final PluginRegistry.Registrar mRegistrar; public static class BoostRegistrarAggregate implements FlutterPlugin, ActivityAware {
private final FlutterEngine mEngine; private final Set<BoostRegistrar> shimRegistrars;
private FlutterPluginBinding flutterPluginBinding;
private ActivityPluginBinding activityPluginBinding;
BoostRegistrar(FlutterEngine engine, PluginRegistry.Registrar registrar) { public ActivityPluginBinding getActivityPluginBinding() {
mRegistrar = registrar; return activityPluginBinding;
mEngine = engine;
} }
@Override private BoostRegistrarAggregate() {
public Activity activity() { this.shimRegistrars = new HashSet();
Activity activity; }
IContainerRecord record;
record = NewFlutterBoost.instance().containerManager().getCurrentTopRecord(); public void addPlugin(BoostRegistrar shimRegistrar) {
if (record == null) { this.shimRegistrars.add(shimRegistrar);
record = NewFlutterBoost.instance().containerManager().getLastGenerateRecord(); if (this.flutterPluginBinding != null) {
shimRegistrar.onAttachedToEngine(this.flutterPluginBinding);
} }
if (record == null) { if (this.activityPluginBinding != null) {
activity = NewFlutterBoost.instance().currentActivity(); shimRegistrar.onAttachedToActivity(this.activityPluginBinding);
} else {
activity = record.getContainer().getContextActivity();
} }
if (activity == null && mCurrentActivityRef != null) { }
activity = mCurrentActivityRef.get();
} public void onAttachedToEngine(FlutterPluginBinding binding) {
this.flutterPluginBinding = binding;
Iterator var2 = this.shimRegistrars.iterator();
if (activity == null) { while (var2.hasNext()) {
throw new RuntimeException("current has no valid Activity yet"); BoostRegistrar shimRegistrar = (BoostRegistrar) var2.next();
shimRegistrar.onAttachedToEngine(binding);
} }
return activity;
} }
@Override public void onDetachedFromEngine(FlutterPluginBinding binding) {
public Context context() { Iterator var2 = this.shimRegistrars.iterator();
return BoostPluginRegistry.this.mContext;
}
@Override while (var2.hasNext()) {
public Context activeContext() { BoostRegistrar shimRegistrar = (BoostRegistrar) var2.next();
return BoostPluginRegistry.this.mContext; shimRegistrar.onDetachedFromEngine(binding);
} }
@Override this.flutterPluginBinding = null;
public BinaryMessenger messenger() {
return mEngine.getDartExecutor();
} }
@Override public void onAttachedToActivity(ActivityPluginBinding binding) {
public TextureRegistry textures() { this.activityPluginBinding = binding;
return mEngine.getRenderer(); Iterator var2 = this.shimRegistrars.iterator();
}
@Override while (var2.hasNext()) {
public PlatformViewRegistry platformViewRegistry() { BoostRegistrar shimRegistrar = (BoostRegistrar) var2.next();
return mEngine.getPlatformViewsController().getRegistry(); shimRegistrar.onAttachedToActivity(binding);
} }
@Override
public FlutterView view() {
throw new RuntimeException("should not use!!!");
} }
@Override public void onDetachedFromActivityForConfigChanges() {
public String lookupKeyForAsset(String s) { Iterator var1 = this.shimRegistrars.iterator();
return mRegistrar.lookupKeyForAsset(s);
}
@Override while (var1.hasNext()) {
public String lookupKeyForAsset(String s, String s1) { BoostRegistrar shimRegistrar = (BoostRegistrar) var1.next();
return mRegistrar.lookupKeyForAsset(s, s1); shimRegistrar.onDetachedFromActivity();
} }
@Override this.activityPluginBinding = null;
public PluginRegistry.Registrar publish(Object o) {
return mRegistrar.publish(o);
} }
@Override public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) {
public PluginRegistry.Registrar addRequestPermissionsResultListener(PluginRegistry.RequestPermissionsResultListener requestPermissionsResultListener) { Iterator var2 = this.shimRegistrars.iterator();
return mRegistrar.addRequestPermissionsResultListener(requestPermissionsResultListener);
}
@Override while (var2.hasNext()) {
public PluginRegistry.Registrar addActivityResultListener(PluginRegistry.ActivityResultListener activityResultListener) { BoostRegistrar shimRegistrar = (BoostRegistrar) var2.next();
return mRegistrar.addActivityResultListener(activityResultListener); shimRegistrar.onReattachedToActivityForConfigChanges(binding);
} }
@Override
public PluginRegistry.Registrar addNewIntentListener(PluginRegistry.NewIntentListener newIntentListener) {
return mRegistrar.addNewIntentListener(newIntentListener);
} }
@Override public void onDetachedFromActivity() {
public PluginRegistry.Registrar addUserLeaveHintListener(PluginRegistry.UserLeaveHintListener userLeaveHintListener) { Iterator var1 = this.shimRegistrars.iterator();
return mRegistrar.addUserLeaveHintListener(userLeaveHintListener);
} while (var1.hasNext()) {
BoostRegistrar shimRegistrar = (BoostRegistrar) var1.next();
shimRegistrar.onDetachedFromActivity();
}
@Override
public PluginRegistry.Registrar addViewDestroyListener(PluginRegistry.ViewDestroyListener viewDestroyListener) {
return mRegistrar.addViewDestroyListener(viewDestroyListener);
} }
} }
} }
package com.idlefish.flutterboost;
import android.app.Activity;
import android.content.Context;
import android.support.annotation.NonNull;
import io.flutter.Log;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.PluginRegistry.ActivityResultListener;
import io.flutter.plugin.common.PluginRegistry.NewIntentListener;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener;
import io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener;
import io.flutter.plugin.common.PluginRegistry.ViewDestroyListener;
import io.flutter.plugin.platform.PlatformViewRegistry;
import io.flutter.view.FlutterMain;
import io.flutter.view.FlutterNativeView;
import io.flutter.view.FlutterView;
import io.flutter.view.TextureRegistry;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
class BoostRegistrar implements Registrar, FlutterPlugin, ActivityAware {
private static final String TAG = "ShimRegistrar";
private final Map<String, Object> globalRegistrarMap;
private final String pluginId;
private final Set<ViewDestroyListener> viewDestroyListeners = new HashSet();
private final Set<RequestPermissionsResultListener> requestPermissionsResultListeners = new HashSet();
private final Set<ActivityResultListener> activityResultListeners = new HashSet();
private final Set<NewIntentListener> newIntentListeners = new HashSet();
private final Set<UserLeaveHintListener> userLeaveHintListeners = new HashSet();
private FlutterPluginBinding pluginBinding;
private ActivityPluginBinding activityPluginBinding;
public BoostRegistrar(@NonNull String pluginId, @NonNull Map<String, Object> globalRegistrarMap) {
this.pluginId = pluginId;
this.globalRegistrarMap = globalRegistrarMap;
}
public Activity activity() {
if(this.activityPluginBinding != null){
return this.activityPluginBinding.getActivity();
}
if(NewFlutterBoost.instance().currentActivity()!=null){
return NewFlutterBoost.instance().currentActivity();
}
return null;
}
public Context context() {
return this.pluginBinding != null ? this.pluginBinding.getApplicationContext() : null;
}
public Context activeContext() {
return (Context)(this.activityPluginBinding == null ? this.context() : this.activity());
}
public BinaryMessenger messenger() {
return this.pluginBinding != null ? this.pluginBinding.getFlutterEngine().getDartExecutor() : null;
}
public TextureRegistry textures() {
return this.pluginBinding != null ? this.pluginBinding.getFlutterEngine().getRenderer() : null;
}
public PlatformViewRegistry platformViewRegistry() {
return this.pluginBinding != null ? this.pluginBinding.getFlutterEngine().getPlatformViewsController().getRegistry() : null;
}
public FlutterView view() {
throw new UnsupportedOperationException("The new embedding does not support the old FlutterView.");
}
public String lookupKeyForAsset(String asset) {
return FlutterMain.getLookupKeyForAsset(asset);
}
public String lookupKeyForAsset(String asset, String packageName) {
return FlutterMain.getLookupKeyForAsset(asset, packageName);
}
public Registrar publish(Object value) {
this.globalRegistrarMap.put(this.pluginId, value);
return this;
}
public Registrar addRequestPermissionsResultListener(RequestPermissionsResultListener listener) {
this.requestPermissionsResultListeners.add(listener);
if (this.activityPluginBinding != null) {
this.activityPluginBinding.addRequestPermissionsResultListener(listener);
}
return this;
}
public Registrar addActivityResultListener(ActivityResultListener listener) {
this.activityResultListeners.add(listener);
if (this.activityPluginBinding != null) {
this.activityPluginBinding.addActivityResultListener(listener);
}
return this;
}
public Registrar addNewIntentListener(NewIntentListener listener) {
this.newIntentListeners.add(listener);
if (this.activityPluginBinding != null) {
this.activityPluginBinding.addOnNewIntentListener(listener);
}
return this;
}
public Registrar addUserLeaveHintListener(UserLeaveHintListener listener) {
this.userLeaveHintListeners.add(listener);
if (this.activityPluginBinding != null) {
this.activityPluginBinding.addOnUserLeaveHintListener(listener);
}
return this;
}
@NonNull
public Registrar addViewDestroyListener(@NonNull ViewDestroyListener listener) {
this.viewDestroyListeners.add(listener);
return this;
}
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
Log.v("ShimRegistrar", "Attached to FlutterEngine.");
this.pluginBinding = binding;
}
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
Log.v("ShimRegistrar", "Detached from FlutterEngine.");
Iterator var2 = this.viewDestroyListeners.iterator();
while(var2.hasNext()) {
ViewDestroyListener listener = (ViewDestroyListener)var2.next();
listener.onViewDestroy((FlutterNativeView)null);
}
this.pluginBinding = null;
}
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
Log.v("ShimRegistrar", "Attached to an Activity.");
this.activityPluginBinding = binding;
this.addExistingListenersToActivityPluginBinding();
}
public void onDetachedFromActivityForConfigChanges() {
Log.v("ShimRegistrar", "Detached from an Activity for config changes.");
this.activityPluginBinding = null;
}
public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
Log.v("ShimRegistrar", "Reconnected to an Activity after config changes.");
this.activityPluginBinding = binding;
this.addExistingListenersToActivityPluginBinding();
}
public void onDetachedFromActivity() {
Log.v("ShimRegistrar", "Detached from an Activity.");
this.activityPluginBinding = null;
}
private void addExistingListenersToActivityPluginBinding() {
Iterator var1 = this.requestPermissionsResultListeners.iterator();
while(var1.hasNext()) {
RequestPermissionsResultListener listener = (RequestPermissionsResultListener)var1.next();
this.activityPluginBinding.addRequestPermissionsResultListener(listener);
}
var1 = this.activityResultListeners.iterator();
while(var1.hasNext()) {
ActivityResultListener listener = (ActivityResultListener)var1.next();
this.activityPluginBinding.addActivityResultListener(listener);
}
var1 = this.newIntentListeners.iterator();
while(var1.hasNext()) {
NewIntentListener listener = (NewIntentListener)var1.next();
this.activityPluginBinding.addOnNewIntentListener(listener);
}
var1 = this.userLeaveHintListeners.iterator();
while(var1.hasNext()) {
UserLeaveHintListener listener = (UserLeaveHintListener)var1.next();
this.activityPluginBinding.addOnUserLeaveHintListener(listener);
}
}
}
...@@ -175,6 +175,7 @@ public class ContainerRecord implements IContainerRecord { ...@@ -175,6 +175,7 @@ public class ContainerRecord implements IContainerRecord {
@Override @Override
public void onContainerResult(int requestCode, int resultCode, Map<String, Object> result) { public void onContainerResult(int requestCode, int resultCode, Map<String, Object> result) {
mManager.setContainerResult(this, requestCode,resultCode, result);
} }
...@@ -192,41 +193,6 @@ public class ContainerRecord implements IContainerRecord { ...@@ -192,41 +193,6 @@ public class ContainerRecord implements IContainerRecord {
public void onLowMemory() { public void onLowMemory() {
} }
//
// @Override
// public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
// mContainer.getBoostFlutterView().onRequestPermissionsResult(requestCode, permissions, grantResults);
// }
//
// @Override
// public void onNewIntent(Intent intent) {
// mContainer.getBoostFlutterView().onNewIntent(intent);
// }
//
// @Override
// public void onActivityResult(int requestCode, int resultCode, Intent data) {
// mContainer.getBoostFlutterView().onActivityResult(requestCode, resultCode, data);
// }
//
// @Override
// public void onContainerResult(int requestCode, int resultCode, Map<String, Object> result) {
// mManager.setContainerResult(this, requestCode,resultCode, result);
// }
//
// @Override
// public void onUserLeaveHint() {
// mContainer.getBoostFlutterView().onUserLeaveHint();
// }
//
// @Override
// public void onTrimMemory(int level) {
// mContainer.getBoostFlutterView().onTrimMemory(level);
// }
//
// @Override
// public void onLowMemory() {
// mContainer.getBoostFlutterView().onLowMemory();
// }
private class MethodChannelProxy { private class MethodChannelProxy {
......
...@@ -84,6 +84,13 @@ public class FlutterViewContainerManager implements IContainerManager { ...@@ -84,6 +84,13 @@ public class FlutterViewContainerManager implements IContainerManager {
void removeRecord(IContainerRecord record) { void removeRecord(IContainerRecord record) {
mRecordStack.remove(record); mRecordStack.remove(record);
mRecordMap.remove(record.getContainer()); mRecordMap.remove(record.getContainer());
if(mRecordStack.empty()){
if( NewFlutterBoost.instance().platform().whenEngineDestroy()== NewFlutterBoost.ConfigBuilder.All_FLUTTER_ACTIVITY_DESTROY){
NewFlutterBoost.instance().boostDestroy();
}
}
} }
void setContainerResult(IContainerRecord record,int requestCode, int resultCode, Map<String,Object> result) { void setContainerResult(IContainerRecord record,int requestCode, int resultCode, Map<String,Object> result) {
......
...@@ -10,9 +10,14 @@ import com.idlefish.flutterboost.interfaces.*; ...@@ -10,9 +10,14 @@ import com.idlefish.flutterboost.interfaces.*;
import io.flutter.Log; import io.flutter.Log;
import io.flutter.embedding.android.FlutterView; import io.flutter.embedding.android.FlutterView;
import io.flutter.embedding.engine.FlutterEngine; import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterShellArgs;
import io.flutter.embedding.engine.dart.DartExecutor; import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.embedding.engine.plugins.shim.ShimPluginRegistry;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.view.FlutterMain; import io.flutter.view.FlutterMain;
import java.lang.reflect.Method;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
...@@ -21,12 +26,11 @@ public class NewFlutterBoost { ...@@ -21,12 +26,11 @@ public class NewFlutterBoost {
private Platform mPlatform; private Platform mPlatform;
private FlutterViewContainerManager mManager; private FlutterViewContainerManager mManager;
private FlutterEngine mEngine;
private Activity mCurrentActiveActivity; private Activity mCurrentActiveActivity;
private BoostPluginRegistry mRegistry; private PluginRegistry mRegistry;
static NewFlutterBoost sInstance = null; static NewFlutterBoost sInstance = null;
public static NewFlutterBoost instance() { public static NewFlutterBoost instance() {
if (sInstance == null) { if (sInstance == null) {
sInstance = new NewFlutterBoost(); sInstance = new NewFlutterBoost();
...@@ -41,19 +45,18 @@ public class NewFlutterBoost { ...@@ -41,19 +45,18 @@ public class NewFlutterBoost {
mManager = new FlutterViewContainerManager(); mManager = new FlutterViewContainerManager();
mRegistry = new BoostPluginRegistry(this.engineProvider(),
mPlatform.getApplication());
platform.getApplication().registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() { platform.getApplication().registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
@Override @Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) { public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
Log.e("bbbb1", "xxxxx"); Log.e("bbbb1", "xxxxx");
mCurrentActiveActivity=activity;
if (mPlatform.whenEngineStart() == ConfigBuilder.ANY_ACTIVITY_CREATED) { if (mPlatform.whenEngineStart() == ConfigBuilder.ANY_ACTIVITY_CREATED) {
Log.e("bbbb2", "xxxxx"); Log.e("bbbb2", "xxxxx");
mRegistry.currentActivity(activity);
doInitialFlutterViewRun(mPlatform,mRegistry); doInitialFlutter();
} }
} }
...@@ -62,7 +65,7 @@ public class NewFlutterBoost { ...@@ -62,7 +65,7 @@ public class NewFlutterBoost {
if (mCurrentActiveActivity == null) { if (mCurrentActiveActivity == null) {
Debuger.log("Application entry foreground"); Debuger.log("Application entry foreground");
if (NewFlutterBoost.instance().engineProvider() != null) { if (createEngine() != null) {
HashMap<String, String> map = new HashMap<>(); HashMap<String, String> map = new HashMap<>();
map.put("type", "foreground"); map.put("type", "foreground");
channel().sendEvent("lifecycle", map); channel().sendEvent("lifecycle", map);
...@@ -86,7 +89,7 @@ public class NewFlutterBoost { ...@@ -86,7 +89,7 @@ public class NewFlutterBoost {
if (mCurrentActiveActivity == activity) { if (mCurrentActiveActivity == activity) {
Debuger.log("Application entry background"); Debuger.log("Application entry background");
if (mPlatform.engineProvider() != null) { if (createEngine() != null) {
HashMap<String, String> map = new HashMap<>(); HashMap<String, String> map = new HashMap<>();
map.put("type", "background"); map.put("type", "background");
channel().sendEvent("lifecycle", map); channel().sendEvent("lifecycle", map);
...@@ -105,7 +108,7 @@ public class NewFlutterBoost { ...@@ -105,7 +108,7 @@ public class NewFlutterBoost {
if (mCurrentActiveActivity == activity) { if (mCurrentActiveActivity == activity) {
Debuger.log("Application entry background"); Debuger.log("Application entry background");
if (mPlatform.engineProvider() != null) { if (createEngine() != null) {
HashMap<String, String> map = new HashMap<>(); HashMap<String, String> map = new HashMap<>();
map.put("type", "background"); map.put("type", "background");
channel().sendEvent("lifecycle", map); channel().sendEvent("lifecycle", map);
...@@ -117,39 +120,46 @@ public class NewFlutterBoost { ...@@ -117,39 +120,46 @@ public class NewFlutterBoost {
if (mPlatform.whenEngineStart() == ConfigBuilder.IMMEDIATELY) { if (mPlatform.whenEngineStart() == ConfigBuilder.IMMEDIATELY) {
doInitialFlutterViewRun(mPlatform,mRegistry); doInitialFlutter();
} }
} }
private void doInitialFlutterViewRun(Platform platform,BoostPluginRegistry registry) { public void doInitialFlutter() {
// Don't attempt to start a FlutterEngine if we're using a cached FlutterEngine.
// if (host.getCachedEngineId() != null) {
// return; if(mEngine!=null) return;
// }
FlutterEngine flutterEngine = platform.engineProvider();
FlutterEngine flutterEngine = createEngine();
if(mPlatform.lifecycleListener!=null){
mPlatform.lifecycleListener.onEngineCreated();
}
if (flutterEngine.getDartExecutor().isExecutingDart()) { if (flutterEngine.getDartExecutor().isExecutingDart()) {
// No warning is logged because this situation will happen on every config // No warning is logged because this situation will happen on every config
// change if the developer does not choose to retain the Fragment instance. // change if the developer does not choose to retain the Fragment instance.
// So this is expected behavior in many cases. // So this is expected behavior in many cases.
return; return;
} }
platform.registerPlugins(registry);
// The engine needs to receive the Flutter app's initial route before executing any // The engine needs to receive the Flutter app's initial route before executing any
// Dart code to ensure that the initial route arrives in time to be applied. // Dart code to ensure that the initial route arrives in time to be applied.
if (platform.initialRoute() != null) { if (mPlatform.initialRoute() != null) {
flutterEngine.getNavigationChannel().setInitialRoute(platform.initialRoute()); flutterEngine.getNavigationChannel().setInitialRoute(mPlatform.initialRoute());
} }
// Configure the Dart entrypoint and execute it. // Configure the Dart entrypoint and execute it.
DartExecutor.DartEntrypoint entrypoint = new DartExecutor.DartEntrypoint( DartExecutor.DartEntrypoint entrypoint = new DartExecutor.DartEntrypoint(
FlutterMain.findAppBundlePath(), FlutterMain.findAppBundlePath(),
"main" "main"
); );
flutterEngine.getDartExecutor().executeDartEntrypoint(entrypoint); flutterEngine.getDartExecutor().executeDartEntrypoint(entrypoint);
mRegistry = new BoostPluginRegistry(createEngine());
registerPlugins();
} }
...@@ -161,20 +171,28 @@ public class NewFlutterBoost { ...@@ -161,20 +171,28 @@ public class NewFlutterBoost {
public static int ANY_ACTIVITY_CREATED = 1; //当有任何Activity创建时,启动引擎 public static int ANY_ACTIVITY_CREATED = 1; //当有任何Activity创建时,启动引擎
public static int FLUTTER_ACTIVITY_CREATED = 2; //当有flutterActivity创建时,启动引擎
public static int APP_EXit = 0; //所有flutter Activity destory 时,销毁engine
public static int All_FLUTTER_ACTIVITY_DESTROY = 1; //所有flutter Activity destory 时,销毁engine
private String dartEntrypoint = DEFAULT_DART_ENTRYPOINT; private String dartEntrypoint = DEFAULT_DART_ENTRYPOINT;
private String initialRoute = DEFAULT_INITIAL_ROUTE; private String initialRoute = DEFAULT_INITIAL_ROUTE;
private int whenEngineStart = ANY_ACTIVITY_CREATED; private int whenEngineStart = ANY_ACTIVITY_CREATED;
private int whenEngineDestory = APP_EXit;
private boolean isDebug = false; private boolean isDebug = false;
private FlutterView.RenderMode renderMode = FlutterView.RenderMode.surface; private FlutterView.RenderMode renderMode = FlutterView.RenderMode.texture;
private Application mApp; private Application mApp;
private INativeRouter router = null; private INativeRouter router = null;
private BoostLifecycleListener lifecycleListener;
public ConfigBuilder(Application app, INativeRouter router) { public ConfigBuilder(Application app, INativeRouter router) {
this.router = router; this.router = router;
this.mApp = app; this.mApp = app;
...@@ -200,11 +218,19 @@ public class NewFlutterBoost { ...@@ -200,11 +218,19 @@ public class NewFlutterBoost {
return this; return this;
} }
public ConfigBuilder whenEngineStart(@NonNull int whenEngineStart) { public ConfigBuilder whenEngineStart( int whenEngineStart) {
this.whenEngineStart = whenEngineStart; this.whenEngineStart = whenEngineStart;
return this; return this;
} }
public ConfigBuilder whenEngineDestory( int whenEngineDestory) {
this.whenEngineDestory = whenEngineDestory;
return this;
}
public ConfigBuilder lifecycleListener( BoostLifecycleListener lifecycleListener) {
this.lifecycleListener = lifecycleListener;
return this;
}
public Platform build() { public Platform build() {
Platform platform = new Platform() { Platform platform = new Platform() {
...@@ -232,22 +258,24 @@ public class NewFlutterBoost { ...@@ -232,22 +258,24 @@ public class NewFlutterBoost {
return ConfigBuilder.this.whenEngineStart; return ConfigBuilder.this.whenEngineStart;
} }
@Override
public int whenEngineDestroy() {
return ConfigBuilder.this.whenEngineDestory;
}
public FlutterView.RenderMode renderMode() { public FlutterView.RenderMode renderMode() {
return ConfigBuilder.this.renderMode; return ConfigBuilder.this.renderMode;
} }
}; };
platform.lifecycleListener=this.lifecycleListener;
return platform; return platform;
} }
} }
public FlutterEngine engineProvider() {
return sInstance.mPlatform.engineProvider();
}
public IContainerManager containerManager() { public IContainerManager containerManager() {
return sInstance.mManager; return sInstance.mManager;
} }
...@@ -268,7 +296,63 @@ public class NewFlutterBoost { ...@@ -268,7 +296,63 @@ public class NewFlutterBoost {
return mManager.findContainerById(id); return mManager.findContainerById(id);
} }
public BoostPluginRegistry getPluginRegistry(){ public PluginRegistry getPluginRegistry(){
return mRegistry; return mRegistry;
} }
private FlutterEngine createEngine(){
if (mEngine == null) {
FlutterMain.startInitialization(mPlatform.getApplication());
FlutterShellArgs flutterShellArgs = new FlutterShellArgs(new String[0]);
FlutterMain.ensureInitializationComplete(
mPlatform.getApplication().getApplicationContext(), flutterShellArgs.toArray());
mEngine = new FlutterEngine(mPlatform.getApplication().getApplicationContext());
}
return mEngine;
}
private void registerPlugins() {
try {
Class clz = Class.forName("io.flutter.plugins.GeneratedPluginRegistrant");
Method method = clz.getDeclaredMethod("registerWith", PluginRegistry.class);
method.invoke(null, mRegistry);
} catch (Throwable t) {
throw new RuntimeException(t);
}
if(mPlatform.lifecycleListener!=null){
mPlatform.lifecycleListener.onPluginsRegistered();
}
}
public FlutterEngine engineProvider() {
return mEngine;
}
public void boostDestroy(){
if(mEngine!=null){
mEngine.destroy();
}
if(mPlatform.lifecycleListener!=null){
mPlatform.lifecycleListener.onEngineDestroy();
}
mEngine=null;
mRegistry=null;
mCurrentActiveActivity=null;
}
public interface BoostLifecycleListener {
void onEngineCreated();
void onPluginsRegistered();
void onEngineDestroy();
}
} }
...@@ -8,57 +8,33 @@ import java.lang.reflect.Method; ...@@ -8,57 +8,33 @@ import java.lang.reflect.Method;
import java.util.Map; import java.util.Map;
import io.flutter.embedding.android.FlutterView; import io.flutter.embedding.android.FlutterView;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterShellArgs;
import io.flutter.plugin.common.PluginRegistry; import io.flutter.plugin.common.PluginRegistry;
import io.flutter.view.FlutterMain;
public abstract class Platform { public abstract class Platform {
public abstract Application getApplication();
public FlutterEngine mEngine ; public abstract void openContainer(Context context, String url, Map<String, Object> urlParams, int requestCode, Map<String, Object> exts);
public abstract Application getApplication(); public abstract int whenEngineStart();
public abstract int whenEngineDestroy();
public abstract void openContainer(Context context, String url, Map<String,Object> urlParams, int requestCode, Map<String,Object> exts); public abstract FlutterView.RenderMode renderMode();
public abstract int whenEngineStart() ; public abstract boolean isDebug();
public abstract FlutterView.RenderMode renderMode(); public abstract String initialRoute();
public abstract boolean isDebug() ;
public abstract String initialRoute();
public NewFlutterBoost.BoostLifecycleListener lifecycleListener;
public void closeContainer(IContainerRecord record, Map<String, Object> result, Map<String, Object> exts) { public void closeContainer(IContainerRecord record, Map<String, Object> result, Map<String, Object> exts) {
if(record == null) return; if (record == null) return;
record.getContainer().finishContainer(result); record.getContainer().finishContainer(result);
} }
public FlutterEngine engineProvider() {
if (mEngine == null) {
FlutterShellArgs flutterShellArgs = new FlutterShellArgs(new String[0]);
FlutterMain.ensureInitializationComplete(
getApplication().getApplicationContext(), flutterShellArgs.toArray());
mEngine = new FlutterEngine( getApplication().getApplicationContext());
}
return mEngine;
}
public void registerPlugins(PluginRegistry registry) {
try {
Class clz = Class.forName("io.flutter.plugins.GeneratedPluginRegistrant");
Method method = clz.getDeclaredMethod("registerWith",PluginRegistry.class);
method.invoke(null,registry);
}catch (Throwable t){
throw new RuntimeException(t);
}
}
} }
...@@ -263,7 +263,7 @@ public class Utils { ...@@ -263,7 +263,7 @@ public class Utils {
return; return;
} }
String [] arr = new String[]{"mServedView", "mNextServedView"}; String [] arr = new String[]{"mLastSrvView","mServedView", "mNextServedView"};
Field f = null; Field f = null;
Object obj_get = null; Object obj_get = null;
for (int i = 0;i < arr.length;i ++) { for (int i = 0;i < arr.length;i ++) {
...@@ -283,7 +283,7 @@ public class Utils { ...@@ -283,7 +283,7 @@ public class Utils {
} }
} }
}catch(Throwable t){ }catch(Throwable t){
t.printStackTrace(); // t.printStackTrace();
} }
} }
} }
......
package com.idlefish.flutterboost;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import io.flutter.embedding.engine.systemchannels.KeyEventChannel;
import io.flutter.plugin.editing.TextInputPlugin;
public class XAndroidKeyProcessor {
@NonNull
private final KeyEventChannel keyEventChannel;
@NonNull
private final XTextInputPlugin textInputPlugin;
private int combiningCharacter;
public XAndroidKeyProcessor(@NonNull KeyEventChannel keyEventChannel, @NonNull XTextInputPlugin textInputPlugin) {
this.keyEventChannel = keyEventChannel;
this.textInputPlugin = textInputPlugin;
}
public void onKeyUp(@NonNull KeyEvent keyEvent) {
Character complexCharacter = applyCombiningCharacterToBaseCharacter(keyEvent.getUnicodeChar());
keyEventChannel.keyUp(
new KeyEventChannel.FlutterKeyEvent(keyEvent, complexCharacter)
);
}
public void onKeyDown(@NonNull KeyEvent keyEvent) {
if (textInputPlugin.getLastInputConnection() != null
&& textInputPlugin.getInputMethodManager().isAcceptingText()) {
textInputPlugin.getLastInputConnection().sendKeyEvent(keyEvent);
}
Character complexCharacter = applyCombiningCharacterToBaseCharacter(keyEvent.getUnicodeChar());
keyEventChannel.keyDown(
new KeyEventChannel.FlutterKeyEvent(keyEvent, complexCharacter)
);
}
/**
* Applies the given Unicode character in {@code newCharacterCodePoint} to a previously
* entered Unicode combining character and returns the combination of these characters
* if a combination exists.
* <p>
* This method mutates {@link #combiningCharacter} over time to combine characters.
* <p>
* One of the following things happens in this method:
* <ul>
* <li>If no previous {@link #combiningCharacter} exists and the {@code newCharacterCodePoint}
* is not a combining character, then {@code newCharacterCodePoint} is returned.</li>
* <li>If no previous {@link #combiningCharacter} exists and the {@code newCharacterCodePoint}
* is a combining character, then {@code newCharacterCodePoint} is saved as the
* {@link #combiningCharacter} and null is returned.</li>
* <li>If a previous {@link #combiningCharacter} exists and the {@code newCharacterCodePoint}
* is also a combining character, then the {@code newCharacterCodePoint} is combined with
* the existing {@link #combiningCharacter} and null is returned.</li>
* <li>If a previous {@link #combiningCharacter} exists and the {@code newCharacterCodePoint}
* is not a combining character, then the {@link #combiningCharacter} is applied to the
* regular {@code newCharacterCodePoint} and the resulting complex character is returned. The
* {@link #combiningCharacter} is cleared.</li>
* </ul>
* <p>
* The following reference explains the concept of a "combining character":
* https://en.wikipedia.org/wiki/Combining_character
*/
@Nullable
private Character applyCombiningCharacterToBaseCharacter(int newCharacterCodePoint) {
if (newCharacterCodePoint == 0) {
return null;
}
Character complexCharacter = (char) newCharacterCodePoint;
boolean isNewCodePointACombiningCharacter = (newCharacterCodePoint & KeyCharacterMap.COMBINING_ACCENT) != 0;
if (isNewCodePointACombiningCharacter) {
// If a combining character was entered before, combine this one with that one.
int plainCodePoint = newCharacterCodePoint & KeyCharacterMap.COMBINING_ACCENT_MASK;
if (combiningCharacter != 0) {
combiningCharacter = KeyCharacterMap.getDeadChar(combiningCharacter, plainCodePoint);
} else {
combiningCharacter = plainCodePoint;
}
} else {
// The new character is a regular character. Apply combiningCharacter to it, if it exists.
if (combiningCharacter != 0) {
int combinedChar = KeyCharacterMap.getDeadChar(combiningCharacter, newCharacterCodePoint);
if (combinedChar > 0) {
complexCharacter = (char) combinedChar;
}
combiningCharacter = 0;
}
}
return complexCharacter;
}
}
\ No newline at end of file
...@@ -90,14 +90,16 @@ public class XFlutterView extends FrameLayout { ...@@ -90,14 +90,16 @@ public class XFlutterView extends FrameLayout {
// These components essentially add some additional behavioral logic on top of // These components essentially add some additional behavioral logic on top of
// existing, stateless system channels, e.g., KeyEventChannel, TextInputChannel, etc. // existing, stateless system channels, e.g., KeyEventChannel, TextInputChannel, etc.
@Nullable @Nullable
private TextInputPlugin textInputPlugin; private XTextInputPlugin textInputPlugin;
@Nullable @Nullable
private AndroidKeyProcessor androidKeyProcessor; private XAndroidKeyProcessor androidKeyProcessor;
@Nullable @Nullable
private AndroidTouchProcessor androidTouchProcessor; private AndroidTouchProcessor androidTouchProcessor;
@Nullable @Nullable
private AccessibilityBridge accessibilityBridge; private AccessibilityBridge accessibilityBridge;
private boolean hasAddFirstFrameRenderedListener=false;
// Directly implemented View behavior that communicates with Flutter. // Directly implemented View behavior that communicates with Flutter.
private final FlutterRenderer.ViewportMetrics viewportMetrics = new FlutterRenderer.ViewportMetrics(); private final FlutterRenderer.ViewportMetrics viewportMetrics = new FlutterRenderer.ViewportMetrics();
...@@ -566,6 +568,7 @@ public class XFlutterView extends FrameLayout { ...@@ -566,6 +568,7 @@ public class XFlutterView extends FrameLayout {
* See {@link #detachFromFlutterEngine()} for information on how to detach from a * See {@link #detachFromFlutterEngine()} for information on how to detach from a
* {@link FlutterEngine}. * {@link FlutterEngine}.
*/ */
public void attachToFlutterEngine( public void attachToFlutterEngine(
@NonNull FlutterEngine flutterEngine @NonNull FlutterEngine flutterEngine
) { ) {
...@@ -582,27 +585,35 @@ public class XFlutterView extends FrameLayout { ...@@ -582,27 +585,35 @@ public class XFlutterView extends FrameLayout {
+ " to new engine."); + " to new engine.");
detachFromFlutterEngine(); detachFromFlutterEngine();
} }
this.requestFocus();
this.flutterEngine = flutterEngine; this.flutterEngine = flutterEngine;
// Instruct our FlutterRenderer that we are now its designated RenderSurface. // Instruct our FlutterRenderer that we are now its designated RenderSurface.
FlutterRenderer flutterRenderer = this.flutterEngine.getRenderer(); FlutterRenderer flutterRenderer = this.flutterEngine.getRenderer();
didRenderFirstFrame = flutterRenderer.hasRenderedFirstFrame(); didRenderFirstFrame = flutterRenderer.hasRenderedFirstFrame();
if(!hasAddFirstFrameRenderedListener){
flutterRenderer.addOnFirstFrameRenderedListener(onFirstFrameRenderedListener);
hasAddFirstFrameRenderedListener=true;
}
flutterRenderer.attachToRenderSurface(renderSurface); flutterRenderer.attachToRenderSurface(renderSurface);
flutterRenderer.addOnFirstFrameRenderedListener(onFirstFrameRenderedListener);
// Initialize various components that know how to process Android View I/O // Initialize various components that know how to process Android View I/O
// in a way that Flutter understands. // in a way that Flutter understands.
if(this.textInputPlugin!=null){
this.textInputPlugin.destroy();
resolveMemoryLeaks();
if(textInputPlugin==null){
textInputPlugin = new XTextInputPlugin(
this,
flutterEngine.getTextInputChannel(),
this.flutterEngine.getPlatformViewsController()
);
} }
this.textInputPlugin = new TextInputPlugin(this, this.flutterEngine.getDartExecutor(), this.flutterEngine.getPlatformViewsController()); textInputPlugin.setTextInputMethodHandler();
textInputPlugin.getInputMethodManager().restartInput(this);
this.androidKeyProcessor = new AndroidKeyProcessor( this.androidKeyProcessor = new XAndroidKeyProcessor(
this.flutterEngine.getKeyEventChannel(), this.flutterEngine.getKeyEventChannel(),
textInputPlugin textInputPlugin
); );
...@@ -643,9 +654,9 @@ public class XFlutterView extends FrameLayout { ...@@ -643,9 +654,9 @@ public class XFlutterView extends FrameLayout {
// If the first frame has already been rendered, notify all first frame listeners. // If the first frame has already been rendered, notify all first frame listeners.
// Do this after all other initialization so that listeners don't inadvertently interact // Do this after all other initialization so that listeners don't inadvertently interact
// with a FlutterView that is only partially attached to a FlutterEngine. // with a FlutterView that is only partially attached to a FlutterEngine.
if (didRenderFirstFrame) { // if (didRenderFirstFrame) {
onFirstFrameRenderedListener.onFirstFrameRendered(); // onFirstFrameRenderedListener.onFirstFrameRendered();
} // }
} }
/** /**
...@@ -681,9 +692,8 @@ public class XFlutterView extends FrameLayout { ...@@ -681,9 +692,8 @@ public class XFlutterView extends FrameLayout {
// now that the engine is detached. The new InputConnection will be null, which // now that the engine is detached. The new InputConnection will be null, which
// signifies that this View does not process input (until a new engine is attached). // signifies that this View does not process input (until a new engine is attached).
// TODO(mattcarroll): once this is proven to work, move this line ot TextInputPlugin // TODO(mattcarroll): once this is proven to work, move this line ot TextInputPlugin
textInputPlugin.getInputMethodManager().restartInput(this);
textInputPlugin.destroy(); // resolveMemoryLeaks();
resolveMemoryLeaks();
// Instruct our FlutterRenderer that we are no longer interested in being its RenderSurface. // Instruct our FlutterRenderer that we are no longer interested in being its RenderSurface.
FlutterRenderer flutterRenderer = flutterEngine.getRenderer(); FlutterRenderer flutterRenderer = flutterEngine.getRenderer();
// didRenderFirstFrame = false; // didRenderFirstFrame = false;
...@@ -691,7 +701,9 @@ public class XFlutterView extends FrameLayout { ...@@ -691,7 +701,9 @@ public class XFlutterView extends FrameLayout {
flutterRenderer.detachFromRenderSurface(); flutterRenderer.detachFromRenderSurface();
flutterEngine = null; flutterEngine = null;
} }
public void release(){
textInputPlugin.release();
}
public void resolveMemoryLeaks(){ public void resolveMemoryLeaks(){
try { try {
......
...@@ -15,9 +15,11 @@ import android.view.ViewGroup; ...@@ -15,9 +15,11 @@ import android.view.ViewGroup;
import java.io.Serializable; import java.io.Serializable;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.idlefish.flutterboost.BoostPluginRegistry;
import com.idlefish.flutterboost.NewFlutterBoost; import com.idlefish.flutterboost.NewFlutterBoost;
import com.idlefish.flutterboost.Utils; import com.idlefish.flutterboost.Utils;
import com.idlefish.flutterboost.XFlutterView; import com.idlefish.flutterboost.XFlutterView;
...@@ -28,6 +30,7 @@ import io.flutter.app.FlutterActivity; ...@@ -28,6 +30,7 @@ import io.flutter.app.FlutterActivity;
import io.flutter.embedding.android.*; import io.flutter.embedding.android.*;
import io.flutter.embedding.engine.FlutterEngine; import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterShellArgs; import io.flutter.embedding.engine.FlutterShellArgs;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.platform.PlatformPlugin; import io.flutter.plugin.platform.PlatformPlugin;
import io.flutter.view.FlutterMain; import io.flutter.view.FlutterMain;
...@@ -74,12 +77,15 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine ...@@ -74,12 +77,15 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
return flutterEngine; return flutterEngine;
} }
XFlutterView getFlutterView(){
return flutterView;
}
void onAttach(@NonNull Context context) { void onAttach(@NonNull Context context) {
ensureAlive(); ensureAlive();
if (NewFlutterBoost.instance().platform().whenEngineStart() == NewFlutterBoost.ConfigBuilder.FLUTTER_ACTIVITY_CREATED) {
initializeFlutter(context); NewFlutterBoost.instance().doInitialFlutter();
}
// When "retain instance" is true, the FlutterEngine will survive configuration // When "retain instance" is true, the FlutterEngine will survive configuration
// changes. Therefore, we create a new one only if one does not already exist. // changes. Therefore, we create a new one only if one does not already exist.
if (flutterEngine == null) { if (flutterEngine == null) {
...@@ -94,47 +100,16 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine ...@@ -94,47 +100,16 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
// use-cases. // use-cases.
platformPlugin = host.providePlatformPlugin(host.getActivity(), flutterEngine); platformPlugin = host.providePlatformPlugin(host.getActivity(), flutterEngine);
if (host.shouldAttachEngineToActivity()) {
// Notify any plugins that are currently attached to our FlutterEngine that they
// are now attached to an Activity.
//
// Passing this Fragment's Lifecycle should be sufficient because as long as this Fragment
// is attached to its Activity, the lifecycles should be in sync. Once this Fragment is
// detached from its Activity, that Activity will be detached from the FlutterEngine, too,
// which means there shouldn't be any possibility for the Fragment Lifecycle to get out of
// sync with the Activity. We use the Fragment's Lifecycle because it is possible that the
// attached Activity is not a LifecycleOwner.
Log.d(TAG, "Attaching FlutterEngine to the Activity that owns this Fragment.");
flutterEngine.getActivityControlSurface().attachToActivity(
host.getActivity(),
host.getLifecycle()
);
}
host.configureFlutterEngine(flutterEngine); host.configureFlutterEngine(flutterEngine);
} }
private void initializeFlutter(@NonNull Context context) {
FlutterMain.ensureInitializationComplete(
context.getApplicationContext(),
host.getFlutterShellArgs().toArray()
);
}
private void setupFlutterEngine() { private void setupFlutterEngine() {
Log.d(TAG, "Setting up FlutterEngine."); Log.d(TAG, "Setting up FlutterEngine.");
// First, check if the host wants to use a cached FlutterEngine.
// String cachedEngineId = host.getCachedEngineId();
// if (cachedEngineId != null) {
// flutterEngine = FlutterEngineCache.getInstance().get(cachedEngineId);
// isFlutterEngineFromHost = true;
// if (flutterEngine == null) {
// throw new IllegalStateException("The requested cached FlutterEngine did not exist in the FlutterEngineCache: '" + cachedEngineId + "'");
// }
// return;
// }
// Second, defer to subclasses for a custom FlutterEngine. // Second, defer to subclasses for a custom FlutterEngine.
flutterEngine = host.provideFlutterEngine(host.getContext()); flutterEngine = host.provideFlutterEngine(host.getContext());
...@@ -147,7 +122,6 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine ...@@ -147,7 +122,6 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
// FlutterView. // FlutterView.
Log.d(TAG, "No preferred FlutterEngine was provided. Creating a new FlutterEngine for" Log.d(TAG, "No preferred FlutterEngine was provided. Creating a new FlutterEngine for"
+ " this NewFlutterFragment."); + " this NewFlutterFragment.");
flutterEngine = new FlutterEngine(host.getContext());
isFlutterEngineFromHost = false; isFlutterEngineFromHost = false;
} }
...@@ -156,6 +130,11 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine ...@@ -156,6 +130,11 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
@NonNull @NonNull
View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.v(TAG, "Creating FlutterView."); Log.v(TAG, "Creating FlutterView.");
flutterEngine.getActivityControlSurface().attachToActivity(
host.getActivity(),
host.getLifecycle()
);
mSyncer = NewFlutterBoost.instance().containerManager().generateSyncer(this); mSyncer = NewFlutterBoost.instance().containerManager().generateSyncer(this);
...@@ -198,22 +177,24 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine ...@@ -198,22 +177,24 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
Log.v(TAG, "onResume()"); Log.v(TAG, "onResume()");
ensureAlive(); ensureAlive();
flutterEngine.getLifecycleChannel().appIsResumed(); flutterEngine.getLifecycleChannel().appIsResumed();
BoostPluginRegistry registry= (BoostPluginRegistry)NewFlutterBoost.instance().getPluginRegistry();
ActivityPluginBinding binding=registry.getRegistrarAggregate().getActivityPluginBinding();
if(binding!=null&&(binding.getActivity()!=this.host.getActivity())){
flutterEngine.getActivityControlSurface().attachToActivity(
host.getActivity(),
host.getLifecycle()
);
}
} }
void onPostResume() { void onPostResume() {
Log.v(TAG, "onPostResume()"); Log.v(TAG, "onPostResume()");
ensureAlive(); ensureAlive();
if (flutterEngine != null) { Utils.setStatusBarLightMode(host.getActivity(),true);
if (platformPlugin != null) {
// TODO(mattcarroll): find a better way to handle the update of UI overlays than calling through
// to platformPlugin. We're implicitly entangling the Window, Activity, Fragment,
// and engine all with this one call.
platformPlugin.updateSystemUiOverlays();
}
} else {
Log.w(TAG, "onPostResume() invoked before NewFlutterFragment was attached to an Activity.");
}
} }
...@@ -229,7 +210,8 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine ...@@ -229,7 +210,8 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
void onStop() { void onStop() {
Log.v(TAG, "onStop()"); Log.v(TAG, "onStop()");
ensureAlive(); ensureAlive();
// flutterView.detachFromFlutterEngine();
} }
void onDestroyView() { void onDestroyView() {
...@@ -237,6 +219,14 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine ...@@ -237,6 +219,14 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
mSyncer.onDestroy(); mSyncer.onDestroy();
ensureAlive(); ensureAlive();
BoostPluginRegistry registry= (BoostPluginRegistry)NewFlutterBoost.instance().getPluginRegistry();
ActivityPluginBinding binding=registry.getRegistrarAggregate().getActivityPluginBinding();
if(binding!=null&&(binding.getActivity()==this.host.getActivity())){
registry.getRegistrarAggregate().onDetachedFromActivityForConfigChanges();
flutterEngine.getActivityControlSurface().detachFromActivityForConfigChanges();
}
flutterView.release();
} }
...@@ -244,15 +234,7 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine ...@@ -244,15 +234,7 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
Log.v(TAG, "onDetach()"); Log.v(TAG, "onDetach()");
ensureAlive(); ensureAlive();
if (host.shouldAttachEngineToActivity()) {
// Notify plugins that they are no longer attached to an Activity.
Log.d(TAG, "Detaching FlutterEngine from the Activity that owns this Fragment.");
if (host.getActivity().isChangingConfigurations()) {
flutterEngine.getActivityControlSurface().detachFromActivityForConfigChanges();
} else {
flutterEngine.getActivityControlSurface().detachFromActivity();
}
}
// Null out the platformPlugin to avoid a possible retain cycle between the plugin, this Fragment, // Null out the platformPlugin to avoid a possible retain cycle between the plugin, this Fragment,
// and this Fragment's Activity. // and this Fragment's Activity.
...@@ -263,16 +245,6 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine ...@@ -263,16 +245,6 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
Utils.fixInputMethodManagerLeak(host.getActivity()); Utils.fixInputMethodManagerLeak(host.getActivity());
// Destroy our FlutterEngine if we're not set to retain it.
// if (host.shouldDestroyEngineWithHost()) {
// flutterEngine.destroy();
//
// if (host.getCachedEngineId() != null) {
// FlutterEngineCache.getInstance().remove(host.getCachedEngineId());
// }
//
// flutterEngine = null;
// }
} }
...@@ -280,12 +252,6 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine ...@@ -280,12 +252,6 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
mSyncer.onBackPressed(); mSyncer.onBackPressed();
ensureAlive(); ensureAlive();
// if (flutterEngine != null) {
// Log.v(TAG, "Forwarding onBackPressed() to FlutterEngine.");
// flutterEngine.getNavigationChannel().popRoute();
// } else {
// Log.w(TAG, "Invoked onBackPressed() before NewFlutterFragment was attached to an Activity.");
// }
} }
...@@ -402,10 +368,26 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine ...@@ -402,10 +368,26 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
@Override @Override
public void finishContainer(Map<String, Object> result) { public void finishContainer(Map<String, Object> result) {
this.host.finishContainer(result);
if(result != null) {
setBoostResult(this.host.getActivity(),new HashMap<>(result));
this.host.getActivity().finish();
}else{
this.host.getActivity().finish();
}
} }
public void setBoostResult(Activity activity, HashMap result) {
Intent intent = new Intent();
if (result != null) {
intent.putExtra(IFlutterViewContainer.RESULT_KEY, result);
}
activity.setResult(Activity.RESULT_OK, intent);
}
@Override @Override
public String getContainerUrl() { public String getContainerUrl() {
return this.host.getContainerUrl(); return this.host.getContainerUrl();
...@@ -503,7 +485,6 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine ...@@ -503,7 +485,6 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
void finishContainer(Map<String, Object> result) ;
String getContainerUrl() ; String getContainerUrl() ;
......
...@@ -59,9 +59,8 @@ public class FlutterSplashView extends FrameLayout { ...@@ -59,9 +59,8 @@ public class FlutterSplashView extends FrameLayout {
private final OnFirstFrameRenderedListener onFirstFrameRenderedListener = new OnFirstFrameRenderedListener() { private final OnFirstFrameRenderedListener onFirstFrameRenderedListener = new OnFirstFrameRenderedListener() {
@Override @Override
public void onFirstFrameRendered() { public void onFirstFrameRendered() {
if (splashScreen != null&&!hasRendered) { if (splashScreen != null) {
transitionToFlutter(); transitionToFlutter();
hasRendered=true;
} }
} }
}; };
...@@ -292,6 +291,9 @@ public class FlutterSplashView extends FrameLayout { ...@@ -292,6 +291,9 @@ public class FlutterSplashView extends FrameLayout {
} }
} }
public void onAttach() { public void onAttach() {
Debuger.log("BoostFlutterView onAttach"); Debuger.log("BoostFlutterView onAttach");
......
...@@ -21,6 +21,7 @@ import android.view.*; ...@@ -21,6 +21,7 @@ import android.view.*;
import android.widget.*; import android.widget.*;
import com.idlefish.flutterboost.NewFlutterBoost; import com.idlefish.flutterboost.NewFlutterBoost;
import com.idlefish.flutterboost.Utils; import com.idlefish.flutterboost.Utils;
import com.idlefish.flutterboost.XFlutterView;
import io.flutter.Log; import io.flutter.Log;
import io.flutter.embedding.android.DrawableSplashScreen; import io.flutter.embedding.android.DrawableSplashScreen;
import io.flutter.embedding.android.FlutterView; import io.flutter.embedding.android.FlutterView;
...@@ -241,8 +242,12 @@ public class NewBoostFlutterActivity extends Activity ...@@ -241,8 +242,12 @@ public class NewBoostFlutterActivity extends Activity
window.setStatusBarColor(Color.TRANSPARENT); window.setStatusBarColor(Color.TRANSPARENT);
window.getDecorView().setSystemUiVisibility(PlatformPlugin.DEFAULT_SYSTEM_UI); window.getDecorView().setSystemUiVisibility(PlatformPlugin.DEFAULT_SYSTEM_UI);
} }
Utils.setStatusBarLightMode(this,true);
}
protected XFlutterView getFlutterView(){
return delegate.getFlutterView();
} }
@Override @Override
...@@ -469,12 +474,6 @@ public class NewBoostFlutterActivity extends Activity ...@@ -469,12 +474,6 @@ public class NewBoostFlutterActivity extends Activity
@Override
public void finishContainer(Map<String, Object> result) {
Activity activity= this.getActivity();
activity.finish();
}
@Override @Override
public String getContainerUrl() { public String getContainerUrl() {
......
...@@ -15,6 +15,7 @@ import android.view.View; ...@@ -15,6 +15,7 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import com.idlefish.flutterboost.NewFlutterBoost; import com.idlefish.flutterboost.NewFlutterBoost;
import com.idlefish.flutterboost.XFlutterView;
import io.flutter.embedding.android.*; import io.flutter.embedding.android.*;
import io.flutter.embedding.engine.FlutterEngine; import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterShellArgs; import io.flutter.embedding.engine.FlutterShellArgs;
...@@ -233,6 +234,10 @@ public class NewFlutterFragment extends Fragment implements FlutterActivityAndFr ...@@ -233,6 +234,10 @@ public class NewFlutterFragment extends Fragment implements FlutterActivityAndFr
private FlutterActivityAndFragmentDelegate delegate; private FlutterActivityAndFragmentDelegate delegate;
protected XFlutterView getFlutterView(){
return delegate.getFlutterView();
}
public NewFlutterFragment() { public NewFlutterFragment() {
// Ensure that we at least have an empty Bundle of arguments so that we don't // Ensure that we at least have an empty Bundle of arguments so that we don't
// need to continually check for null arguments before grabbing one. // need to continually check for null arguments before grabbing one.
...@@ -485,16 +490,11 @@ public class NewFlutterFragment extends Fragment implements FlutterActivityAndFr ...@@ -485,16 +490,11 @@ public class NewFlutterFragment extends Fragment implements FlutterActivityAndFr
*/ */
@Override @Override
public boolean shouldAttachEngineToActivity() { public boolean shouldAttachEngineToActivity() {
return getArguments().getBoolean(ARG_SHOULD_ATTACH_ENGINE_TO_ACTIVITY); return true;
} }
@Override
public void finishContainer(Map<String, Object> result) {
Activity activity = this.getActivity();
activity.finish();
}
@Override @Override
public String getContainerUrl() { public String getContainerUrl() {
......
...@@ -3,19 +3,21 @@ package com.taobao.idlefish.flutterboostexample; ...@@ -3,19 +3,21 @@ package com.taobao.idlefish.flutterboostexample;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import android.util.Log;
import com.idlefish.flutterboost.*; import com.idlefish.flutterboost.*;
import com.idlefish.flutterboost.interfaces.IContainerRecord;
import java.util.Map; import java.util.Map;
import com.idlefish.flutterboost.interfaces.INativeRouter; import com.idlefish.flutterboost.interfaces.INativeRouter;
import io.flutter.app.FlutterApplication; import io.flutter.embedding.android.FlutterView;
import io.flutter.plugin.common.MethodChannel;
public class MyApplication extends Application {
public class MyApplication extends FlutterApplication {
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
INativeRouter router =new INativeRouter() { INativeRouter router =new INativeRouter() {
@Override @Override
public void openContainer(Context context, String url, Map<String, Object> urlParams, int requestCode, Map<String, Object> exts) { public void openContainer(Context context, String url, Map<String, Object> urlParams, int requestCode, Map<String, Object> exts) {
...@@ -25,12 +27,36 @@ public class MyApplication extends FlutterApplication { ...@@ -25,12 +27,36 @@ public class MyApplication extends FlutterApplication {
}; };
NewFlutterBoost.BoostLifecycleListener lifecycleListener= new NewFlutterBoost.BoostLifecycleListener() {
@Override
public void onEngineCreated() {
}
@Override
public void onPluginsRegistered() {
MethodChannel mMethodChannel = new MethodChannel( NewFlutterBoost.instance().engineProvider().getDartExecutor(), "methodChannel");
Log.e("MyApplication","MethodChannel create");
TextPlatformViewPlugin.register(NewFlutterBoost.instance().getPluginRegistry().registrarFor("TextPlatformViewPlugin"));
}
@Override
public void onEngineDestroy() {
}
};
Platform platform= new NewFlutterBoost Platform platform= new NewFlutterBoost
.ConfigBuilder(this,router) .ConfigBuilder(this,router)
.isDebug(true) .isDebug(true)
.whenEngineStart(NewFlutterBoost.ConfigBuilder.ANY_ACTIVITY_CREATED) .whenEngineStart(NewFlutterBoost.ConfigBuilder.ANY_ACTIVITY_CREATED)
.renderMode(FlutterView.RenderMode.texture)
.lifecycleListener(lifecycleListener)
.build(); .build();
NewFlutterBoost.instance().init(platform); NewFlutterBoost.instance().init(platform);
} }
} }
package com.taobao.idlefish.flutterboostexample; package com.taobao.idlefish.flutterboostexample;
import io.flutter.app.FlutterPluginRegistry; import io.flutter.app.FlutterPluginRegistry;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.StandardMessageCodec; import io.flutter.plugin.common.StandardMessageCodec;
public class TextPlatformViewPlugin { public class TextPlatformViewPlugin {
public static void register(FlutterPluginRegistry registry) { public static void register(PluginRegistry.Registrar registrar) {
registry.getPlatformViewsController().getRegistry().registerViewFactory("plugins.test/view", registrar.platformViewRegistry().registerViewFactory("plugins.test/view",
new TextPlatformViewFactory(StandardMessageCodec.INSTANCE)); new TextPlatformViewFactory(StandardMessageCodec.INSTANCE));
} }
} }
...@@ -20,6 +20,7 @@ class _MyAppState extends State<MyApp> { ...@@ -20,6 +20,7 @@ class _MyAppState extends State<MyApp> {
'first': (pageName, params, _) => FirstRouteWidget(), 'first': (pageName, params, _) => FirstRouteWidget(),
'second': (pageName, params, _) => SecondRouteWidget(), 'second': (pageName, params, _) => SecondRouteWidget(),
'tab': (pageName, params, _) => TabRouteWidget(), 'tab': (pageName, params, _) => TabRouteWidget(),
'platformView': (pageName, params, _) => PlatformRouteWidget(),
'flutterFragment': (pageName, params, _) => FragmentRouteWidget(params), 'flutterFragment': (pageName, params, _) => FragmentRouteWidget(params),
///可以在native层通过 getContainerParams 来传递参数 ///可以在native层通过 getContainerParams 来传递参数
'flutterPage': (pageName, params, _) { 'flutterPage': (pageName, params, _) {
......
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
typedef void TextViewCreatedCallback(TextViewController controller);
class TextView extends StatefulWidget {
const TextView({
Key key,
this.onTextViewCreated,
}) : super(key: key);
final TextViewCreatedCallback onTextViewCreated;
@override
State<StatefulWidget> createState() => _TextViewState();
}
class _TextViewState extends State<TextView> {
@override
Widget build(BuildContext context) {
if (defaultTargetPlatform == TargetPlatform.android) {
return AndroidView(
viewType: 'plugins.test/view',
onPlatformViewCreated: _onPlatformViewCreated,
);
}
return Text(
'$defaultTargetPlatform is not yet supported by the text_view plugin');
}
void _onPlatformViewCreated(int id) {
if (widget.onTextViewCreated == null) {
return;
}
widget.onTextViewCreated(new TextViewController._(id));
}
}
class TextViewController {
TextViewController._(int id)
: _channel = new MethodChannel('plugins.felix.angelov/textview_$id');
final MethodChannel _channel;
Future<void> setText(String text) async {
assert(text != null);
return _channel.invokeMethod('setText', text);
}
}
\ No newline at end of file
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_boost/flutter_boost.dart'; import 'package:flutter_boost/flutter_boost.dart';
import 'package:flutter_boost_example/platform_view.dart';
class FirstRouteWidget extends StatelessWidget { class FirstRouteWidget extends StatelessWidget {
@override @override
...@@ -68,6 +69,28 @@ class TabRouteWidget extends StatelessWidget { ...@@ -68,6 +69,28 @@ class TabRouteWidget extends StatelessWidget {
} }
} }
class PlatformRouteWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title:Text("Platform Route"),
),
body: Center(
child: RaisedButton(
child: TextView(),
onPressed: () {
print("open second page!");
FlutterBoost.singleton.open("second").then((Map value) {
print(
"call me when page is finished. did recieve second route result $value");
});
},
),
),
);
}
}
class FlutterRouteWidget extends StatefulWidget { class FlutterRouteWidget extends StatefulWidget {
FlutterRouteWidget({this.params,this.message}); FlutterRouteWidget({this.params,this.message});
final Map params; final Map params;
...@@ -85,6 +108,10 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { ...@@ -85,6 +108,10 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
final String message=widget.message; final String message=widget.message;
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
brightness:Brightness.light,
backgroundColor: Colors.white,
textTheme:new TextTheme(title: TextStyle(color: Colors.black)) ,
title: Text('flutter_boost_example'), title: Text('flutter_boost_example'),
), ),
body: SingleChildScrollView( body: SingleChildScrollView(
...@@ -216,6 +243,21 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { ...@@ -216,6 +243,21 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
MaterialPageRoute(builder: (_) => PushWidget())); MaterialPageRoute(builder: (_) => PushWidget()));
}, },
), ),
InkWell(
child: Container(
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
color: Colors.yellow,
child: Text(
'push Platform demo',
style: TextStyle(fontSize: 22.0, color: Colors.black),
)),
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (_) => PlatformRouteWidget()));
},
),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment