在Flutter App工程中的AndroidManifest.xml注冊(cè)了FlutterApplication和MainActivity,跟Android工程一樣都是Application作為入口饺窿,看看Application的代碼肚医。
public class FlutterApplication extends Application {
private Activity mCurrentActivity = null;
public FlutterApplication() {
}
@CallSuper
public void onCreate() {
super.onCreate();
FlutterMain.startInitialization(this);
}
public Activity getCurrentActivity() {
return this.mCurrentActivity;
}
public void setCurrentActivity(Activity mCurrentActivity) {
this.mCurrentActivity = mCurrentActivity;
}
}
在onCreate ()
中調(diào)用了FlutterMain.startInitialization(this);
進(jìn)行初始化。
public static void startInitialization(Context applicationContext) {
startInitialization(applicationContext, new FlutterMain.Settings());
}
public static void startInitialization(Context applicationContext, FlutterMain.Settings settings) {
if(Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("startInitialization must be called on the main thread");
} else if(sSettings == null) {
sSettings = settings;
long initStartTimestampMillis = SystemClock.uptimeMillis();
initConfig(applicationContext);
initAot(applicationContext);
initResources(applicationContext);
System.loadLibrary("flutter");
long initTimeMillis = SystemClock.uptimeMillis() - initStartTimestampMillis;
nativeRecordStartTimestamp(initTimeMillis);
}
}
FlutterMain.Settings
是日志logTag
的設(shè)置舰涌,接著初始化一些配置瓷耙、Aot和資源文件和目錄搁痛,這里不展開了鸡典,最后加載了flutter的so庫(kù)彻况,還調(diào)用了native方法記錄初始化時(shí)間舅踪,接下來(lái)去C++層看看如何進(jìn)行下一步初始化操作的。
// This is called by the VM when the shared library is first loaded.
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
// Initialize the Java VM.
fml::jni::InitJavaVM(vm);
JNIEnv* env = fml::jni::AttachCurrentThread();
bool result = false;
// Register FlutterMain.
result = shell::FlutterMain::Register(env);
FML_CHECK(result);
// Register PlatformView
result = shell::PlatformViewAndroid::Register(env);
FML_CHECK(result);
// Register VSyncWaiter.
result = shell::VsyncWaiterAndroid::Register(env);
FML_CHECK(result);
return JNI_VERSION_1_4;
}
InitJavaVM(vm)
jni_util.cc
void InitJavaVM(JavaVM* vm) {
FML_DCHECK(g_jvm == nullptr);
g_jvm = vm;
}
JNIEnv* AttachCurrentThread() {
FML_DCHECK(g_jvm != nullptr)
<< "Trying to attach to current thread without calling InitJavaVM first.";
JNIEnv* env = nullptr;
jint ret = g_jvm->AttachCurrentThread(&env, nullptr);
FML_DCHECK(JNI_OK == ret);
return env;
}
主要做了以下工作:初始化JavaVM,獲取JNIEnv泽裳。
知識(shí)補(bǔ)充:
- JavaVM破婆,它是虛擬機(jī)在JNI層的代表,全進(jìn)程只有一個(gè)JavaVM對(duì)象瀑梗,不論進(jìn)程中有多少個(gè)線程抛丽,JavaVM卻是獨(dú)此一份饰豺,所以可以保存,并且在任何地方使用都沒有問(wèn)題饶套。
- JNIEnv代表Java環(huán)境垒探。 JNIEnv的指針會(huì)被JNI傳送到本地方法的實(shí)現(xiàn)函數(shù)中來(lái)對(duì)Java端的代碼進(jìn)行操作圾叼,如夷蚊,創(chuàng)建Java類得對(duì)象,調(diào)用Java對(duì)象的方法儿倒,獲取Java對(duì)象的屬性等。
- JNIEnv是一個(gè)與線程相關(guān)的對(duì)象叫胁,不同線程之間不能共享JNIEnv結(jié)構(gòu)體驼鹅。
- 通過(guò)
AttachCurrentThread()
输钩,就可得到這個(gè)線程的JNIEnv結(jié)構(gòu)體买乃。
FlutterMain::Register(env)
flutter_main.cc
bool FlutterMain::Register(JNIEnv* env) {
static const JNINativeMethod methods[] = {
{
.name = "nativeInit",
.signature = "(Landroid/content/Context;[Ljava/lang/String;Ljava/"
"lang/String;Ljava/lang/String;Ljava/lang/String;)V",
.fnPtr = reinterpret_cast<void*>(&Init),
},
{
.name = "nativeRecordStartTimestamp",
.signature = "(J)V",
.fnPtr = reinterpret_cast<void*>(&RecordStartTimestamp),
},
};
jclass clazz = env->FindClass("io/flutter/view/FlutterMain");
if (clazz == nullptr) {
return false;
}
return env->RegisterNatives(clazz, methods, arraysize(methods)) == 0;
}
動(dòng)態(tài)注冊(cè)了兩個(gè)方法nativeInit
和nativeRecordStartTimestamp
剪验,供Java層調(diào)用功戚,依次看看兩個(gè)方法似嗤。
static void RecordStartTimestamp(JNIEnv* env,
jclass jcaller,
jlong initTimeMillis) {
int64_t initTimeMicros =
static_cast<int64_t>(initTimeMillis) * static_cast<int64_t>(1000);
blink::engine_main_enter_ts = Dart_TimelineGetMicros() - initTimeMicros;
}
void FlutterMain::Init(JNIEnv* env,
jclass clazz,
jobject context,
jobjectArray jargs,
jstring bundlePath,
jstring appStoragePath,
jstring engineCachesPath) {
std::vector<std::string> args;
args.push_back("flutter");
for (auto& arg : fml::jni::StringArrayToVector(env, jargs)) {
args.push_back(std::move(arg));
}
auto command_line = fml::CommandLineFromIterators(args.begin(), args.end());
auto settings = SettingsFromCommandLine(command_line);
settings.assets_path = fml::jni::JavaStringToString(env, bundlePath);
// Restore the callback cache.
// TODO(chinmaygarde): Route all cache file access through FML and remove this
// setter.
blink::DartCallbackCache::SetCachePath(
fml::jni::JavaStringToString(env, appStoragePath));
fml::paths::InitializeAndroidCachesPath(
fml::jni::JavaStringToString(env, engineCachesPath));
blink::DartCallbackCache::LoadCacheFromDisk();
if (!blink::DartVM::IsRunningPrecompiledCode()) {
// Check to see if the appropriate kernel files are present and configure
// settings accordingly.
auto application_kernel_path =
fml::paths::JoinPaths({settings.assets_path, "kernel_blob.bin"});
if (fml::IsFile(application_kernel_path)) {
settings.application_kernel_asset = application_kernel_path;
}
}
settings.task_observer_add = [](intptr_t key, fml::closure callback) {
fml::MessageLoop::GetCurrent().AddTaskObserver(key, std::move(callback));
};
settings.task_observer_remove = [](intptr_t key) {
fml::MessageLoop::GetCurrent().RemoveTaskObserver(key);
};
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
// There are no ownership concerns here as all mappings are owned by the
// embedder and not the engine.
auto make_mapping_callback = [](const uint8_t* mapping, size_t size) {
return [mapping, size]() {
return std::make_unique<fml::NonOwnedMapping>(mapping, size);
};
};
settings.dart_library_sources_kernel =
make_mapping_callback(kPlatformStrongDill, kPlatformStrongDillSize);
#endif // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
// Not thread safe. Will be removed when FlutterMain is refactored to no
// longer be a singleton.
g_flutter_main.reset(new FlutterMain(std::move(settings)));
}
static std::unique_ptr<FlutterMain> g_flutter_main;
FlutterMain& FlutterMain::Get() {
FML_CHECK(g_flutter_main) << "ensureInitializationComplete must have already "
"been called.";
return *g_flutter_main;
}
std::unique_ptr使用
RecordStartTimestamp()
前面說(shuō)了是用于記錄初始化的事件豌注,可以說(shuō)是Java層到C++層消息傳遞的初始化時(shí)間谓厘,此時(shí)初始化還未結(jié)束竟稳。
Init()
方法中進(jìn)行了一些路徑的配置聂宾、添加task觀察诊笤、內(nèi)核資源配置等讨跟,最后創(chuàng)建了FlutterMain對(duì)象晾匠。
PlatformViewAndroid::Register(env)
bool PlatformViewAndroid::Register(JNIEnv* env) {
if (env == nullptr) {
FML_LOG(ERROR) << "No JNIEnv provided";
return false;
}
g_flutter_callback_info_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
env, env->FindClass("io/flutter/view/FlutterCallbackInformation"));
if (g_flutter_callback_info_class->is_null()) {
FML_LOG(ERROR) << "Could not locate FlutterCallbackInformation class";
return false;
}
g_flutter_callback_info_constructor = env->GetMethodID(
g_flutter_callback_info_class->obj(), "<init>",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
if (g_flutter_callback_info_constructor == nullptr) {
FML_LOG(ERROR) << "Could not locate FlutterCallbackInformation constructor";
return false;
}
g_flutter_jni_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
env, env->FindClass("io/flutter/embedding/engine/FlutterJNI"));
if (g_flutter_jni_class->is_null()) {
FML_LOG(ERROR) << "Failed to find FlutterJNI Class.";
return false;
}
g_surface_texture_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
env, env->FindClass("android/graphics/SurfaceTexture"));
if (g_surface_texture_class->is_null()) {
FML_LOG(ERROR) << "Could not locate SurfaceTexture class";
return false;
}
static const JNINativeMethod callback_info_methods[] = {
{
.name = "nativeLookupCallbackInformation",
.signature = "(J)Lio/flutter/view/FlutterCallbackInformation;",
.fnPtr = reinterpret_cast<void*>(&shell::LookupCallbackInformation),
},
};
if (env->RegisterNatives(g_flutter_callback_info_class->obj(),
callback_info_methods,
arraysize(callback_info_methods)) != 0) {
FML_LOG(ERROR) << "Failed to RegisterNatives with FlutterCallbackInfo";
return false;
}
g_attach_to_gl_context_method = env->GetMethodID(
g_surface_texture_class->obj(), "attachToGLContext", "(I)V");
if (g_attach_to_gl_context_method == nullptr) {
FML_LOG(ERROR) << "Could not locate attachToGlContext method";
return false;
}
g_update_tex_image_method =
env->GetMethodID(g_surface_texture_class->obj(), "updateTexImage", "()V");
if (g_update_tex_image_method == nullptr) {
FML_LOG(ERROR) << "Could not locate updateTexImage method";
return false;
}
g_get_transform_matrix_method = env->GetMethodID(
g_surface_texture_class->obj(), "getTransformMatrix", "([F)V");
if (g_get_transform_matrix_method == nullptr) {
FML_LOG(ERROR) << "Could not locate getTransformMatrix method";
return false;
}
g_detach_from_gl_context_method = env->GetMethodID(
g_surface_texture_class->obj(), "detachFromGLContext", "()V");
if (g_detach_from_gl_context_method == nullptr) {
FML_LOG(ERROR) << "Could not locate detachFromGlContext method";
return false;
}
return RegisterApi(env);
}
bool RegisterApi(JNIEnv* env) {
static const JNINativeMethod flutter_jni_methods[] = {
// Start of methods from FlutterNativeView
{
.name = "nativeAttach",
.signature = "(Lio/flutter/embedding/engine/FlutterJNI;Z)J",
.fnPtr = reinterpret_cast<void*>(&shell::AttachJNI),
},
{
.name = "nativeDestroy",
.signature = "(J)V",
.fnPtr = reinterpret_cast<void*>(&shell::DestroyJNI),
},
{
.name = "nativeRunBundleAndSnapshotFromLibrary",
.signature = "(J[Ljava/lang/String;Ljava/lang/String;"
"Ljava/lang/String;Landroid/content/res/AssetManager;)V",
.fnPtr =
reinterpret_cast<void*>(&shell::RunBundleAndSnapshotFromLibrary),
},
{
.name = "nativeGetObservatoryUri",
.signature = "()Ljava/lang/String;",
.fnPtr = reinterpret_cast<void*>(&shell::GetObservatoryUri),
},
{
.name = "nativeDispatchEmptyPlatformMessage",
.signature = "(JLjava/lang/String;I)V",
.fnPtr =
reinterpret_cast<void*>(&shell::DispatchEmptyPlatformMessage),
},
{
.name = "nativeDispatchPlatformMessage",
.signature = "(JLjava/lang/String;Ljava/nio/ByteBuffer;II)V",
.fnPtr = reinterpret_cast<void*>(&shell::DispatchPlatformMessage),
},
{
.name = "nativeInvokePlatformMessageResponseCallback",
.signature = "(JILjava/nio/ByteBuffer;I)V",
.fnPtr = reinterpret_cast<void*>(
&shell::InvokePlatformMessageResponseCallback),
},
{
.name = "nativeInvokePlatformMessageEmptyResponseCallback",
.signature = "(JI)V",
.fnPtr = reinterpret_cast<void*>(
&shell::InvokePlatformMessageEmptyResponseCallback),
},
// Start of methods from FlutterView
{
.name = "nativeGetBitmap",
.signature = "(J)Landroid/graphics/Bitmap;",
.fnPtr = reinterpret_cast<void*>(&shell::GetBitmap),
},
{
.name = "nativeSurfaceCreated",
.signature = "(JLandroid/view/Surface;)V",
.fnPtr = reinterpret_cast<void*>(&shell::SurfaceCreated),
},
{
.name = "nativeSurfaceChanged",
.signature = "(JII)V",
.fnPtr = reinterpret_cast<void*>(&shell::SurfaceChanged),
},
{
.name = "nativeSurfaceDestroyed",
.signature = "(J)V",
.fnPtr = reinterpret_cast<void*>(&shell::SurfaceDestroyed),
},
{
.name = "nativeSetViewportMetrics",
.signature = "(JFIIIIIIIIII)V",
.fnPtr = reinterpret_cast<void*>(&shell::SetViewportMetrics),
},
{
.name = "nativeDispatchPointerDataPacket",
.signature = "(JLjava/nio/ByteBuffer;I)V",
.fnPtr = reinterpret_cast<void*>(&shell::DispatchPointerDataPacket),
},
{
.name = "nativeDispatchSemanticsAction",
.signature = "(JIILjava/nio/ByteBuffer;I)V",
.fnPtr = reinterpret_cast<void*>(&shell::DispatchSemanticsAction),
},
{
.name = "nativeSetSemanticsEnabled",
.signature = "(JZ)V",
.fnPtr = reinterpret_cast<void*>(&shell::SetSemanticsEnabled),
},
{
.name = "nativeSetAccessibilityFeatures",
.signature = "(JI)V",
.fnPtr = reinterpret_cast<void*>(&shell::SetAccessibilityFeatures),
},
{
.name = "nativeGetIsSoftwareRenderingEnabled",
.signature = "()Z",
.fnPtr = reinterpret_cast<void*>(&shell::GetIsSoftwareRendering),
},
{
.name = "nativeRegisterTexture",
.signature = "(JJLandroid/graphics/SurfaceTexture;)V",
.fnPtr = reinterpret_cast<void*>(&shell::RegisterTexture),
},
{
.name = "nativeMarkTextureFrameAvailable",
.signature = "(JJ)V",
.fnPtr = reinterpret_cast<void*>(&shell::MarkTextureFrameAvailable),
},
{
.name = "nativeUnregisterTexture",
.signature = "(JJ)V",
.fnPtr = reinterpret_cast<void*>(&shell::UnregisterTexture),
},
};
if (env->RegisterNatives(g_flutter_jni_class->obj(), flutter_jni_methods,
arraysize(flutter_jni_methods)) != 0) {
FML_LOG(ERROR) << "Failed to RegisterNatives with FlutterJNI";
return false;
}
g_handle_platform_message_method =
env->GetMethodID(g_flutter_jni_class->obj(), "handlePlatformMessage",
"(Ljava/lang/String;[BI)V");
if (g_handle_platform_message_method == nullptr) {
FML_LOG(ERROR) << "Could not locate handlePlatformMessage method";
return false;
}
g_handle_platform_message_response_method = env->GetMethodID(
g_flutter_jni_class->obj(), "handlePlatformMessageResponse", "(I[B)V");
if (g_handle_platform_message_response_method == nullptr) {
FML_LOG(ERROR) << "Could not locate handlePlatformMessageResponse method";
return false;
}
g_update_semantics_method =
env->GetMethodID(g_flutter_jni_class->obj(), "updateSemantics",
"(Ljava/nio/ByteBuffer;[Ljava/lang/String;)V");
if (g_update_semantics_method == nullptr) {
FML_LOG(ERROR) << "Could not locate updateSemantics method";
return false;
}
g_update_custom_accessibility_actions_method = env->GetMethodID(
g_flutter_jni_class->obj(), "updateCustomAccessibilityActions",
"(Ljava/nio/ByteBuffer;[Ljava/lang/String;)V");
if (g_update_custom_accessibility_actions_method == nullptr) {
FML_LOG(ERROR)
<< "Could not locate updateCustomAccessibilityActions method";
return false;
}
g_on_first_frame_method =
env->GetMethodID(g_flutter_jni_class->obj(), "onFirstFrame", "()V");
if (g_on_first_frame_method == nullptr) {
FML_LOG(ERROR) << "Could not locate onFirstFrame method";
return false;
}
g_on_engine_restart_method =
env->GetMethodID(g_flutter_jni_class->obj(), "onPreEngineRestart", "()V");
if (g_on_engine_restart_method == nullptr) {
FML_LOG(ERROR) << "Could not locate onEngineRestart method";
return false;
}
return true;
}
可見母谎,同樣是動(dòng)態(tài)注冊(cè)一些方法供Java層調(diào)用销睁,同時(shí)還獲取Java層類中的方法冻记,實(shí)現(xiàn)雙向消息傳遞来惧。
VsyncWaiterAndroid::Register(env)
vsync_waiter_android.cc
bool VsyncWaiterAndroid::Register(JNIEnv* env) {
static const JNINativeMethod methods[] = {{
.name = "nativeOnVsync",
.signature = "(JJJ)V",
.fnPtr = reinterpret_cast<void*>(&OnNativeVsync),
}};
jclass clazz = env->FindClass("io/flutter/view/VsyncWaiter");
if (clazz == nullptr) {
return false;
}
g_vsync_waiter_class = new fml::jni::ScopedJavaGlobalRef<jclass>(env, clazz);
FML_CHECK(!g_vsync_waiter_class->is_null());
g_async_wait_for_vsync_method_ = env->GetStaticMethodID(
g_vsync_waiter_class->obj(), "asyncWaitForVsync", "(J)V");
FML_CHECK(g_async_wait_for_vsync_method_ != nullptr);
return env->RegisterNatives(clazz, methods, arraysize(methods)) == 0;
}
同理,不再分析隅居。
小結(jié)
- 通過(guò)
FlutterApplication
的入口分析钠至,進(jìn)行了原生一些配置,然后通過(guò)加載flutter的so庫(kù)進(jìn)行C++層的配置胎源,建立了Java和C++的消息傳遞通道棉钧。 - 注意僅僅是搭建起橋梁,并沒有觸發(fā)
init()
方法涕蚤,因?yàn)榇藭r(shí)Java沒有調(diào)用nativeInit()
宪卿,此方法觸發(fā)取決于Java層中的FlutterMain.ensureInitializationComplete()
。
另外可知的信息:
- Flutter在Android運(yùn)行也是跟原生App一樣万栅,Application有一個(gè)
FlutterActivity
佑钾,頁(yè)面運(yùn)行在FlutterView
(繼承SurfaceView)上。 - 并未創(chuàng)建
FlutterView
或者使程序跑起來(lái)烦粒,猜測(cè)在創(chuàng)建FlutterActivity后會(huì)有相關(guān)的邏輯扰她。
下一遍禾进,將從FlutterActivity
創(chuàng)建開始分析艇拍。