Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
TIdTCPClient on Android: Can't catch Exception Popup - Socket Error #107
#1
In our Application we offer connect to our server by in 2 ways - by URL (when we are in LTE network) or direct by IP (when we are in same WLAN network as the server).

The app tried to connect the URL first, an when not available (EIdSocketError occours) then we try to connect by direct IP address. On IOS this is working perfect.

On Android, the Indy 10 pop up with a Message Box 'Socket Error 107' when we try to connect to an URL which is not available yet.

We are not able to catch the exception in our code, so our app is not able to handle this.

How can we get the Socket Error 107 instead a popup to the user ??

Here are the relevant code segments. Thanks in advance.

Code:
private
  { Private declarations }
  FClient: TIdTCPClient;

// -----------------------------------------------------------------------------
// Erzeugen
constructor TAppComThread.Create(OnMsgEvent: TComEvent);
begin
  FClient := TIdTCPClient.Create(nil);
  FClient.OnStatus := OnStatus;
  FClient.OnConnected := OnConnected;

  FClient.ConnectTimeout  := c_TcpConnectTimeout;
  FClient.ReadTimeout    := c_TcpReadTimeout;

end;

//------------------------------------------------------------------------------
//  Ausführen
procedure TAppComThread.Execute;
var

begin

  while not Terminated do
  begin

    Sleep(10);

    // Connect now
    if bConnectFlag then
    begin
      bConnectFlag := false;
      Try
        FClient.Port := c_TcpPortPersonen;
        FClient.Connect;
      Except
        On E: EIdSocketError Do
        begin
          bConnectionFailed := true;
          ReplyMessage('167: No Socket at '+ FClient.Host);
        end;

        On E: Exception Do
        begin
          bConnectionFailed := true;
          ReplyMessage('172: No Connection to '+ FClient.Host);
        end;
      End;
    end;
  end;
end;
Reply
#2
(06-18-2020, 09:25 AM)Peter_WB Wrote: On Android, the Indy 10 pop up with a Message Box 'Socket Error 107' when we try to connect to an URL which is not available yet.

Indy does not display message boxes, it just raises exceptions. Either YOU, the RTL, or the OS itself, is the one displaying message boxes, usually on uncaught exceptions only.

(06-18-2020, 09:25 AM)Peter_WB Wrote: We are not able to catch the exception in our code, so our app is not able to handle this.

I see nothing in the code you have shown that would prevent exceptions from being caught.

On the other hand, Embarcadero's exception handling on Android is severely broken in C++Builder, so it is not outside the realm of possibility that there is also something broken in Delphi, too. Assuming you are using Delphi, and not FreePascal. What version of Delphi/FPC are you actually using?

Either way, whatever is going on has to be happening outside of Indy. You are just going to have to debug the code to see how the exception is actually handled and how it leads to a message box.

Also, note that EIdSocketError is not the only kind of exception that TIdTCPClient.Connect() can raise. It may raise EIdConnectException, which is not derived from EIdSocketError. But your generic Exception handler should catch that.

Reply
#3
Thank you for the fast answer.
The App is Build by Delphi in Rad Studio Rio 10.3.3.

While debugging the code, I found out that at first the exception On E: EIdSocketError Do is called as expected and the instructions there are operated.
Afterwards, the Socket Error 107 is operated.

When i stop the program by breakpoint in the exception handling, the Socket Error 107 is poping up, when I continue the program.

I tried to freeAndNil the TIdTCPClient as first on exception, but the Socket Error 107 still is poping up.

But I'm able to know about an failed connection and I'm able to give a notice to the user. But I was not able to suppress the socket error message.

This must be an exeption of internal network layers, i don't know how to catch this exception in my application.

The issue is only at Android 32 Bit and 64 Bit using Andriod SDK 25.2.5, IOS ist working well.
Reply
#4
I found a work arround today, but unsure if this is a good practice:

The IdTCPClient.Connect was done inside a TThread to prevent delays in the main task.
For android only I run the Connect instruction in Synchronized(FClient.Connect).

Since that, the Socket Error 107 is disapperared, only the EIdSocketError is called.

Are there options to update the Indy code that the connect is operable even when called from a thread ?
Reply
#5
(06-19-2020, 03:36 PM)Peter_WB Wrote: The IdTCPClient.Connect was done inside a TThread to prevent delays in the main task.
For android only I run the Connect instruction in Synchronized(FClient.Connect).

That is a really bad idea.

TThread.Synchronize() calls the specified procedure in the main UI thread. TIdTCPClient.Connect() is a synchronous method that blocks the thread that calls it. So, you would be blocking your app's main UI thread, and iOS and Android are not very forgiving of that. If your app blocks the main UI thread for a noticeable duration, those OSes are very likely to just outright kill your app process immediately. So don't EVER block the main UI thread on a mobile platform. Doing that is not a good idea even on desktop platforms either, but at least those OSes are more forgiving of slow UIs. But users are not.

Not to mention, Android does not allow network operations in the main UI thread anyway. It will raise a NetworkOnMainThreadException Java error if you try. The only reason you are not getting that error in this situation is because TIdTCPClient.Connect() internally uses its own worker thread to establish the TCP connection when the TIdTCPClient.ConnectTimeout property is set to a non-infinite value, or the TIdAntiFreeze component is being used. TIdTCPClient.Connect() may be updated in the future to get rid of that internal worker thread, thus the TCP connection would be established in the same thread that calls TIdTCPClient.Connect(), which will then lead to the NetworkOnMainThreadException error on Android if called in the main UI thread.

So, just don't use Synchronized(FClient.Connect) at all, it is not worth the risks.

(06-19-2020, 03:36 PM)Peter_WB Wrote: Since that, the Socket Error 107 is disapperared, only the EIdSocketError is called.

Then the problem is not related to Indy at all. You have now proved that, when your debugging saw the EIdSocketError exception raised by TIdTCPClient.Connect() being caught in your except block. So, the popup message is a completely different issue that is unrelated to TIdTCPClient.Connect() itself. Either there is a flaw in how Delphi's RTL handles exceptions in worker threads on Android, or the popup is occurring inside of your own ReplyMessage() which you are calling inside of your except block (I'm leaning towards the latter).

(06-19-2020, 03:36 PM)Peter_WB Wrote: Are there options to update the Indy code that the connect is operable even when called from a thread ?

TIdTCPClient.Connect() itself already works fine in a worker thread. Your debugging has proved that. Something else is going on, and you will have to debug further to find out what exactly. If the popup is not occurring inside of ReplyMessage(), then it has to be inside the RTL itself, in which case you will have to debug into that source code to find it, and then report the culprit to Embarcadero.

Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)