Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by Yaron

  1. I wonder if anything in my code is not thread safe as I get the occasional random freezes in the copy-background code (bitblt functions) when using multiple threads. As you can see, all the bitmaps are created within the thread's execute function and their source data is coming from bitmaps in the main thread that is copied over within a critical section. This is using Delphi 7. procedure TThumbRendererThread.Execute; var thumbBitmapDarkL : TBitmap; backgroundBitmap : TBitmap; WorkBM : TBitmap; begin thumbBitmapDarkL := TBitmap.Create; backgroundBitmap := TBitmap.Create; WorkBM := TBitmap.Create; WorkBM.Width := thumbWidth; WorkBM.Height := thumbHeightTotal; BackdropChanged := True; While (Terminated = False) do Begin If BackdropChanged = True then Begin csThumbRenderer.Enter; Try // Copy bitmaps from main thread (within Critical Section) thumbBitmapDarkL.Assign(LibNavForm.thumbBitmapDark); backgroundBitmap.Assign(s_mlBackground); Finally csThumbRenderer.Leave; End; BackdropChanged := False; End; DebugLog('Copy backgrounds (before)'); BitBlt(WorkBM.Canvas.Handle,0,0,thumbWidth,thumbHeight,thumbBitmapDarkL.Canvas.Handle,xOfs,yOfs,SRCCOPY); BitBlt(WorkBM.Canvas.Handle,0,thumbHeight,thumbWidth,thumbHeightTotal-thumbHeight,BackgroundBitmap.Canvas.Handle,xOfs,yOfs+thumbHeight,SRCCOPY); DebugLog('Copy backgrounds (after)'); // Do other things End; WorkBM.Free; backgroundBitmap.Free; thumbBitmapDarkL.Free; end;
  2. Thank you Peter & Remy, I wasn't aware that TCanvas was sharing resources, the D7 documentation on lock/unlock refers to use lock to prevent other threads from writing to the canvas, but since my code wasn't accessing the canvas from outside the thread, I didn't think locking was mandatory. I have now changed the code to lock all 3 canvases outside the thread loop. Sherlock: It's funny how one person's confusing syntax is exactly the opposite for another person, I hate using "not" in any boolean check because for me it's confusing with logical (bitwise) operators. John Kouraklis I'm not sure what you mean. I use "csThumbRenderer" TCriticalSection in a try/finally block to copy over the contents of TBitmaps from the main thread. I use the same critical section in the main thread as well when accessing these bitmaps, so there should be no case where the bitmaps are used concurrently by more than one thread.
  3. We all knew it would come this August, but now the Google Play store is showing warning notifications on new uploads: And to top it off, there's a new warning that I have no idea how to address (if it's even possible) with Delphi:
  4. Is it possible to make a sort of "catch all" for all "GET/POST" commands that use a path not specified through mars? For example, I have mars specified to return a page using "http://website.com/rest/info" However, If the client opens the unspecified "http://website.com/rest/none" path, MARS throws an exception. Instead of the exception, I want to catch all unspecified paths and return an HTML result (and keep a record of the unspecified path in my debug logs). Is this possible?
  5. I am trying to upload an image from an html form (see below) to a MARS server. Previously, I was able to get this working when the client was written in Delphi, but now the client is a standard browser and the code fails (LParam.isFile returns false). HTML form: <form method="post"> <input type="text" name="ImageName" required><br> <input type="file" accept="image/jpeg" name="ImageFile" required> </form> The code I used to get the image that doesn't seem to work in this case : var lParam : TFormParam; mStream : TMemoryStream; begin For lParam in aParams do Begin If (SameText(lParam.FieldName, 'ImageFile')) then Begin If (LParam.isFile) then Begin mStream := TMemoryStream.Create; mStream.Write(lParam.AsFile.Bytes,Length(lParam.AsFile.Bytes)); mStream.Position := 0; Try mStream.SaveToFile('d:\test.jpg'); Finally mStream.Free; End; End; End; end; Any ideas?
  6. I believe that I solved this issue, I was missing enctype="multipart/form-data" in the form's statement.
  7. Is there a way to shorten the URL required to access the MARS server? What I did so far was to modify FEngine.AddApplication('DefaultApp', '/v', [ 'Server.Resources.*']); in "Server.Ignition". Ideally, I would like to eliminate the "/rest" and application name entirely, so the entry point would be whatever I define in [Path('')].
  8. For reasons I don't understand, the issue in the screenshot occasionally shows up. Then, when an exception is raised or when I place breakpoints, it causes them to trigger/show on the wrong line of code. Any idea how to resolve this issue?
  9. I am creating an Android application that scales images based on the device's fullscreen resolution. To enable fullscreen, I do: 1. In "Project Options / Application / Version Info" I set the theme to "No TitleBar". 2. Set "Form.Fullscreen" to enabled in the main form's "OnCreate" event. However, I'm having problems detecting when my App is finally fullscreen, I suspect there may be a rounding error in Delphi's function, here is the log: 05-17 03:56:36.660: I/info(15344): FMX: ZP Remote: ZPR_DBG: Screen Scale : 1.3125 05-17 03:56:36.666: I/info(15344): FMX: ZP Remote: ZPR_DBG: IFMXScreenService.GetScreenSize : 1280x736 (with screen scale) 05-17 03:56:36.666: I/info(15344): FMX: ZP Remote: ZPR_DBG: IFMXScreenService.GetScreenSize : 975x561 (original) 05-17 03:56:36.666: I/info(15344): FMX: ZP Remote: ZPR_DBG: Screen : 975x561 05-17 03:56:36.664: I/info(15344): FMX: ZP Remote: ZPR_DBG: Client : 975x537 05-17 03:56:36.724: I/info(15344): FMX: ZP Remote: ZPR_DBG: Client : 975x537 05-17 03:56:36.940: I/info(15344): FMX: ZP Remote: ZPR_DBG: Client : 975x562 The first 4 lines give system detail from IFMXScreenService.GetScreenScale, IFMXScreenService.GetScreenSize and Screen.Width/Screen.Height. Each "client" line shows the values of "ClientWidth/ClientHeight" on a FormResize event. As you can see, the ClientHeight value is higher than the Screen.Height value, which doesm't make sense.
  10. I am writing a server using MARS with the client being a web browser (e.g. firefox) sending form data to the server. I don't want every user to be able to access the form, so I need to implement a login/authentication system. The authentication demo code I've seen ('MARS-Repository\MARS\Demos\Authorization\') seems to require using MARS client-code, which I don't think is possible if the client is a web browser. Do I need to write my own authentication code or is there some way I can leverage MARS's authentication code for this purpose?
  11. Is there documentation on how to use MARS to embed data in a cookie and retrieve it on subsequent calls? And of course, any additional sample code would be a blessing.
  12. I am developing a cross-platform remote control app for my Windows PC media player: https://play.google.com/store/apps/details?id=com.inmatrix.ZP_Remote However, I have a user running Android 9 that reports that right after the splash screen (delphi's built-in splash screen, no custom code), all they see is a gray screen. Since the user is on a rooted phone, I provided a debug APK with code that outputs progress to a log file, however the log file is never created. The only thing I can compare it to is trying to run the App on the Nox emulator running Android 7, which instantly crashes after the splash screen without reaching the first line of code on even a blank application (new multi-device application, with no additional code): Here is the pertinent code that should at least output one line of debug code (which works just fine on all devices I could test locally): program ZP_Remote; {$R *.dres} uses FMX.Forms, FMX.Types, misc_functions, System.IOUtils, System.SyncObjs, MainUnit in 'MainUnit.pas' {MainForm}, transunit in 'transunit.pas'; {$R *.res} begin csDebug := TCriticalSection.Create; clientStopWatch.Start; UserDataPath := System.IOUtils.TPath.GetHomePath+System.IOUtils.TPath.DirectorySeparatorChar+clientName+System.IOUtils.TPath.DirectorySeparatorChar; {$IFDEF TRACEDEBUG}AddDebugEntry('DPR:Start');{$ENDIF} FMX.Types.GlobalUseGPUCanvas := True; // 25->840fps! but messes with font rendering?!? Application.Initialize; {$IFDEF TRACEDEBUG}AddDebugEntry('DPR:Initialized');{$ENDIF} Application.FormFactor.Orientations := [TFormOrientation.Portrait]; {$IFDEF TRACEDEBUG}AddDebugEntry('DPR:Form orientation set');{$ENDIF} Application.CreateForm(TMainForm, MainForm); {$IFDEF TRACEDEBUG}AddDebugEntry('DPR:Form created, ready to run');{$ENDIF} Application.Run; {$IFDEF TRACEDEBUG}AddDebugEntry('DPR:Last line');{$ENDIF} end. And here is the code that writes the debug output: procedure AddDebugEntry(S : String); const UTF8BOM : Array[0..2] of Byte = ($EF,$BB,$BF); Var FileName : String; fStream : TFileStream; sAnsi : UTF8String; S1 : String; begin If csDebug <> nil then csDebug.Enter; Try if UserDataPath <> '' then Begin FileName := UserDataPath+clientDebugFile; If FileExists(FileName) = True then Begin Try fStream := TFileStream.Create(FileName,fmOpenWrite); Except fStream := nil; End; End else Begin Try fStream := TFileStream.Create(FileName,fmCreate); fStream.Write(UTF8BOM,3); Except fStream := nil; End; End; If fStream <> nil then Begin S1 := IntToStr(clientStopWatch.ElapsedMilliseconds); While Length(S1) < 12 do S1 := ' '+S1; S := {$IFDEF DEBUGDATE}DateToStr(Date)+' '+TimeToStr(Time)+' '+{$ENDIF}'['+S1+'] : '+S; sAnsi := UTF8Encode(S)+#13#10; fStream.Seek(0,soFromEnd); fStream.Write(sAnsi[Low(sAnsi)],Length(sAnsi)); fStream.Free; End; End; Finally If csDebug <> nil then csDebug.Leave; End; end; I welcome any advice on the best practices to diagnose and resolve such issues when access to the devices is severely limited.
  13. Please ignore this post, the issue was a combination of a bug and the user's inability to find the output log.
  14. I was able to obtain some logcat/event, any idea what's going on? Logcat: 05-13 16:00:47.545 I/ActivityManager( 1383): START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity bnds=[37,1730][238,2028]} from uid 10015 05-13 16:00:47.636 I/ActivityManager( 1383): Start proc 14206:com.inmatrix.ZP_Remote/u0a227 for activity com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity 05-13 16:00:48.297 W/linker (14206): Warning: "/data/app/com.inmatrix.ZP_Remote-S-1zk8LZ5cw0Sxl-7bv-GA==/lib/arm/libZP_Remote.so" unused DT entry: DT_RPATH (type 0xf arg 0x145ae) (ignoring) 05-13 16:00:49.598 D/SurfaceFlinger( 814): duplicate layer name: changing SurfaceView - com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity to SurfaceView - com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity#1 05-13 16:00:49.599 D/SurfaceFlinger( 814): duplicate layer name: changing Background for -SurfaceView - com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity to Background for -SurfaceView - com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity#1 05-13 16:00:49.994 I/ActivityManager( 1383): Displayed com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity: +2s446ms 05-13 16:00:50.100 W/SurfaceFlinger( 814): Attempting to set client state on removed layer: Splash Screen com.inmatrix.ZP_Remote#0 05-13 16:00:50.100 W/SurfaceFlinger( 814): Attempting to destroy on removed layer: Splash Screen com.inmatrix.ZP_Remote#0 05-13 16:00:57.071 E/BufferQueueProducer( 814): [SurfaceView - com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity#1] disconnect: not connected (req=1) 05-13 16:00:58.326 W/InputDispatcher( 1383): channel '3be32e5 com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity (server)' ~ Consumer closed input channel or an error occurred. events=0x9 05-13 16:00:58.326 E/InputDispatcher( 1383): channel '3be32e5 com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity (server)' ~ Channel is unrecoverably broken and will be disposed! 05-13 16:00:58.329 I/ActivityManager( 1383): Process com.inmatrix.ZP_Remote (pid 14206) has died: cch CRE 05-13 16:00:58.329 I/WindowManager( 1383): WIN DEATH: Window{3be32e5 u0 com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity} 05-13 16:00:58.329 W/InputDispatcher( 1383): Attempted to unregister already unregistered input channel '3be32e5 com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity (server)' 05-13 16:00:58.349 W/SurfaceFlinger( 814): Attempting to destroy on removed layer: AppWindowToken{58e86aa token=Token{2ad595 ActivityRecord{e1ab14c u0 com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity t9944}}}#0 Events: 05-13 15:56:13.909 I/am_create_activity( 1383): [0,177586847,9925,com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity,android.intent.action.MAIN,NULL,NULL,270532608] 05-13 15:56:13.971 I/am_proc_start( 1383): [0,11738,10227,com.inmatrix.ZP_Remote,activity,com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity] 05-13 15:56:14.131 I/am_proc_bound( 1383): [0,11738,com.inmatrix.ZP_Remote] 05-13 15:56:14.143 I/am_restart_activity( 1383): [0,177586847,9925,com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity] 05-13 15:56:14.145 I/am_set_resumed_activity( 1383): [0,com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity,minimalResumeActivityLocked] 05-13 15:56:16.473 I/sysui_multi_action( 1383): [319,268,321,116,322,2583,325,94229,757,761,758,7,759,1,806,com.inmatrix.ZP_Remote,871,com.embarcadero.firemonkey.FMXNativeActivity,904,com.google.android.apps.nexuslauncher,905,0,945,247,1320,12,1321,1] 05-13 15:56:16.475 I/am_activity_launch_time( 1383): [0,177586847,com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity,2583] 05-13 15:56:22.553 I/am_finish_activity( 1383): [0,177586847,9925,com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity,app-request] 05-13 15:56:22.555 I/am_pause_activity( 1383): [0,177586847,com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity,userLeaving=false] 05-13 15:56:23.195 I/am_destroy_activity( 1383): [0,177586847,9925,com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity,finish-imm:activityIdleInternalLocked] 05-13 15:56:24.232 I/am_proc_died( 1383): [0,11738,com.inmatrix.ZP_Remote,900,17] 05-13 16:00:47.559 I/am_create_activity( 1383): [0,236630348,9944,com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity,android.intent.action.MAIN,NULL,NULL,270532608] 05-13 16:00:47.636 I/am_proc_start( 1383): [0,14206,10227,com.inmatrix.ZP_Remote,activity,com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity] 05-13 16:00:47.854 I/am_proc_bound( 1383): [0,14206,com.inmatrix.ZP_Remote] 05-13 16:00:47.865 I/am_restart_activity( 1383): [0,236630348,9944,com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity] 05-13 16:00:47.865 I/am_set_resumed_activity( 1383): [0,com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity,minimalResumeActivityLocked] 05-13 16:00:49.993 I/sysui_multi_action( 1383): [319,336,321,104,322,2446,325,94503,757,761,758,7,759,1,806,com.inmatrix.ZP_Remote,871,com.embarcadero.firemonkey.FMXNativeActivity,904,com.google.android.apps.nexuslauncher,905,0,945,311,1320,12,1321,1] 05-13 16:00:49.994 I/am_activity_launch_time( 1383): [0,236630348,com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity,2446] 05-13 16:00:56.363 I/am_finish_activity( 1383): [0,236630348,9944,com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity,app-request] 05-13 16:00:56.365 I/am_pause_activity( 1383): [0,236630348,com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity,userLeaving=false] 05-13 16:00:56.987 I/am_destroy_activity( 1383): [0,236630348,9944,com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity,finish-imm:activityIdleInternalLocked] 05-13 16:00:58.329 I/am_proc_died( 1383): [0,14206,com.inmatrix.ZP_Remote,900,17]
  15. It seems that Delphi 10.3 generated APKs are not compatible with the NOX emulator running Android 7. The moment I try running the APK, I get a message that the application closed. This happens with every APK I generate (e.g. https://github.com/bLightZP/ElegantCalculator). Trying to debug the issue, it seems that my first line of code is not even executed before the app closes. Any ideas?
  16. I managed to get a logcat of my app not loading in Nox (this also happens with a blank app): I/ActivityManager( 2149): START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity bnds=[930,370][1189,525]} from uid 1000 on display 0 I/ActivityManager( 2149): Start proc 4473:com.inmatrix.ZP_Remote/u0a44 for activity com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity D/houdini ( 4473): [4473] Added shared library /data/app/com.inmatrix.ZP_Remote-1/lib/arm/libZP_Remote.so for ClassLoader by Native Bridge. F/DEBUG ( 4489): pid: 4473, tid: 4473, name: atrix.ZP_Remote >>> com.inmatrix.ZP_Remote <<< W/ActivityManager( 2149): Force finishing activity com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity I/WindowManager( 2149): Failed to capture screenshot of Token{1a08a1d ActivityRecord{48bc2f4 u0 com.inmatrix.ZP_Remote/com.embarcadero.firemonkey.FMXNativeActivity t7 f}} appWin=Window{3b58c89 u0 Starting com.inmatrix.ZP_Remote} drawState=4 I/ActivityManager( 2149): Process com.inmatrix.ZP_Remote (pid 4473) has died W/ActivityManager( 2149): Ignoring remove of inactive process: ProcessRecord{98f6a49 0:com.inmatrix.ZP_Remote/u0a44} I'm not proficient enough to understand the debug out, can anyone shed any light?
  17. I don't think the AppBundle will become mandatory, but I wouldn't put it past google to down-grade your position in search results based on it.
  18. I am trying to upload JSON data and an image as a MultipartFormData and return a JSON string from mars using the following code: var shareData : TMultipartFormData; jsonStr : String; begin shareData := TMultipartFormData.Create; shareData.AddField('json','{"empty":"empty"}'); shareData.AddFile('image',FileName); jsonStr := NetHTTPRequest.Post(urlAPIBase+urlAPIShareImage,shareData).ContentAsString(TEncoding.UTF8); end; How do I setup mars to give me access to the json field and image fields? I looked at the ContentTypes demo, but I wasn't sure if any of the examples actually covered MultipartFormData.
  19. I am trying to create a really simple TCP/IP connection to a server using Indy on Android. All the communication between the client and server is text based. I tried adjusting the code on Remi's answer from this thread to my needs: https://stackoverflow.com/questions/17372366/delphi-indy-tidtcpclient-reading-data However, what happens is that "FConn.IOHandler.ReadLn;" is blocking (at least under Android), so when the App closes and I try to terminate the thread, calling the thread's "WaitFor" method triggers a freeze as the thread never leaves the blocking "ReadLn" and never terminates. Is there a way to instantly stop ReadLn from waiting so the thread could terminate cleanly? Or should I use "FConn.IOHandler.ReadBytes" instead? P.S. I read this thread: https://stackoverflow.com/questions/12507677/terminate-a-thread-and-disconnect-an-indy-client And in it Remy writes that "Disconnecting the client will cause ReadLn() to raise an exception inside the thread.", which is not the case for me under Android (I'm trying to catch the exception and write a log entry when it triggers, but nothing gets written). I also tried wrapping the disconnect method in a "try except" block, but it's not triggering any exception. The code I'm using: procedure TMainForm.CreateTCPIPConnection; var B : Boolean; begin IdTCPClient.Host := AddressEdit.Text; IdTCPClient.Port := StrToIntDef(PortEdit.Text,4769); B := False; Try IdTCPClient.Connect; except on E: Exception do Begin B := True; {$IFDEF TRACEDEBUG}AddDebugEntry('TCP/IP connect exception : '+E.Message);{$ENDIF} End; end; If B = False then Begin If Assigned(ZPReadThread) = False then try ZPReadThread := TReadingThread.Create(IdTCPClient); ZPReadThread.OnData := DataReceived; ZPReadThread.Start; except on E: Exception do Begin IdTCPClient.Disconnect; {$IFDEF TRACEDEBUG}AddDebugEntry('TCP/IP exception creating read thread : '+E.Message);{$ENDIF} End; end; End; end; procedure TReadingThread.Execute; begin {$IFDEF TRACEDEBUG}AddDebugEntry('Read thread created');{$ENDIF} while not Terminated do begin {$IFDEF TRACEDEBUG}AddDebugEntry('Read thread ReadLn (before)');{$ENDIF} Try FData := FClient.IOHandler.ReadLn; Except on E: Exception do Begin {$IFDEF TRACEDEBUG}AddDebugEntry('TCP/IP IOHandler.ReadLn exception : '+E.Message);{$ENDIF} End; End; //FClient.IOHandler.ReadBytes(AData, sizeof(TWaveFormSample), False); {$IFDEF TRACEDEBUG}AddDebugEntry('Read thread ReadLn (after)');{$ENDIF} if (FData <> '') and Assigned(FOnData) then Synchronize(DataReceived); //Sleep(1); end; {$IFDEF TRACEDEBUG}AddDebugEntry('Read thread about to terminate');{$ENDIF} end; procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction); begin If IdTCPClient.Connected = True then Begin try IdTCPClient.Disconnect; except on E: Exception do Begin {$IFDEF TRACEDEBUG}AddDebugEntry('TCP/IP Disconnect exception : '+E.Message);{$ENDIF} End; end; End; if Assigned(ZPReadThread) then Begin {$IFDEF TRACEDEBUG}AddDebugEntry('Terminating Read thread');{$ENDIF} ZPReadThread.Terminate; {$IFDEF TRACEDEBUG}AddDebugEntry('Waiting for read thread termination');{$ENDIF} ZPReadThread.WaitFor; {$IFDEF TRACEDEBUG}AddDebugEntry('Finished waiting for read thread termination');{$ENDIF} FreeAndNil(ZPReadThread); End; end;
  20. Yaron

    Using Indy for cross-platform TCP/IP

    I am writing a remote control App that controls a PC. I am sending commands over TCP/IP each time a user clicks a UI button and at the same time, listening to responses to my commands. Presently, I am getting responses in the background "reading" thread and sending the command in the main thread. After reading your comments I realize my issue is further complicated, as your recommend not calling any TCP/IP function at all in my main thread, which means my Read function can't be blocking at all, otherwise the user will experience input-lag. Is it safe to call "IdTCPClient.IOHandler.WriteLn" in the main thread? If not, what is the best approach to check if there is data waiting without blocking?
  21. When specifying the multiple resolution images in the project's options page, there doesn't seem to be any relations between the device's screen resolution and the resolution of the splash image. For example, on a Note4 device with a screen resolution of 1440x2560, the "470x320" (blurry) splash screen is displayed. Is there a way to influence this selection?
  22. I actually posted this question on stack overflow a while back, got what I thought was a working answer but over time realized that on different devices, waiting for "onIdle" doesn't actually work. Here's the background, my app on first-load does some time-consuming (3-8 sec) pre-calculations so subsequent runs would be much faster. During this processing period, I want to show a "loading %" track-bar. However, for the life of me, I haven't been able to find the exact moment my form is visible and responsive for action. I tried different approaches: 1. waiting for "OnActivate" event. 2. Implementing IFMXApplicationEventService.SetApplicationEventHandler and waiting for "TApplicationEvent.BecameActive". 3. Waiting for "TApplicationEvent.BecameActive" to trigger and then waiting for 3 "OnIdle" events to trigger (2 OnIdle events were not enough for my Galaxy Note 4 device). Only #3 sort of worked on most devices using Delphi 10.2.3, but then when I upgraded to Delphi 10.3.1 even that stopped working (my progress bar shows up but the screen stops updating, so the bar remains on 0% until the pre-calculation function completes, even when calling Application.ProcessMessages after each update and no other code running in the background). Is there a better solution to know the exact moment my app will start responding to screen updates on launch under Android?
  23. I was doing this in v10.2.3 and it was not stable, I chronicled my experiences here: https://stackoverflow.com/questions/52168940/is-png-decoding-not-thread-safe-under-android After replacing TBitmap PNG decoding with JBitmap, the issue was resolved, so I do believe that at least in v10.2.3 TBitmap is not thread safe.
  24. Yaron

    Issue with code-editor toolbars

    I just realized that the "palette" window switches context between new project files or components based on whether you're editing code or the form. 🤯