Lazarus

Programming => Operating Systems => Android => Topic started by: Robert Gilland on June 14, 2019, 04:27:36 am

Title: LAMW and TThread
Post by: Robert Gilland on June 14, 2019, 04:27:36 am
The below code crashes my app, id dies when it calls the line "inherited Create(TRUE)", any Ideas?

Code: Pascal  [Select]
  1. type
  2.   TTestThread = class(TThread)
  3.      procedure Execute;  override;
  4.      constructor Create;
  5.    end;
  6.  
  7.  constructor TTestThread.Create;
  8. begin
  9.   inherited Create(TRUE);
  10.   FreeOnTerminate := TRUE;
  11. end;
  12.  
  13. procedure TTestThread.Execute;
  14. begin
  15.  
  16. end;
  17.  
  18. procedure TAndroidModule2.TestThreading;
  19. begin
  20.   TTestThread.Create;
  21. end;
  22.  
Title: Re: LAMW and TThread
Post by: SymbolicFrank on June 14, 2019, 08:07:30 am
Do you call the Create of the instance, instead of the type?
Title: Re: LAMW and TThread
Post by: PascalDragon on June 14, 2019, 09:06:14 am
Does your main project file have the cthreads unit in its usage clause? This unit is required on *nix systems which Android is one of. The Lazarus templates usually have the unit protected by a {$ifdef unix}{$ifdef usecthreads}cthreads{$endif}{$endif} or so, so you need to define the usecthreads define in that case (or remove the ifdef altogether).
Title: Re: LAMW and TThread
Post by: Robert Gilland on June 16, 2019, 01:50:54 am
Thank you PascalDragon, "cThreads" did stop the app crash.

However now I can't get the OnTerminate event to be called see below code.

When run the jProgressDialog does not close.

Any Ideas?

Code: Pascal  [Select]
  1. type
  2.   TTestThread = class(TThread)
  3.      procedure Execute;  override;
  4.      constructor Create( pOnTerminateEvent : TNotifyEvent);
  5.    end;
  6.    
  7.   TAndroidModule1 = class(jForm)  
  8.      dlgTestProgress: jDialogProgress;  
  9.      thrdSendOffLine : TTestThread;      
  10.   end;  
  11.    
  12.  
  13. procedure TAndroidModule1.TestTerminated(Sender: TObject);
  14. begin
  15.   dlgTestProgress.Close;
  16. end;
  17.  
  18. constructor TTestThread.Create( pOnTerminateEvent : TNotifyEvent);
  19. begin
  20.  inherited Create(TRUE);
  21.  OnTerminate := pOnTerminateEvent;
  22.  FreeOnTerminate := TRUE;
  23. end;
  24.  
  25.  
  26. procedure TTestThread.Execute;
  27. begin
  28.  
  29. end;
  30.  
  31. procedure TAndroidModule1.RunThreadTest;
  32. begin
  33.   dlgTestProgress.Show();
  34.   thrdSendOffLine  := TTestThread.Create(TestTerminated);
  35.   thrdSendOffLine.Start;
  36. end;  
  37.  
  38.  
Title: Re: LAMW and TThread
Post by: PascalDragon on June 22, 2019, 05:53:14 pm
It could be that the main thread is not calling CheckSynchronize as OnTerminate is called using Synchronize. I don't have enough experience with Android modules in FPC, so I don't know whether there is supposed to be component that's indeed calling that function or not.
Title: Re: LAMW and TThread
Post by: engkin on June 22, 2019, 07:24:21 pm
IIRC, your code in LAMW resides in a library (.so). Probably the best option for you to get TThread to work as you expect is to fake a main thread like in this case (https://forum.lazarus.freepascal.org/index.php?topic=44522.0).
Title: Re: LAMW and TThread
Post by: Robert Gilland on June 24, 2019, 05:38:47 am
I have looked at https://forum.lazarus.freepascal.org/index.php/topic,44522.0.html.

This looks rather not usable inside the LAMW framework, unless I am mistaken.
LAMW creates a libcontrols.so library, then does a lot of packaging to make an Androd App.

I will keep looking though

Title: Re: LAMW and TThread
Post by: jmpessoa on June 24, 2019, 06:13:09 am

Quote
This looks rather not usable inside the LAMW framework, unless I am mistaken....

I think you could give it a try ... LAMW lib/.so  is a "TCustomApplication",  too...

What is going to be precessed in the TThread?
Title: Re: LAMW and TThread
Post by: Robert Gilland on June 24, 2019, 06:49:13 am
The application simply makes web service calls in response to the users interactions, some of these web service calls may take some time. I want a thread to process the web service call. allowing the main app to show a progress dialog until the web service API returns. This is proving far more difficult than I hoped for. I still have not worked out how the packaging of the app works, so I don't know how to add a separate library beside as this solution states can be done.
Title: Re: LAMW and TThread
Post by: Robert Gilland on June 24, 2019, 06:54:32 am
I am wondering if there could not be a "jThread" component to make threads inside LAMW applications?
Title: Re: LAMW and TThread
Post by: jmpessoa on June 24, 2019, 06:58:06 am
Quote
so I don't know how to add a separate library beside as this solution states can be done....

Put your custom ".so"  [can be a simple raw ".so" ] in the same folder as  "libcontrols.so" .... 
LAMW will takes care of your library automatically...


Quote
I am wondering if there could not be a "jThread" component to make threads inside LAMW applications?

jHttpClient component has some "async" methods.....  what you need?
Title: Re: LAMW and TThread
Post by: Robert Gilland on June 24, 2019, 07:13:12 am
will give AppAsyncTaskDemo1 a try it does look promising
Title: Re: LAMW and TThread
Post by: Robert Gilland on June 24, 2019, 07:56:08 am
If I could make a "WST" ( web services toolkit ) transport based on jHttpClient async methods , then we just might have a viable solution.
Title: Re: LAMW and TThread
Post by: Robert Gilland on June 24, 2019, 08:59:49 am
We have a winner "jAsyncTask"can handle the requirement
Title: Re: LAMW and TThread
Post by: jmpessoa on June 24, 2019, 07:40:48 pm
Quote
We have a winner "jAsyncTask"can handle the requirement

Nice!

What about a simple demo  jAsyncTask +  WST?

You can help all LAMW/Lazarus/FreePascal  community!!!
Title: Re: LAMW and TThread
Post by: Robert Gilland on June 25, 2019, 08:53:11 am
here is the core code:

Code: Pascal  [Select]
  1. {Hint: save all files to location: C:\adt32\eclipse\workspace\asyncdemo\jni }
  2. unit unit1;
  3.  
  4. {$mode delphi}
  5.  
  6. interface
  7.  
  8. uses
  9.   Classes, SysUtils, Laz_And_Controls, AndroidWidget, user_service_intf,
  10.   user_service_intf_proxy, And_Log_h;
  11.  
  12. type
  13.  
  14.   { TAndroidModule1 }
  15.  
  16.   TAndroidModule1 = class(jForm)
  17.       jAsyncTask1: jAsyncTask;
  18.       jButton1: jButton;
  19.       jDialogProgress1: jDialogProgress;
  20.       jEditText1: jEditText;
  21.       jListView1: jListView;
  22.       procedure AndroidModule1Create(Sender: TObject);
  23.       procedure AndroidModule1Destroy(Sender: TObject);
  24.       procedure jAsyncTask1DoInBackground(Sender: TObject; progress: Integer;
  25.         out keepInBackground: boolean);
  26.       procedure jAsyncTask1PostExecute(Sender: TObject; progress: integer);
  27.       procedure jAsyncTask1PreExecute(Sender: TObject; out
  28.         startProgress: integer);
  29.       procedure jButton1Click(Sender: TObject);
  30.     private
  31.       {private declarations}
  32.       procedure LogMessage( psMsg : String );
  33.       procedure   RunGetUsers;
  34.       function CreateUserProxy : UserService;
  35.     public
  36.       {public declarations}
  37.       slUsers : TStringList;
  38.   end;
  39.  
  40. var
  41.   AndroidModule1: TAndroidModule1;
  42.  
  43. implementation
  44.  
  45. {$R *.lfm}
  46.  
  47. uses soap_formatter, json_formatter, xmlrpc_formatter, fpc_http_protocol, service_intf;
  48.  
  49. { TAndroidModule1 }
  50.  
  51.  
  52. procedure TAndroidModule1.jAsyncTask1DoInBackground(Sender: TObject; progress: Integer; out keepInBackground: boolean);
  53. begin
  54.   RunGetUsers;
  55.   keepInBackground:= False;
  56. end;
  57.  
  58. procedure TAndroidModule1.AndroidModule1Create(Sender: TObject);
  59. begin
  60.   slUsers := tStringList.Create;
  61. end;
  62.  
  63. procedure TAndroidModule1.AndroidModule1Destroy(Sender: TObject);
  64. begin
  65.   slUsers.Free;
  66. end;
  67.  
  68. procedure TAndroidModule1.jAsyncTask1PostExecute(Sender: TObject; progress: integer);
  69. begin
  70.   LogMessage('Dialog Stop');
  71.   jDialogProgress1.Stop;
  72.   LogMessage('Async Stop');
  73.   jAsyncTask1.Done;
  74.   LogMessage('List View Assign');
  75.   jListView1.Items.Assign(slUsers);
  76.   ShowMessage(slUsers.text);
  77. end;
  78.  
  79. procedure TAndroidModule1.jAsyncTask1PreExecute(Sender: TObject; out startProgress: integer);
  80. begin
  81.    startProgress:= 0;  //out param !
  82.    LogMessage('Dialog Start');
  83.    jDialogProgress1.Start; //or Show
  84. end;
  85.  
  86.  
  87.  
  88.  
  89. procedure TAndroidModule1.jButton1Click(Sender: TObject);
  90. begin
  91.  
  92.    if not jAsyncTask1.Running then
  93.    begin
  94.      //ShowMessage('Execute ... ');
  95.      jAsyncTask1.Execute
  96.    end
  97.   else
  98.      ShowMessage('Running...');
  99. end;
  100.  
  101. procedure TAndroidModule1.LogMessage(psMsg: String);
  102. begin
  103.   __android_log_write(ANDROID_LOG_INFO,PChar(Text),PChar(psMsg));
  104. end;
  105.  
  106. procedure TAndroidModule1.RunGetUsers;
  107. var
  108.   lpUserService : UserService;
  109.   loUserArray   : TUserArray;
  110.   loUser        : TUser;
  111.   i             : Integer;
  112.  
  113. begin
  114.   LogMessage('Create proxy');
  115.   lpUserService := CreateUserProxy;
  116.   LogMessage('proxy Get List');
  117.   loUserArray   := lpUserService.GetList();
  118.   slUsers.Clear;
  119.   LogMessage('List Length ' + IntToStr(loUserArray.Length));
  120.   for i := 0 to loUserArray.Length-1 do
  121.     begin
  122.       loUser := loUserArray[i];
  123.       slUsers.Add( loUser.UserName );
  124.     end;
  125. end;
  126.  
  127. function TAndroidModule1.CreateUserProxy: UserService;
  128. var
  129.   buffsimplecall, buffTransport, buffFormat : string;
  130.  
  131.   function GetServiceURL( WebServiceAddress : String ):String;
  132.   begin
  133.     Result := WebServiceAddress   + '/services/UserService';
  134.   end;
  135.  
  136. begin
  137.   buffFormat     := 'json';
  138.   buffsimplecall := 'http:Address=' + GetServiceURL(jEditText1.Text) + '/?format=' + buffFormat;
  139.   buffTransport  := buffsimplecall;
  140.   buffFormat := buffFormat + ':';
  141.   LogMessage(buffTransport);
  142.   LogMessage(buffFormat);
  143.   Result     := TUserService_Proxy.Create( 'UserService',  buffFormat,  buffTransport  );
  144. end;
  145.  
  146.  
  147. end.
  148.