Created
August 5, 2020 02:05
-
-
Save wei-spring/e0f0586de07507337360b82f9e83dfa4 to your computer and use it in GitHub Desktop.
Tinker for Flutter with FlutterBoost
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.idlefish.flutterboost; | |
import android.app.Activity; | |
import android.app.Application; | |
import android.content.Context; | |
import android.os.Bundle; | |
import android.support.annotation.NonNull; | |
import android.util.Log; | |
import com.idlefish.flutterboost.interfaces.*; | |
import io.flutter.embedding.android.FlutterView; | |
import io.flutter.embedding.engine.FlutterEngine; | |
import io.flutter.embedding.engine.FlutterJNI; | |
import io.flutter.embedding.engine.FlutterShellArgs; | |
import io.flutter.embedding.engine.dart.DartExecutor; | |
import io.flutter.embedding.engine.loader.FlutterLoader; | |
import io.flutter.plugin.common.PluginRegistry; | |
import io.flutter.view.FlutterMain; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.Method; | |
import java.util.HashMap; | |
import java.util.Map; | |
public class FlutterBoost { | |
private Platform mPlatform; | |
private FlutterViewContainerManager mManager; | |
private FlutterEngine mEngine; | |
private Activity mCurrentActiveActivity; | |
private boolean mEnterActivityCreate = false; | |
static FlutterBoost sInstance = null; | |
private static boolean sInit; | |
private long FlutterPostFrameCallTime = 0; | |
private Application.ActivityLifecycleCallbacks mActivityLifecycleCallbacks; | |
private PluginRegistry mRegistry; | |
public long getFlutterPostFrameCallTime() { | |
return FlutterPostFrameCallTime; | |
} | |
private String libPath; | |
public void setFlutterPostFrameCallTime(long FlutterPostFrameCallTime) { | |
this.FlutterPostFrameCallTime = FlutterPostFrameCallTime; | |
} | |
public static FlutterBoost instance() { | |
if (sInstance == null) { | |
sInstance = new FlutterBoost(); | |
} | |
return sInstance; | |
} | |
public void init(Platform platform, final String libName) { | |
if (sInit) { | |
Debuger.log("FlutterBoost is alread inited. Do not init twice"); | |
return; | |
} | |
libPath = libName; | |
mPlatform = platform; | |
mManager = new FlutterViewContainerManager(); | |
mActivityLifecycleCallbacks = new Application.ActivityLifecycleCallbacks() { | |
@Override | |
public void onActivityCreated(Activity activity, Bundle savedInstanceState) { | |
//fix crash:'FlutterBoostPlugin not register yet' | |
//case: initFlutter after Activity.OnCreate method,and then called start/stop crash | |
// In SplashActivity ,showDialog(in OnCreate method) to check permission, if authorized, then init sdk and jump homePage) | |
mEnterActivityCreate = true; | |
mCurrentActiveActivity = activity; | |
if (mPlatform.whenEngineStart() == ConfigBuilder.ANY_ACTIVITY_CREATED) { | |
doInitialFlutter(); | |
} | |
} | |
@Override | |
public void onActivityStarted(Activity activity) { | |
if (!mEnterActivityCreate) { | |
return; | |
} | |
if (mCurrentActiveActivity == null) { | |
Debuger.log("Application entry foreground"); | |
if (mEngine != null) { | |
HashMap<String, String> map = new HashMap<>(); | |
map.put("type", "foreground"); | |
channel().sendEvent("lifecycle", map); | |
} | |
} | |
mCurrentActiveActivity = activity; | |
} | |
@Override | |
public void onActivityResumed(Activity activity) { | |
if (!mEnterActivityCreate) { | |
return; | |
} | |
mCurrentActiveActivity = activity; | |
} | |
@Override | |
public void onActivityPaused(Activity activity) { | |
if (!mEnterActivityCreate) { | |
return; | |
} | |
} | |
@Override | |
public void onActivityStopped(Activity activity) { | |
if (!mEnterActivityCreate) { | |
return; | |
} | |
if (mCurrentActiveActivity == activity) { | |
Debuger.log("Application entry background"); | |
if (mEngine != null) { | |
HashMap<String, String> map = new HashMap<>(); | |
map.put("type", "background"); | |
channel().sendEvent("lifecycle", map); | |
} | |
mCurrentActiveActivity = null; | |
} | |
} | |
@Override | |
public void onActivitySaveInstanceState(Activity activity, Bundle outState) { | |
if (!mEnterActivityCreate) { | |
return; | |
} | |
} | |
@Override | |
public void onActivityDestroyed(Activity activity) { | |
if (!mEnterActivityCreate) { | |
return; | |
} | |
if (mCurrentActiveActivity == activity) { | |
Debuger.log("Application entry background"); | |
if (mEngine != null) { | |
HashMap<String, String> map = new HashMap<>(); | |
map.put("type", "background"); | |
channel().sendEvent("lifecycle", map); | |
} | |
mCurrentActiveActivity = null; | |
} | |
} | |
}; | |
platform.getApplication().registerActivityLifecycleCallbacks(mActivityLifecycleCallbacks); | |
if (mPlatform.whenEngineStart() == ConfigBuilder.IMMEDIATELY) { | |
doInitialFlutter(); | |
} | |
sInit = true; | |
} | |
public void doInitialFlutter() { | |
if (mEngine != null) { | |
return; | |
} | |
if (mPlatform.lifecycleListener != null) { | |
mPlatform.lifecycleListener.beforeCreateEngine(); | |
} | |
FlutterEngine flutterEngine = createEngine(); | |
if (mPlatform.lifecycleListener != null) { | |
mPlatform.lifecycleListener.onEngineCreated(); | |
} | |
if (flutterEngine.getDartExecutor().isExecutingDart()) { | |
return; | |
} | |
if (mPlatform.initialRoute() != null) { | |
flutterEngine.getNavigationChannel().setInitialRoute(mPlatform.initialRoute()); | |
} | |
DartExecutor.DartEntrypoint entrypoint = new DartExecutor.DartEntrypoint( | |
FlutterMain.findAppBundlePath(), | |
"main" | |
); | |
flutterEngine.getDartExecutor().executeDartEntrypoint(entrypoint); | |
} | |
public static class ConfigBuilder { | |
public static final String DEFAULT_DART_ENTRYPOINT = "main"; | |
public static final String DEFAULT_INITIAL_ROUTE = "/"; | |
public static int IMMEDIATELY = 0; //立即启动引擎 | |
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 initialRoute = DEFAULT_INITIAL_ROUTE; | |
private int whenEngineStart = ANY_ACTIVITY_CREATED; | |
private int whenEngineDestory = APP_EXit; | |
private boolean isDebug = false; | |
private FlutterView.RenderMode renderMode = FlutterView.RenderMode.texture; | |
private Application mApp; | |
private INativeRouter router = null; | |
private BoostLifecycleListener lifecycleListener; | |
public ConfigBuilder(Application app, INativeRouter router) { | |
this.router = router; | |
this.mApp = app; | |
} | |
public ConfigBuilder renderMode(FlutterView.RenderMode renderMode) { | |
this.renderMode = renderMode; | |
return this; | |
} | |
public ConfigBuilder dartEntrypoint(@NonNull String dartEntrypoint) { | |
this.dartEntrypoint = dartEntrypoint; | |
return this; | |
} | |
public ConfigBuilder initialRoute(@NonNull String initialRoute) { | |
this.initialRoute = initialRoute; | |
return this; | |
} | |
public ConfigBuilder isDebug(boolean isDebug) { | |
this.isDebug = isDebug; | |
return this; | |
} | |
public ConfigBuilder whenEngineStart(int whenEngineStart) { | |
this.whenEngineStart = whenEngineStart; | |
return this; | |
} | |
public ConfigBuilder lifecycleListener(BoostLifecycleListener lifecycleListener) { | |
this.lifecycleListener = lifecycleListener; | |
return this; | |
} | |
public Platform build() { | |
Platform platform = new Platform() { | |
public Application getApplication() { | |
return ConfigBuilder.this.mApp; | |
} | |
public boolean isDebug() { | |
return ConfigBuilder.this.isDebug; | |
} | |
@Override | |
public String initialRoute() { | |
return ConfigBuilder.this.initialRoute; | |
} | |
public void openContainer(Context context, String url, Map<String, Object> urlParams, int requestCode, Map<String, Object> exts) { | |
router.openContainer(context, url, urlParams, requestCode, exts); | |
} | |
public int whenEngineStart() { | |
return ConfigBuilder.this.whenEngineStart; | |
} | |
public FlutterView.RenderMode renderMode() { | |
return ConfigBuilder.this.renderMode; | |
} | |
}; | |
platform.lifecycleListener = this.lifecycleListener; | |
return platform; | |
} | |
} | |
public IContainerManager containerManager() { | |
return sInstance.mManager; | |
} | |
public Platform platform() { | |
return sInstance.mPlatform; | |
} | |
public FlutterBoostPlugin channel() { | |
return FlutterBoostPlugin.singleton(); | |
} | |
public Activity currentActivity() { | |
return sInstance.mCurrentActiveActivity; | |
} | |
public IFlutterViewContainer findContainerById(String id) { | |
return mManager.findContainerById(id); | |
} | |
private FlutterEngine createEngine() { | |
System.err.println("aaa flutter libpath:" + libPath); | |
if (mEngine == null) { | |
FlutterMain.startInitialization(mPlatform.getApplication()); | |
try { | |
if (!"libapp.so".equals(libPath) && libPath != null && !libPath.equals("null")) { | |
FlutterLoader flutterLoader = FlutterLoader.getInstance(); | |
Log.e("FlutterPatch", "flutterPatchInit() called init after " + libPath); | |
Field field = FlutterLoader.class.getDeclaredField("aotSharedLibraryName"); | |
field.setAccessible(true); | |
field.set(flutterLoader, libPath); | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
FlutterShellArgs flutterShellArgs = new FlutterShellArgs(new String[0]); | |
FlutterMain.ensureInitializationComplete( | |
mPlatform.getApplication().getApplicationContext(), flutterShellArgs.toArray()); | |
mEngine = new FlutterEngine(mPlatform.getApplication().getApplicationContext(), FlutterLoader.getInstance(), new FlutterJNI(), null, true); | |
registerPlugins(mEngine); | |
// mRegistry = new BoostPluginRegistry(createEngine()); | |
// mPlatform.registerPlugins(mRegistry); | |
} | |
return mEngine; | |
} | |
private void registerPlugins(FlutterEngine engine) { | |
try { | |
Class<?> generatedPluginRegistrant = Class.forName("io.flutter.plugins.GeneratedPluginRegistrant"); | |
Method registrationMethod = generatedPluginRegistrant.getDeclaredMethod("registerWith", FlutterEngine.class); | |
registrationMethod.invoke(null, engine); | |
} catch (Exception e) { | |
Debuger.exception(e); | |
} | |
} | |
public FlutterEngine engineProvider() { | |
return mEngine; | |
} | |
public void boostDestroy() { | |
if (mEngine != null) { | |
mEngine.destroy(); | |
} | |
if (mPlatform.lifecycleListener != null) { | |
mPlatform.lifecycleListener.onEngineDestroy(); | |
} | |
mEngine = null; | |
mCurrentActiveActivity = null; | |
} | |
public interface BoostLifecycleListener { | |
void beforeCreateEngine(); | |
void onEngineCreated(); | |
void onPluginsRegistered(); | |
void onEngineDestroy(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment