// -------------------------------------------------------------------- // Native activity interaction (called from main thread) // -------------------------------------------------------------------- function android_app_create(activity: PANativeActivity; savedState: Pointer; savedStateSize: size_t): Pandroid_app; var android_app: Pandroid_app; PipeDescriptors: TPipeDescriptors; attr: pthread_attr_t; thread: pthread_t; begin android_app := Pandroid_app(__malloc(SizeOf(TAndroid_app))); FillChar(android_app^, SizeOf(TAndroid_app), 0); android_app^.activity := activity; pthread_mutex_init(android_app^.mutex, nil); pthread_cond_init(android_app^.cond, nil); if savedState <> nil then begin android_app^.savedState := __malloc(savedStateSize); android_app^.savedStateSize := savedStateSize; Move(PByte(savedState)^, PByte(android_app^.savedState)^, savedStateSize); end; pipe(PipeDescriptors); android_app^.msgread := PipeDescriptors.ReadDes; android_app^.msgwrite := PipeDescriptors.WriteDes; pthread_attr_init(attr); pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED); pthread_create(thread, attr, @android_app_entry, android_app); pthread_mutex_lock(android_app^.mutex); while android_app^.running = 0 do pthread_cond_wait(android_app^.cond, android_app^.mutex); pthread_mutex_unlock(android_app^.mutex); Result := android_app; end;
function android_app_entry(param: Pointer): Pointer; cdecl; // Delphi: init system unit and RTL. procedure SystemEntry; type TMainFunction = procedure; var DlsymPointer: Pointer; EntryPoint: TMainFunction; begin DlsymPointer := dlsym(RTLD_DEFAULT, '_NativeMain'); if DlsymPointer <> nil then begin EntryPoint := TMainFunction(DlsymPointer); EntryPoint; end; end; var android_app: Pandroid_app; looper: PALooper; begin android_app := Pandroid_app(param); android_app^.config := AConfiguration_new;//建立應用程序config AConfiguration_fromAssetManager(android_app^.config, android_app^.activity^.assetManager); //從主線程獲取消息用 android_app^.cmdPollSource.id := LOOPER_ID_MAIN; android_app^.cmdPollSource.app := android_app; android_app^.cmdPollSource.process := @process_cmd;//設置處理cmd的命令的函數 android_app^.inputPollSource.id := LOOPER_ID_INPUT; android_app^.inputPollSource.app := android_app; android_app^.inputPollSource.process := @process_input;//輸入事件處理的函數 //建立一個looper消息循環,用來抓取消息 looper := ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); ALooper_addFd(looper, android_app^.msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, nil, @android_app^.cmdPollSource); android_app^.looper := looper; pthread_mutex_lock(android_app^.mutex); android_app^.running := 1; //設置,讓線程從等待開啓運行中退出,也就是從android_app_create中退出 pthread_cond_broadcast(android_app^.cond); pthread_mutex_unlock(android_app^.mutex); { Delphi: this will initialize System and any RTL related functions, call unit initialization sections and then project main code, which will enter application main loop. This call will block until the loop ends, which is typically signalled by android_app^.destroyRequested. } SystemEntry;//這裏纔是調用了工程文件的Begin End之間的代碼,是Delphi的一個封裝,實際上,在Android Native中調用的是android_main(android_app);而後再這裏執行一些消息的處理,等待程序運行結束 { This place would be ideal to call unit finalization, class destructors and so on. } // Halt; android_app_destroy(android_app);//銷燬android_app退出線程。這裏實際上纔是Android程序的終結 Result := nil; end;
function android_app_read_cmd(android_app: Pandroid_app): ShortInt; cdecl; var cmd: ShortInt; begin Result := -1; if __read(android_app^.msgread, @cmd, sizeof(cmd)) = SizeOf(cmd) then begin case cmd of APP_CMD_SAVE_STATE: free_saved_state(android_app);//釋放當前的保存狀態 end; Result := cmd; end; end; procedure android_app_pre_exec_cmd(android_app: Pandroid_app; cmd: ShortInt); cdecl; //準備執行命令狀態 begin case cmd of APP_CMD_INPUT_CHANGED: begin pthread_mutex_lock(android_app^.mutex); if android_app^.inputQueue <> nil then AInputQueue_detachLooper(android_app^.inputQueue); android_app^.inputQueue := android_app^.pendingInputQueue; if android_app^.inputQueue <> nil then AInputQueue_attachLooper(android_app^.inputQueue, android_app^.looper, LOOPER_ID_INPUT, nil, @android_app^.inputPollSource); pthread_cond_broadcast(android_app^.cond); pthread_mutex_unlock(android_app^.mutex); end; APP_CMD_INIT_WINDOW: begin pthread_mutex_lock(android_app^.mutex); android_app^.window := android_app^.pendingWindow; pthread_cond_broadcast(android_app^.cond); pthread_mutex_unlock(android_app^.mutex); end; APP_CMD_TERM_WINDOW: pthread_cond_broadcast(android_app^.cond); APP_CMD_RESUME, APP_CMD_START, APP_CMD_PAUSE, APP_CMD_STOP: begin pthread_mutex_lock(android_app^.mutex); android_app^.activityState := cmd; pthread_cond_broadcast(android_app^.cond); pthread_mutex_unlock(android_app^.mutex); end; APP_CMD_CONFIG_CHANGED: AConfiguration_fromAssetManager(android_app^.config, android_app^.activity^.assetManager); APP_CMD_DESTROY: android_app^.destroyRequested := 1; end; end; procedure android_app_post_exec_cmd(android_app: Pandroid_app; cmd: ShortInt); cdecl; begin case cmd of APP_CMD_TERM_WINDOW: begin pthread_mutex_lock(android_app^.mutex); android_app^.window := nil; pthread_cond_broadcast(android_app^.cond); pthread_mutex_unlock(android_app^.mutex); end; APP_CMD_SAVE_STATE: begin pthread_mutex_lock(android_app^.mutex); android_app^.stateSaved := 1; pthread_cond_broadcast(android_app^.cond); pthread_mutex_unlock(android_app^.mutex); end; APP_CMD_RESUME: { Delphi: It is unclear why this line is necessary in original AppGlue, but it prevents FireMonkey applications from recovering saved state. FireMonkey recovers saved state usually after APP_CMD_INIT_WINDOW, which happens much later after CMD_RESUME. } { free_saved_state(android_app) }; end; end; procedure process_cmd(app: Pandroid_app; source: Pandroid_poll_source); cdecl; var cmd: ShortInt; begin cmd := android_app_read_cmd(app);//先讀取命令 android_app_pre_exec_cmd(app, cmd);//準備命令 if Assigned(app^.onAppCmd) then //程序內部的指令處理 app^.onAppCmd(app, cmd); android_app_post_exec_cmd(app, cmd);//執行處理 end;
這些代碼將在Android消息循環中處理調用java
而後程序進入工程文件的Begin End之間,先進入SysInit.pas單元的_InitExe,而後會調用GetThisModuleHandle,這個會調用dlopen(Info.dli_fname, RTLD_LAZY)就是至關於加載Windows的DLL,會先加載(Lib+程序名.so)得到當前句柄,而後dlClose關閉,最後程序以這個工程的庫句柄做爲程序的Hinstance,也就是說咱們的好多資源應該會都打包到這個so中去,最後若是是Android環境,會調用_StartExe,來啓動程序,_StartExe中會調用InitUnits來初始化一些單元,這裏就會調用程序所引用到的各個單元的Initialization中的內容,在這個過程當中會初始化FMX.PlatForm這個跨平臺單元的TPlatformServices類庫,本庫是跨平臺單元服務管理,而後就會調用FMX.PlatForm下的initialization,裏面的RegisterCorePlatformServices會根據選擇的平臺來斷定到底調用哪一個平臺下的RegisterCorePlatformServices,這個斷定經過編譯預處理指令在Implemention下的Use中android
procedure TApplication.Run; var AppService: IFMXApplicationService; begin {$IFNDEF ANDROID} AddExitProc(DoneApplication); {$ENDIF} FRunning := True; try if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationService, AppService) then AppService.Run; finally FRunning := False; end; end;
procedure TPlatformAndroid.Run; begin { Although calling this routine is not really necessary, but it is a way to ensure that "Androidapi.AppGlue.pas" is kept in uses list, in order to export ANativeActivity_onCreate callback. } app_dummy; repeat InternalProcessMessages; until FAndroidApp^.destroyRequested <> 0; end;