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

Posted

技术标签:

【中文标题】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 之后注入的。

【讨论】:

以上是关于Flutter web app中注入Android对象的Android webview调用方法的主要内容,如果未能解决你的问题,请参考以下文章

Android Flutter App 中的持久后台工作程序,每 30 秒获取一次 Web API

Flutter 安卓app web网页电脑桌面软件

签名发布后尝试调试时 Flutter android App 崩溃

是否可以在 Flutter Web 和 Flutter App 中实现 Agora Video Call?

Flutter Web和Firebase身份验证TypeError:无法读取未定义的属性'app'

Flutter Web:在 Flutter 运行时在注入的 client.js 脚本中检测到未处理的错误