DonSa 4 Posted May 5, 2023 I have a sample code to callback from TWebbrowser, for example: get a selected text on webbrowser... It is OK in Firemonkey Android. But in Firemonkey iOS, there is error at line: "FJavaScriptValueCallback := TJavaScriptValueCallback.Create;" with message: Incompatibe types TJavaScriptValueCallback and TWKScriptMessage. I don't know in iOS, what object evaqulient with class that i ahve decalred in Android: TJavaScriptValueCallback = class(TJavalocal, JValueCallBack) Please give idea! Thanks! This is my code: unit uMain; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects, FMX.TabControl, FMX.WebBrowser, System.IOUtils, FMX.Controls.Presentation, FMX.Edit, FMX.Memo.Types, FMX.ScrollBox, FMX.Memo, FMX.StdCtrls, System.JSON, System.Actions, FMX.ActnList, FMX.ListView.Types, FMX.ListView.Appearances, FMX.ListView.Adapters.Base, FMX.ListView, System.StrUtils, FMX.ListBox, FMX.Layouts, FMX.MultiView, System.RegularExpressions, FMX.Platform, FMX.Clipboard {$IFDEF ANDROID} , Androidapi.JNIBridge, Androidapi.JNI.WebKit, Androidapi.JNI.JavaTypes, FMX.StdActns, FMX.MediaLibrary.Actions, System.ImageList, FMX.ImgList {$ENDIF} {$IFDEF IOS} , iOSapi.WebKit, iOSapi.Foundation, Macapi.Helpers, iOSapi.Helpers, iOSapi.UIKit, System.ImageList, FMX.ImgList, FMX.StdActns, FMX.MediaLibrary.Actions {$ENDIF}; type TJavaScriptResultEvent = procedure(Sender: TObject; const JavaScriptResult: string) of object; {$IFDEF ANDROID} TJavaScriptValueCallback = class(TJavalocal, JValueCallBack) {$ENDIF} {$IFDEF IOS} TJavaScriptValueCallback = class(TWKScriptMessage) {$ENDIF} private FOnResult: TJavaScriptResultEvent; public {$IFDEF ANDROID} { JValueCallback } procedure onReceiveValue(value:JObject); cdecl; {$ENDIF} {$IFDEF IOS} { TWKScriptMessage } procedure onReceiveValue(controller: WKUserContentController; message: WKScriptMessage); {$ENDIF} property OnResult: TJavaScriptResultEvent read FOnResult write FOnResult; end; TfrmMain = class(TForm) private { Private declarations } FJavaScriptValueCallback: TJavaScriptValueCallback; public { Public declarations } constructor Create(AOwner: TComponent); override; destructor Destroy; override; end; var frmMain: TfrmMain; implementation {$R *.fmx} { TJavaScriptValueCallback } {$IFDEF ANDROID} procedure TJavaScriptValueCallback.onReceiveValue(value: JObject); begin if Assigned(FOnResult) then FOnResult(Self, JStringToString(TJString.Wrap(value)).DeQuotedString('"')); end; {$ENDIF} {$IFDEF IOS} procedure TJavaScriptValueCallback.onReceiveValue(controller: WKUserContentController; message: WKScriptMessage); var MessageText: string; begin if Assigned(FOnResult) then begin if Assigned(message.body) then begin MessageText := NSStrToStr(TNSString.Wrap(message.body)); FOnResult(Self, MessageText); end; end; end; constructor TfrmMain.Create(AOwner: TComponent); begin inherited; FJavaScriptValueCallback := TJavaScriptValueCallback.Create; end; destructor TfrmMain.Destroy; begin FJavaScriptValueCallback.Free; inherited; end; {$ENDIF} end. Share this post Link to post
Rollo62 536 Posted May 5, 2023 (edited) TL;DR; There was a scripting solution from freeonterninate: ScriptGate https://bitbucket.org/freeonterminate/scriptgate/src/master/ I don't use this currently and this is quite old, so I would bet it's not working anymore with current TWebBrowser. Maybe it will be helpful anyway, and you might get this working (again ?). Would be great to get some feedback on the status of this project. Edited May 5, 2023 by Rollo62 1 Share this post Link to post
Dave Nottage 557 Posted May 5, 2023 10 hours ago, DonSa said: But in Firemonkey iOS, there is error at line: "FJavaScriptValueCallback := TJavaScriptValueCallback.Create;" with message: Incompatibe types TJavaScriptValueCallback and TWKScriptMessage As per the documentation, you do not create an instance of WKScriptMessage, and in any event, you cannot descend from TWKScriptMessage anyway. Also as per the documentation it is used when you implement custom Javascript message handlers. What you could do is use the evaluateJavaScript method of WKWebView and pass to it a completion handler, which could be declared on your main form like this: procedure JavaScriptCompletionHandler(obj: Pointer; error: NSError); ..and implement it like this: procedure TfrmMain.JavaScriptCompletionHandler(obj: Pointer; error: NSError); var LJavaScriptResult: string; LCode: Integer; begin if obj <> nil then LJavaScriptResult := NSStrToStr(TNSString.Wrap(obj)) else LJavaScriptResult := 'null'; if error = nil then LCode := 0 else LCode := error.code; // Do something with LJavaScriptResult and LCode, here end; Call evaluateJavascript like this: LWebView.evaluateJavaScript(StrToNSStr(AJavaScript), JavaScriptCompletionHandler) Where LWebView is a reference to the WKWebView in the iOS implementation of TWebBrowser 1 Share this post Link to post
Rollo62 536 Posted May 8, 2023 Perhaps these notes from Dave were useful here as well: https://en.delphipraxis.net/topic/8065-how-can-i-handle-the-javascript-result/?tab=comments#comment-68093 2 Share this post Link to post
DonSa 4 Posted May 9, 2023 thank Dave Nottage and Rollo62. It was ok for both iOS and Android 2 Share this post Link to post