AndroidWebView的Js对象注入,使用场景是怎样的?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AndroidWebView的Js对象注入,使用场景是怎样的?相关的知识,希望对你有一定的参考价值。

参考技术A 很多时候要使用WebView来展示一个网页,现在很多应用为了做到服务端可控,很多结果页都是网页的,而不是本地实现,这样做有很多好处,比如界面的改变不需要重新发布新版本,直接在Server端修改就行了。用网页来展示界面,通常情况下都或多或少都与Java代码有交互,比如点击网页上面的一个按钮,需要知道这个按钮点击事件,或者要调用某个方法,让页面执行某种动作,为了实现这些交互,通常都是使用JS来实现,而WebView已经提供了这样的方法。 参考技术B 第一步:
mainfest.xml中加入网络权限
<uses-permission android:name="android.permission.INTERNET" />
第二步:
加载本地写好的html文件(定义好js中提供给android调用的方法 funFromjs(),和android提供给js调用的对象接口fun1FromAndroid(String name)),放在 assets目录下。
<body>
<a>js中调用本地方法</a>
<script>

function funFromjs()
document.getElementById("helloweb").innerHTML="HelloWebView,i'm from js";

var aTag = document.getElementsByTagName('a')[0];
aTag.addEventListener('click', function()
//调用android本地方法
myObj.fun1FromAndroid("调用android本地方法fun1FromAndroid(String name)!!");
return false;
, false);
</script>
<p></p>
<div id="helloweb">

</div>
</body>
第三步:

实现android工程与js交互的相关代码
android主题代码:
public class javascriptObject
Context mContxt;
@JavascriptInterface //sdk17版本以上加上注解
public JavaScriptObject(Context mContxt)
this.mContxt = mContxt;


public void fun1FromAndroid(String name)
Toast.makeText(mContxt, name, Toast.LENGTH_LONG).show();


public void fun2(String name)
Toast.makeText(mContxt, "调用fun2:" + name, Toast.LENGTH_SHORT).show();

参考技术C 例如,WebView页面中的一个按钮的点击事件是调用手机摄像头或拨号等手机自带功能实需要使用。
目前出现了很多混合开发,如APPCan、PhoneGap等,他们就是将网页调用猴急自带功能进行了封装,更方便的实现网页调用手机功能。

Flutter web app中注入Android对象的Android webview调用方法

【中文标题】Flutter web app中注入Android对象的Android webview调用方法【英文标题】:Flutter web app in the Android webview calling method of injected Android object 【发布时间】:2021-03-15 20:24:22 【问题描述】:

我有这种情况:有 android/Kotlin 应用程序,它有 webview,它从 Internet URL 加载 Flutter web 应用程序。

要明确 - 这不是在 Flutter 中拥有 webview 的情况。恰恰相反——Flutter 用于构建 web 应用,在 Android webview 中呈现。

我们按照google的说明创建了webview界面:https://developer.android.com/guide/webapps/webview

即Kotlin 在 webview 中创建 Android 对象。

我可以在调试 webview 时从 Chrome 调试工具控制台访问这个 Javascript Android 对象。

即Android / Kotlin 部分没问题。

但是,从 Flutter Web 应用程序调用时找不到 Android 对象。我交叉检查了,Flutter web app 可以调用 alert 函数。

谁能告诉我如何调用注入的 Android 对象?

Flutter Web 应用的代码:

void webViewExit() 
  print("User command: Exit webview.");

  try 
    js.context.callMethod("Android.onExitPressed");
   catch (e) 
    print(e);
  

chrome devtools 控制台中的结果:

User command: Exit webview.
NoSuchMethodError: method not found: 'apply' on null

 ​​​ 这直接在附加到 webview 的 devtools 控制台中工作:

Android.onExitPressed();

这也有效(来自 Flutter webview webapp):

void webViewExit() 
  print("User command: Exit webview.");

  try 
    // js.context.callMethod("Android.onBackPressed");
    js.context.callMethod("alert", ["Calling Alert works!"]);
   catch (e) 
    print(e);
  

【问题讨论】:

【参考方案1】:

我找到了解决方法:

我在 Flutter web 应用的静态 index.html 页面中添加了预定义函数:

index.html

  ...
  <script>
    if ('serviceWorker' in navigator) 
      window.addEventListener('flutter-first-frame', function () 
        navigator.serviceWorker.register('flutter_service_worker.js');
      );
    

    // Added JS function starts here

    function onExitPressed() 
      console.log("Called onExitPressed in webview JS.");
      Android.onExitPressed();
    
    // Added JS function ends here

  </script>
  <script src="main.dart.js" type="application/javascript"></script>
  ...

现在来自 Flutter Web 应用的调用可以正常工作了:

void webViewExit() 
  print("User command: Exit webview.");

  try 
    js.context.callMethod("Android.onExitPressed", []);
   catch (e) 
    print(e);
  

我认为原因是 Android 对象是在加载并启动 dart 的 main.dart.js 之后注入的。

【讨论】:

以上是关于AndroidWebView的Js对象注入,使用场景是怎样的?的主要内容,如果未能解决你的问题,请参考以下文章

androidwebview加载本地js怎么实现交互

Flutter web app中注入Android对象的Android webview调用方法

译 Node.js 中的依赖注入

如何在 Android Webview 中加载网页之前注入 javascript?

前端跨域

如何使 Vert.x JWTAuthHandler 只注入用户对象而不拒绝未经授权的请求?