#1 2016-07-13 12:27:20

Peter Evans
Member
Registered: 2016-07-03
Posts: 32

Windows FMX Client versus Android FMX Client

I have successfully made a Delphi 10.1 Berlin, mORMot Windows Server.
Also a Windows FireMonkey Client can successfully log on and log off my system. This is excellent.

I have one parameter which is an object TMemSettingObj.

It is defined like:-

type
  TMemSettingObj = class
  private
  ...

So far so good.

When I make the Android FireMonkey Client I create the unit mORMotClient using a
server wrapper project.

On Android there are a few problems. For example,

  MemSettingObj := TableMemSettingObj.TMemSettingObj.CreateFromVariant(res[7]);

I get an error :-

  'TMemSettingObj' does not contain a member named 'CreateFromVariant'.

So I defined TMemSettingObj with conditional compilation:-

type
  TMemSettingObj = class
{$IFDEF SERVERWRAPPER}
                        (TSQLRecord)
{$ENDIF}
  private
  ...

The program now compiles under Android.

However when the Server runs I get error:_

TSQLRestRoutingREST.Error: {  "errorCode":406,  "errorText":"(sicShared) execution failed
(probably due to bad input parameters) for LoginAdmin.LoginAdmin"  }

Comparing the Log with the Log used to call from Windows FireMonkey Client the main differences are:

Android gets a prefix of    "ID":0,
  (I understand this as the class now descends from TSQLRecord)

Windows - "MainViewTimelineShow":true
Android - "MainViewTimelineShow":1

Do you have any tips on how I can get it working on both Windows and Android?

Regards,
  Peter Evans

Offline

#2 2016-07-13 16:25:49

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,655
Website

Re: Windows FMX Client versus Android FMX Client

Yes, TSQLRecord has a ID property added to the published properties...
So both client and server side should match, for this to work properly...

Did you try define some records for your SOA parameters?
They should be marshalled as expected by the wrapper generator.
And you could easily add some dynamic arrays of records, if needed, to transmit some lists.

Idea is to define record types as DTO (Data Transfer Object - please check the framework doc), instead of classes.
So on server side, you have to make some quick marshalling to/from DTO records to/from your business classes.

Offline

#3 2016-07-14 00:12:31

Peter Evans
Member
Registered: 2016-07-03
Posts: 32

Re: Windows FMX Client versus Android FMX Client

Thank you. I will investigate further and report back.

Offline

#4 2016-07-18 07:12:18

Peter Evans
Member
Registered: 2016-07-03
Posts: 32

Re: Windows FMX Client versus Android FMX Client

I am running a test program on Android using Delphi FireMonkey.

Note - I have overcome my issue with passing objects as parameters. I now pass
records. I use a server wrapper to generate the unit mORMotClient.

The problem I am having is with these lines :-

var
FProxy : SynCrossPlatformREST.TSQLRestClientURI;

FProxy := mORMotClient.GetClient('999.999.9.99'         {not the correct name} {aServerName},
                                 'User'                 {aUserName},
                                 'synopse'              {aPassword},
                                  211                   {aServerPort},
                                  ROOT_NAME             {aServerRoot}
                                  {aHttps default is False} );


    Int := mORMotClient.TServiceLoginAdmin.Create(FProxy);

    if Assigned(Int) then begin
      if not             Int.LoginAdmin(aCompany,
                                        ...
                                        MemSettingRec     {Returned}) then begin
    ...

This is what gets generated in unit mORMotClient :-

/// service implemented by TServiceLoginAdmin
  // - you can access this service as such:
  // !var aLoginAdmin: ILoginAdmin;
  // !begin
  // !   aLoginAdmin := TLoginAdmin.Create(aClient);
  // !   // now you can use aLoginAdmin methods
  // !...
  ILoginAdmin = interface(IServiceAbstract)
    ['{A1767BC6-0A1A-41D9-AD6A-A4785458F9B8}']
    function LoginAdmin(const Company1: String; ...; var MemSettingRec: TMemSettingRec): Boolean;
  end;

  /// implements ILoginAdmin from http://localhost:888/root/LoginAdmin
  // - this service will run in sicShared mode
  TServiceLoginAdmin = class(TServiceClientAbstract,ILoginAdmin)
  public
    constructor Create(aClient: TSQLRestClientURI); override;
    function LoginAdmin(const Company1: String; ...; var MemSettingRec: TMemSettingRec): Boolean;
  end;

What I do not understand is the comment that you need to code :-
  aLoginAdmin := TLoginAdmin.Create(aClient);

I need to code :-
  mORMotClient.TServiceLoginAdmin.Create(FProxy);

The difference being the word "Service". Is the automatic comment wrong or is it something I am doing that is wrong?

What else might I need to change to get it working?

Regards,
  Peter Evans

Offline

#5 2016-07-18 07:41:26

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,655
Website

Re: Windows FMX Client versus Android FMX Client

Yes, the generated comment is wrong.

I've fixed the template - see http://synopse.info/fossil/info/836c54d0d1

Thanks for the report.

Offline

#6 2016-07-18 12:30:37

Peter Evans
Member
Registered: 2016-07-03
Posts: 32

Re: Windows FMX Client versus Android FMX Client

I'm pleased that the template has been tweaked. But back to my real problem...

My problem is in the line:-
  Int := mORMotClient.TServiceLoginAdmin.Create(FProxy);

I get the error:-  raised exception class EJMIException with message 'java.io.EOFException'.

This is raised in the Delphi unit System.Internal.ExcUtils

The last lines in that unit are :-

{$IFDEF ANDROID}
procedure DoRaiseJNIExceptionCallBack(const JNIExceptionClassName: string; const Msg: string);
begin
  raise EJNIException.CreateWithClassName(JNIExceptionClassName, Msg);
end;
{$ENDIF}

initialization
{$IFDEF ENABLE_SIGNAL_HANDLING}
  ExitProcessProc := PropagateSignals;
{$ENDIF ENABLE_SIGNAL_HANDLING}
{$IFDEF ANDROID}
  Androidapi.Jni.DoRaiseJNIException := DoRaiseJNIExceptionCallBack;
{$ENDIF}
end.

Any clues as to what may be the problem?

Offline

#7 2016-07-19 10:32:26

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,655
Website

Re: Windows FMX Client versus Android FMX Client

EOFException means that the Java layer did reach a "file" end.
Sounds like a problem with the underlying socket library, in which here a "file" is in fact a socket.

Which version of Delphi are you using?
Try to enable Indy as client.

Offline

#8 2016-07-19 22:30:10

Peter Evans
Member
Registered: 2016-07-03
Posts: 32

Re: Windows FMX Client versus Android FMX Client

Thank you for your reply. I am using Delphi 10.1 Berlin.
I will look again at this problem today. Especially the Indy clue you gave.
The Android version (FireMonkey Android client) of my system is the only part not working. (The FireMonkey Windows client works.)

Offline

#9 2016-07-25 10:43:19

Peter Evans
Member
Registered: 2016-07-03
Posts: 32

Re: Windows FMX Client versus Android FMX Client

It has taken me some days to put together a program outlining the problem I am having.
If my program is suitable then it might be considered as a Sample program for mORMot.
I have written it so that it can be added to the mORMot sample programs.

The problem I am having is with the Android Client. I can not get that to work. (What works is the Server, the Windows Client, and the server wrapper.)

(Most of the following is from the ReadMe that comes with the program.)

A sample program to assist people converting from the Delphi framework DataSnap
to the mORMot framework.

This Project Group 'TestMormotGroup1' consists of 4 projects.

1) TestMormotServer.
This server must run before you run one of the clients.

2) TestMormotWin.
Test program for mORMot running on Windows.
It is built in Delphi FireMonkey.

3) TestMormotAnd.
Test program for mORMot running on Android.
It is built in Delphi FireMonkey.

4) TestMormotServerWrapper.
A CLI program that is used to generate the unit 'mORMotClient.pas'.
That unit is used in the project TestMormotAnd.

The program is structured around DataSnap. For example, there is a unit
mORMot_ServerContainer and mORMot_ServerMethods.

If you wish to convert your own DataSnap program to mORMot then you can
follow the pattern of introducing these units in parallel with your
existing program. Then switching over to mORMot.

The program also shows how to keep any existing objects that you use
in DataSnap and make Record versions of them and how to convert from Object
to Record and Record to Object.

You will need to change the IP Address in 2 places :-

1) unit TestMormotWin1
2) unit TestMormotAnd1

You will need to change the Log path in unit 'Unit1.pas'.


The sample is located at
  http://www.cocolsoft.com.au/ba/testmorm … 1_toab.zip

I look forward to feedback on how I can get project TestMormotAnd to work.

Regards,
  Peter Evans

Offline

#10 2016-08-09 00:27:17

Peter Evans
Member
Registered: 2016-07-03
Posts: 32

Re: Windows FMX Client versus Android FMX Client

I have now put together a revised sample project group.
This sample now has a working version of Delphi FireMonkey on Android.

This group also simplifies the way the IP Address is used in the Clients.

Please see the 'ReadMe.txt' for information.

I did have to make one (1) change in mORMotClient to get Android to work.

The change is :-
  Amend in LoginAdmin
    DateTimeToIso8601(ServerTime) -->  0
    (This avoids a problem of date handling)

I do not understand why this code (generated by the Server Wrapper) crashes
with an invalid floating point operation.


The sample is located at
  http://www.cocolsoft.com.au/ba/testmorm … _toab2.zip

Offline

#11 2016-08-14 22:52:38

Peter Evans
Member
Registered: 2016-07-03
Posts: 32

Re: Windows FMX Client versus Android FMX Client

I have now fixed the problem of date handling.

The solution is to change any parameters from TDateTime to String;

The following works for Delphi FireMonkey on Windows and Delphi FireMonkey on Android.
It preserves milliseconds. Breaking this down into simple parts.

At the Server :-

var
  ServerTime    : TDateTime;
  ServerTimeStr : String;

ServerTime    := System.SysUtils.Now;
ServerTimeStr := System.DateUtils.DateToISO8601(ServerTime);

At the Client :-

var
  ServerTime        : TDateTime;
  ThisServerTimeStr : String;

ServerTime := System.DateUtils.ISO8601ToDate(ThisServerTimeStr);

Offline

#12 2016-08-16 16:41:18

BLADEXP
Member
Registered: 2016-06-30
Posts: 3

Re: Windows FMX Client versus Android FMX Client

Boolean values are transmitted to the server:
true = -1
false = 0


function TServiceRemoteSQL.Execute(const aSQL: String; const aExpectResults: Boolean; const aExpanded: Boolean): Variant;
var res: TVariantDynArray;
    a,b:integer;
begin
  if aExpectResults=True then a:=1 else a:=0;
  if aExpanded=True then b:=1 else b:=1;
  fClient.CallRemoteService(self,'Execute',1, // raise EServiceException on error
    [aSQL,a,b],res);
  Result := res[0];
end;

Offline

#13 2016-08-18 23:01:46

Peter Evans
Member
Registered: 2016-07-03
Posts: 32

Re: Windows FMX Client versus Android FMX Client

Hope that the following explanation helps. mORMot correctly deals with both Windows and Android situations.

Assume you have a record with 2 fields:   Boolean1 and Boolean2.

Using FireMonkey Client on Windows:-
  Looking at the Server log. The call may look a bit like:

    {"Boolean1":true,"Boolean2":false}

Using FireMonkey Client on Android:-
  Looking at the Server log. The call may look a bit like:

    {"Boolean1":-1,"Boolean2":0}

Offline

#14 2016-09-24 18:45:32

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,655
Website

Re: Windows FMX Client versus Android FMX Client

Offline

#15 2017-09-08 07:45:31

sunxiamen
Member
Registered: 2017-09-03
Posts: 3

Re: Windows FMX Client versus Android FMX Client

I download the sample and compile under Delphi 10.2, run client on android, it seem the TestMormotAnd runing not so stable, when click button2, it cause hang and waiting...

Offline

#16 2017-09-10 05:33:23

Peter Evans
Member
Registered: 2016-07-03
Posts: 32

Re: Windows FMX Client versus Android FMX Client

When you run the Server please note the IP address.

Look at unit mORMot_Assist.

What is the constant IPAddress? It should be the same.

What is the constant ServerLogBase? Change that to suit your computer.

Run the Windows Client. Ensure that that works.

Ensure you have enabled the server through your firewall.

Before you run the Android Client. Use an app to check that you can
access the IPAddress from the Client device.

Offline

Board footer

Powered by FluxBB