Android调用js的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android调用js的问题相关的知识,希望对你有一定的参考价值。

请问android直接webview.loadUrl("javascript:js()")
js()的方法会执行嘛?
还是要弄个button出发js()

参考技术A Android中可以使用WebView加载网页,同时Android端的java代码可以与网页上的javascript代码之间相互调用。
一 Android部分:
布局代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:focusable="true" android:focusableInTouchMode="true" android:orientation="vertical" android:padding="8dp" tools:context=".MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/input_et" android:layout_width="0dp" android:layout_height="wrap_content" android:singleLine="true" android:layout_weight="1" android:hint="请输入信息" /> <Button android:text="Java调用JS" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="sendInfoToJs" /> </LinearLayout> <WebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
Activity代码:
public class MainActivity extends AppCompatActivity private WebView webView; @Override protected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = (WebView) findViewById(R.id.webView); webView.setVerticalScrollbarOverlay(true); //设置WebView支持JavaScript webView.getSettings().setJavaScriptEnabled(true); webView.loadUrl("file:///android_asset/webview.html"); //在js中调用本地java方法 webView.addJavascriptInterface(new JsInterface(this), "AndroidWebView"); // //添加客户端支持 webView.setWebChromeClient(new WebChromeClient()); private class JsInterface private Context mContext; public JsInterface(Context context) this.mContext = context; //在js中调用window.AndroidWebView.showInfoFromJs(name),便会触发此方法。 @JavascriptInterface public void showInfoFromJs(String name) Toast.makeText(mContext, name, Toast.LENGTH_SHORT).show(); //在java中调用js代码 public void sendInfoToJs(View view) String msg = ((EditText) findViewById(R.id.input_et)).getText().toString(); //调用js中的函数:showInfoFromJava(msg) webView.loadUrl("javascript:showInfoFromJava('" + msg + "')"); // webView.loadUrl("javascript:showInfoFromJava()");
二 网页代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Android WebView 与 Javascript 交互</title> </head> <body> <input type="button" value="分享" onclick="f1()"> <input type="text" id="show"/> </body> <script> function f1() AndroidWebView.showInfoFromJs("hello"); function showInfoFromJava(msg) document.getElementById("show").value=msg; alert(1); </script> </html>
注意: android 调用js代码可能会报错如下:
W/WebView(2088): java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread.
解决办法:

webView.post(new Runnable() @Override public void run() webView.loadUrl("javascript:showInfoFromJava('" + msg + "')"); );
参考技术B android怎样调用js文件里面的方法
如果多个线程同时访问一个集合,而其中至少一个线程修改了该集合,那么它必须 保持外部同步。这通常是通过对自然封装该集合的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用 Collections.synchronizedSet 方法来“包装”集合。最好在创建时完成这一操作,以防止对 HashSet 实例进行意外的不同步访问:
Set s = Collections.synchronizedSet(new HashSet(...));

在 Flutter Web 中从 JS 调用 Dart 方法

【中文标题】在 Flutter Web 中从 JS 调用 Dart 方法【英文标题】:Call Dart method from JS in Flutter Web 【发布时间】:2021-04-02 01:14:59 【问题描述】:

对于 Webview 相关功能,我使用方法通道通过原生 Android 和 iOS 代码打开 Webview,并且我正在其中打开一个网站,我正在从 JS 回调到移动平台中的原生代码。 对于 Android,我提供了一个从 JS 调用其方法的类, 它看起来像这样:

webView.settings.javaScriptEnabled = true
webView.addJavascriptInterface(WebAppInterface(this), "nativeCommunicator")

webView.loadUrl("SOME_URL")

…

class WebAppInterface(private val mContext: Activity) 
  @JavascriptInterface
  fun postMessage(text: String) 
    println("WebAppInterface.message($text)")
    //send back to flutter
  

从 js 到我的代码的回调似乎很简单。

现在我正在尝试在 Flutter Web 中执行此操作 我通过调用打开了网站

import 'package:js/js.dart';
...
js.context.callMethod('open', 'SOME_URL', '_self');

效果很好,现在我正在尝试通过创建此类来获取回调

@JS()
library native_communicator;

import 'package:js/js.dart';
@JS('nativeCommunicator')
class NativeCommunicator

 @JS('postMessage')
 external static set _postMessage(void Function(String text) f);


 @JS()
 external static void postMessage();



void setJSCallbackFunction(void Function(String text) postMessageFunction) 
 NativeCommunicator._postMessage = allowInterop(postMessageFunction);

我正在调用 setJSCallbackFunction 并将我的函数作为参数传递,但它不断给我运行时错误 它找不到'postMessage',我尝试了其他一些导致找不到'nativeCommunicator'错误的方法, 谁能指出如何正确地做到这一点? 我需要从 js 中调用一个 dart 方法。

【问题讨论】:

【参考方案1】:

我认为您正在从 dart:js 库中寻找 allowInterop 函数:https://api.flutter.dev/flutter/dart-js/dart-js-library.html

示例代码:

import 'dart:html';
import 'dart:js';
import 'package:js/js_util.dart';

String dartFunc(String str) 
  return 'Inside dartFunc: ' + str;


void main() 
  setProperty(window, 'dartFunc', allowInterop(dartFunc));
  runApp(MyApp());

【讨论】:

它就在我的代码中。请检查一下,您尝试过并且有工作样品吗? 抱歉,没注意到。我已经用一些示例代码更新了答案。 js怎么调用? 它是在全局window对象上定义的,所以你可以通过dartFuncwindow.dartFunc来引用它【参考方案2】:

使 Dart 函数可从 JavaScript 调用

如果您将 Dart 函数作为参数传递给 JavaScript API,请使用 allowInterop()allowInteropCaptureThis() 包装 Dart 函数。

要通过名称从 JavaScript 调用 Dart 函数,请使用带有 @JS() 注释的 setter。

示例:

@JS()
library callable_function;

import 'package:js/js.dart';

/// Allows assigning a function to be callable from `window.functionName()`
@JS('functionName')
external set _functionName(void Function() f);

void _someDartFunction() 
  print('Hello from Dart!');


void main() 
  _functionName = allowInterop(_someDartFunction);
  // JavaScript code may now call `functionName()` or `window.functionName()`.

来自package:js docs

变化 -

@JS()
library native_communicator;

import 'package:js/js.dart';
@JS('nativeCommunicator')
class NativeCommunicator

 @JS('postMessage')
 external static set _postMessage(void Function(String text) f);

// No need to do this as 'allowInterop()' will do the necessary.
//
// @JS()
// external static void postMessage();
//
// 

void setJSCallbackFunction(void Function(String text) postMessageFunction) 
 NativeCommunicator._postMessage = allowInterop(postMessageFunction);

import 'path/to/setJSCallbackFunction-file';

void main() 
    setJSCallbackFunction(param);

调试步骤

    寻找生成的js文件-build/web/main.dart.js 尝试使用搜索来定位函数。 (这里,postMessage) 如果你找不到它,那么你可能错过了一些注释或者可能没有在main() 中调用allowInterop() 如果您能够找到它但它不起作用,请检查您的 dart 函数并确保您传递了正确的参数。此外,请确保 dart.main.js 在范围内。
<script src"path/to/dart.main.js">
window.functionName(); // or functionName()
</script>

倾向于将js函数定义为顶层函数,可以用window.functionName()functionName()调用

【讨论】:

以上是关于Android调用js的问题的主要内容,如果未能解决你的问题,请参考以下文章

Android与JS混编(js调用android相机)

在android中怎样调用本地js文件里的方法并得到返回值

需要从cordova插件-android调用js函数

如何在Android平台上使用JS直接调用Java方法

Webview Android与js交互

搜索 - 本地处理或进行 API 调用? (Android、Node.JS、MongoDB 后端)