目录
delphi FMX.WebBrowser与H5交互JavaScript
一、原理
1.1、前提条件(主要是针对MSWindows下对D10.4以下的TWebBrowser的支持,不过D10.4已解决了这个前提)
1.2、Delphi FMX.WebBrowser.pas
1.2.1、直接放个TWebBrowser可视化控件来交互FMX界面
1.2.2、动态产生客制化的TCustomWebBrowser非可视化控件来交互FMX界面
1.2.3、以FMX服务的方式IFMXWBService来交互FMX界面
1.3、综上所述:
二、应用
2.1、腾讯开源H5图形图形处理库AlloyImage
2.2、。。。。。(2021-01-11)写累了,明儿继续
你所选用的JS库或JS代码本身是很好的兼容IE10及其以上
国内大厂和国外优质站点,一般在写Web代码时,都考虑了IE的兼容性问题。国内小厂,大多数的做得不好只考虑省事、少写了很多代码,引以为戒,你在发布自己的API时,一定要考虑浏览器内核的兼容性,不要学习国内这些小厂。
以下三种方式,一个目的,都是为了拿到接口ICustomBrowser :
LWebBrowser :TWebBrowser;
LWebBrowser :TCustomWebBrowser;
LWebBrowser.Create(AOwner: TComponent);
1.2.3.1、这是FMX.WebBrowser.Android、FMX.WebBrowser.Cocoa及FMX.WebBrowser.Win分别为Android、IOS、MSWINDOWS下完美拿到TWebBrowser接口ICustomBrowser最好的方法
1.2.3.2、然后ICustomBrowser执行JS
ICustomBrowser. EvaluateJavaScript(const JavaScript: string); //:执行JS,但不回调执行的结果
1.2.3.4、ICustomBrowser执行JS并回调:
1.2.3.4.1、Android
在Android 4.4之后,WebView提供了一个新的2个执行JS的接口:
$(BDS)\source\rtl\android\
unit Androidapi.JNI.Webkit;
[JavaSignature('android/webkit/WebView')]
JWebView = interface(JAbsoluteLayout)
['{0001776D-86A0-43B3-A64C-C6FEA095AD91}']
procedure addJavascriptInterface(object_: JObject; name: JString); cdecl;
procedure evaluateJavascript(script: JString; resultCallback: JValueCallback); cdecl;
//...................以下为delphi FMX通过TAndroidWebBrowserService调用ICustomBrowser.EvaluateJavaScript(const JavaScript: string)的Android实现的内部方法:
//procedure loadUrl(url: JString; additionalHttpHeaders: JMap); cdecl; overload;
procedure loadUrl(url: JString); cdecl; overload;
//...................
《=========拿到JValueCallback :
$(BDS)\source\rtl\android\
unit Androidapi.JNI.Webkit;
JValueCallbackClass = interface(IJavaClass)
['{5CE4D0B0-6C4F-43BD-B57F-A06401A5FB2F}']
end;
[JavaSignature('android/webkit/ValueCallback')]
JValueCallback = interface(IJavaInstance)
['{3B24779A-3678-4AD8-B421-A8A9C6F3E742}']
procedure onReceiveValue(value: JObject); cdecl;
end;
TJValueCallback = class(TJavaGenericImport) end;
《=========拿到JWebView :
$(BDS)\source\rtl\android\
unit Androidapi.JNI.Webkit;
JWebViewClass = interface(JAbsoluteLayoutClass)
['{57C30F7F-F8C7-4C19-859E-073DC4DA4250}']
{class} function _GetRENDERER_PRIORITY_BOUND: Integer; cdecl;
{class} function _GetRENDERER_PRIORITY_IMPORTANT: Integer; cdecl;
{class} function _GetRENDERER_PRIORITY_WAIVED: Integer; cdecl;
{class} function _GetSCHEME_GEO: JString; cdecl;
{class} function _GetSCHEME_MAILTO: JString; cdecl;
{class} function _GetSCHEME_TEL: JString; cdecl;
{class} function init(context: JContext): JWebView; cdecl; overload;
//.............
$(BDS)\source\rtl\android\
unit Androidapi.JNI.Embarcadero;
JWebBrowserClass = interface(JWebViewClass)
['{C9D39057-C2B7-4264-8E58-52DE4CA5AE56}']
{class} function init(context: JContext): JWebBrowser; cdecl;
end;
[JavaSignature('com/embarcadero/firemonkey/webbrowser/WebBrowser')]
JWebBrowser = interface(JWebView)
['{21876269-EEA5-4130-BE15-F23BEB8ECA69}']
procedure SetWebViewListener(listener: JOnWebViewListener); cdecl;
end;
TJWebBrowser = class(TJavaGenericImport) end;
JWebClientClass = interface(JWebViewClientClass)
['{424BCB34-24B0-4A4B-830B-D396C3667344}']
{class} function init: JWebClient; cdecl;
end;
最新的D10.4对应的Android SDK,Delphi为我们实现的API接口的基础知识:
delphi的类及其接口 和JAVA的类及其接口
delphi导入java类的方法:
方法一、原生方法导入:
//这是1个用于较易声明Java的泛型对象工厂的通用类。在这个模型中,我们划分为两个接口:类方法接口(第1个参数)和实例方法接口(第2个参数)。这个类将此2个接口融合到该工厂类中,可以产生Java的实例对象,或提供代表单线程实例的Java类的参照:
$(BDS)\source\rtl\android\
unit Androidapi.JNIBridge;
/// A generic class that we use to make the declaration of Java
/// object factories easier. In our model, we split the class methods
/// and instance methods into two interfaces. This class blends the
/// two interfaces into one factory that can produce instances of Java
/// objects, or provide a reference to a singleton instance representing
/// the Java class.
//这是1个用于较易声明Java的泛型对象工厂的通用类。在它的模型中,我们将参数划分为两个接口:类方法接口(第1个参数)和实例方法接口(第2个参数)。这个类将此2个接口融合到该工厂类中,可以产生Java的实例对象,或提供代表单线程实例的Java类的参照:
TJavaGenericImport = class
方法二、用EMB的代理接口导入DefaultProxyInterfaceName = 'com/embarcadero/rtl/ProxyInterface'; :
$(BDS)\source\rtl\android\
unit Androidapi.JNIBridge;
TJInterfacedObject = class(TInterfacedObject)
procedure AfterConstruction; override;
procedure BeforeDestruction; override;
end;
TJavaLocal = class abstract (TJInterfacedObject, ILocalObject, IJava)
const
DefaultProxyInterfaceName = 'com/embarcadero/rtl/ProxyInterface';
----------->通过以上原理和方法,Delphi第三方生态ScriptGate(是一个实现Delphi和JavaScript相互调用的库,10.4以下使用,D10.4.1请不要再使用有问题)已经为我们做好了封装,可直接拿来用(https://bitbucket.org/freeonterminate/scriptgate/src/master/)。
//............................现在使用 ScriptGate 可轻易解决这个问题,ScriptGate 支持 Windows, macOS, Android, iOS,非常好用,强烈推荐。
//............................(详述:略),自己下载后看。SGWebClient.jar:Android下高勇老师直接引用了这个封装。调用方法示例:http://bbs.2ccc.com/topic.asp?topicid=544553
----------->通过以上原理和方法,(修改:爱吃猪头肉 & Flying Wang 2015-07-21)已经为我们修改好了补丁单元Delphi10.4Update0_FixedDelphiPas\FMX.WebBrowser.pas,
(1)、新增 跨平台属性 GetRealWebBrowserObject 获取各个平台下 原生的 浏览器对象:
// 下面是 GetRealWebBrowserObject 在安卓下的 例子
// (WebBrowser1.GetRealWebBrowserObject as JWebBrowser).getSettings.setUserAgentString(StringToJString('你的UserAgent'));
:注意:《WebView在使用setUserAgentString时的坑》https://blog.csdn.net/mahongy/article/details/103856643
:您若尝试确认正确后,请这样使用:
uses Androidapi.JNI.Webkit;
var LJWebSettings :JWebSettings ;
begin
LJWebSettings := (WebBrowser1.GetRealWebBrowserObject as JWebBrowser).getSettings ;
LJWebSettings.setUserAgentString (LJWebSettings.getUserAgentString);
//LJWebSettings.setUserAgentString(StringToJString('ua'+'你的UserAgent的字符串'));
end;
user-agent,可以用getUserAgentString()方法获取,在手机上打印出来的结果是:
Mozilla/5.0 (Linux; Android 8.1.0; NX606J Build/OPM1.171019.026; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.98 Mobile Safari/537.36
(2)、新增 重定向 Redirection 功能:
// 重定向 Redirection 功能 完全来自 [重庆]新手(371889755)
// IOS MAC 安卓的 重定向 全靠 [龟山]阿卍(1467948783) 帮忙测试:
// 请设置好 RedirectionKey,千万不要用 URL 上的一些关键字,也不要用特殊字符:
// 用 wwwwww 做关键字,比较好。
// 测试用 wwwwww.xxx.com
// 你发送的 url 中,千万也不要有 http: ftp: file: 等在 mac osx 系统上,带有这些,会导致打开网页。
可直接拿来用:
(* ****************************************************** *)
(* *)
(* 修改:爱吃猪头肉 & Flying Wang 2015-07-21 *)
(* 上面的版权声明请不要移除。 *)
(* *)
(* 禁止发布到城通网盘。 *)
(* *)
(* 仅支持 RAD10.4.0(10.4 Release 0),其他版本请自行修改 *)
(* *)
(* ****************************************************** *)
{ IFMXWebBrowserService }
ICustomBrowser = interface(IInterface)
['{A5BB2E8C-6D53-4FF3-BC38-2299285F07BD}']
// ...........................
// procedure EvaluateJavaScript(const JavaScript: string);
//Fix By Flying Wang and 爱吃猪头肉:
procedure EvaluateJavaScript(const JavaScript: string;
DidEvaluateJavaScript: TWebBrowserDidEvaluateJavaScript = nil);
//Fix or Add By 爱吃猪头肉:
function GetRealWebBrowserObject: IUnknown;
//Fix 重定向关键字,如果包含这个关键字 页面不刷新:
//解析 重定向字符串:
function GetRedirectionKey: string;
procedure SetRedirectionKey(const Value:string);
property RedirectionKey: string read GetRedirectionKey write SetRedirectionKey;
// ...........................
procedure LoadFromStrings(const Content: string; const BaseUrl: string);
// ...........................
1.2.3.4.2、、IOS
----------->通过以上原理和方法,(修改:爱吃猪头肉 & Flying Wang 2015-07-21)已经为我们修改好了补丁单元:Delphi10.4Update0_FixedDelphiPas\FMX.WebBrowser.pas,
FMX.WebBrowser.Cocoa.pas
===========》TCommonWebBrowserService===========》继承后将protected的可见性发布出来使用,即可:
(* ****************************************************** *)
(* *)
(* 修改:爱吃猪头肉 & Flying Wang 2015-07-21 *)
(* 上面的版权声明请不要移除。 *)
(* *)
(* 禁止发布到城通网盘。 *)
(* *)
(* 仅支持 RAD10.4.0(10.4 Release 0),其他版本请自行修改 *)
(* *)
(* ****************************************************** *)
{ TCommonWebBrowserService }
TCommonWebBrowserService = class(TInterfacedObject, ICustomBrowser)
//Fix 重定向关键字
private
FRedirectionKey: string;
private
//...................................
protected
//...................................
procedure LoadFromStrings(const Content: string; const BaseUrl: string);
// procedure EvaluateJavaScript(const JavaScript: string);
//Fix By Flying Wang and 爱吃猪头肉
procedure EvaluateJavaScript(const JavaScript: string;
DidEvaluateJavaScript: TWebBrowserDidEvaluateJavaScript = nil);
//Fix or Add By 爱吃猪头肉
function GetRealWebBrowserObject: IUnknown;
//Fix 重定向关键字,如果包含这个关键字 页面不刷新
//解析 重定向字符串
function GetRedirectionKey: string;
procedure SetRedirectionKey(const Value:string);
//...................................
1.2.3.4.3、Linux
----------->通过以上原理和方法,(修改:爱吃猪头肉 & Flying Wang 2015-07-21)已经为我们修改好了补丁单元Delphi10.4Update0_FixedDelphiPas\FMX.WebBrowser.pas,
(1)、新增 跨平台属性 GetRealWebBrowserObject 获取各个平台下 原生的 浏览器对象:
// 下面是 GetRealWebBrowserObject 在安卓下的 例子
// (WebBrowser1.GetRealWebBrowserObject as JWebBrowser).getSettings.setUserAgentString(StringToJString('你的UserAgent'));
(2)、新增 重定向 Redirection 功能:
// 重定向 Redirection 功能 完全来自 [重庆]新手(371889755)
// IOS MAC 安卓的 重定向 全靠 [龟山]阿卍(1467948783) 帮忙测试:
// 请设置好 RedirectionKey,千万不要用 URL 上的一些关键字,也不要用特殊字符:
// 用 wwwwww 做关键字,比较好。
// 测试用 wwwwww.xxx.com
// 你发送的 url 中,千万也不要有 http: ftp: file: 等在 mac osx 系统上,带有这些,会导致打开网页。
可直接拿来用:
{ TLinuxWebBrowserService }
TLinuxWebBrowserService = class(TInterfacedObject, ICustomBrowser)
//Fix 重定向关键字
private
FRedirectionKey: string;
//...............................
// procedure EvaluateJavaScript(const JavaScript: string);
//Fix By Flying Wang and 爱吃猪头肉
procedure EvaluateJavaScript(const JavaScript: string;
DidEvaluateJavaScript: TWebBrowserDidEvaluateJavaScript = nil);
//Fix or Add By 爱吃猪头肉
function GetRealWebBrowserObject: IUnknown;
//Fix 重定向关键字,如果包含这个关键字 页面不刷新
//解析 重定向字符串
function GetRedirectionKey: string;
procedure SetRedirectionKey(const Value:string);
procedure LoadFromStrings(const Content: string; const BaseUrl: string);
//procedure EvaluateJavaScript(const JavaScript: string);
//...............................
1.2.3.4.4、MSWindows
----------->通过以上原理和方法,(修改:爱吃猪头肉 & Flying Wang 2015-07-21)已经为我们修改好了补丁单元:Delphi10.4Update0_FixedDelphiPas\FMX.WebBrowser.pas,
FMX.WebBrowser.Win.pas===========》TWindowsWebBrowserService ===========》直接使用public方法,即可:
(* ****************************************************** *)
(* *)
(* 修改:爱吃猪头肉 & Flying Wang 2015-07-21 *)
(* 上面的版权声明请不要移除。 *)
(* *)
(* 禁止发布到城通网盘。 *)
(* *)
(* 仅支持 RAD10.4.0(10.4 Release 0),其他版本请自行修改 *)
(* *)
(* ****************************************************** *)
TWindowsWebBrowserService = class;
TWinWBMediator = class(TInterfacedObject, ICustomBrowser)
private
FBrowser: TWindowsWebBrowserService;
public
constructor Create;
destructor Destroy; override;
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
property WB: TWindowsWebBrowserService read FBrowser implements ICustomBrowser;
end;
TWindowsWebBrowserService = class(TOLEFrameworkDelegate, ICustomBrowser)
//Fix 重定向 关键字
private
FRedirectionKey: string;
private
//....................................
public
//....................................
// procedure EvaluateJavaScript(const JavaScript: string);
//Fix By Flying Wang and 爱吃猪头肉
procedure EvaluateJavaScript(const JavaScript: string;
DidEvaluateJavaScript: TWebBrowserDidEvaluateJavaScript = nil);
//Fix or Add By 爱吃猪头肉
function GetRealWebBrowserObject: IUnknown;
//Fix 重定向关键字,如果包含这个关键字 页面不刷新
//解析 重定向字符串
function GetRedirectionKey: string;
procedure SetRedirectionKey(const Value:string);
//....................................
1.2.3.4、事件中处理页面内容的回调
在这些事件中处理页面内容的回调:
property OnDidStartLoad: TWebBrowserDidStartLoad read GetOnDidStartLoad write SetOnDidStartLoad;
property OnDidFinishLoad: TWebBrowserDidFinishLoad read GetOnDidFinishLoad write SetOnDidFinishLoad;
property OnShouldStartLoadWithRequest: TWebBrowserShouldStartLoadWithRequest read GetOnShouldStartLoadWithRequest
write SetOnShouldStartLoadWithRequest;
property OnDidFailLoadWithError: TWebBrowserDidFailLoadWithError read GetOnDidFailLoadWithError
write SetOnDidFailLoadWithError;
页面回调BaseUrl,拿到回调结果字符串Content:
接口ICustomBrowser :
procedure LoadFromStrings(const Content: string; const BaseUrl: string);
扩展的接口:
ICustomBrowserEx = interface(IInterface)
['{5F61E8E6-54B5-4305-88DD-C7F8086352FF}']
procedure LoadFromStrings(const Content: string; const ContentEncoding: TEncoding; const BaseUrl: string);
end;
1.2.3.5、D10.4对TEdgeBrowser的支持及其新增TWebBrowser通过SelectedEngine 来选择使用老的 IE 核心还是新的 Edge 核心,完美支持在MSWINDOWS下H5的各种性能
详见本博客博文:
《RAD Studio 10.4.1的TEdgeBrowser与javascript交互-基于Chromium的Edge浏览器控件用法之二》https://blog.csdn.net/pulledup/article/details/109934357
《RAD Studio 10.4.1新的基于Chromium的Microsoft Edge浏览器的TEdgeBrowser控件用法》https://blog.csdn.net/pulledup/article/details/109848546
----------->通过以上原理和方法,(修改:爱吃猪头肉 & Flying Wang 2015-07-21)已经为我们修改好了补丁单元Delphi10.4Update0_FixedDelphiPas\FMX.WebBrowser.pas,
(1)、新增 跨平台属性 GetRealWebBrowserObject 获取各个平台下 原生的 浏览器对象:
// 下面是 GetRealWebBrowserObject 在安卓下的 例子
// (WebBrowser1.GetRealWebBrowserObject as JWebBrowser).getSettings.setUserAgentString(StringToJString('你的UserAgent'));
(2)、新增 重定向 Redirection 功能:
// 重定向 Redirection 功能 完全来自 [重庆]新手(371889755)
// IOS MAC 安卓的 重定向 全靠 [龟山]阿卍(1467948783) 帮忙测试:
// 请设置好 RedirectionKey,千万不要用 URL 上的一些关键字,也不要用特殊字符:
// 用 wwwwww 做关键字,比较好。
// 测试用 wwwwww.xxx.com
// 你发送的 url 中,千万也不要有 http: ftp: file: 等在 mac osx 系统上,带有这些,会导致打开网页。
可直接拿来用,用于FMX.WebBrowser与H5交互JavaScript。
前端-纯前端实现人脸识别-提取-合成:https://cloud.tencent.com/developer/article/1408454
腾讯开源H5图形图形处理库:https://github.com/AlloyTeam/AlloyImage
Delphi FMX.WebBrowser.pas就能很好的跨平台交互js:方法见“一、原理”:
procedure EvaluateJavaScript(const JavaScript: string);
//Fix By Flying Wang and 爱吃猪头肉
procedure EvaluateJavaScript(const JavaScript: string;
DidEvaluateJavaScript: TWebBrowserDidEvaluateJavaScript = nil);
//Fix or Add By 爱吃猪头肉
function GetRealWebBrowserObject: IUnknown;
//Fix 重定向关键字,如果包含这个关键字 页面不刷新
//解析 重定向字符串
function GetRedirectionKey: string;
procedure SetRedirectionKey(const Value:string);
《图片处理不用愁,给你十个小帮手》https://cloud.tencent.com/developer/article/1649704
其中,有很多案例在线测试。