React,WebView以及如何在Android上与JavaScript进行通信

介绍 (Intro)

WebView is a component used to render web pages in Android applications. It’s quite useful if you’d like to display some content (for example, your site) and want it to look like a part of an application.

WebView是用于在Android应用程序中呈现网页的组件。 如果您想显示一些内容(例如,您的网站),并希望它看起来像应用程序的一部分,这将非常有用。

In some cases, the developer only needs to display some information without any interactions with an Android application.

在某些情况下,开发人员只需要显示一些信息,而无需与Android应用程序进行任何交互。

But sometimes it’s not enough, and a developer should implement a bridge between JavaScript and Kotlin for communication: For example, maybe you’d like to call a JavaScript function when a user clicks on some button in your application.

但是有时这还不够,开发人员应该在JavaScript和Kotlin之间实现沟通桥梁:例如,当用户单击应用程序中的某些按钮时,您可能想调用JavaScript函数。

In my case, I needed to use WebView because there was some JavaScript code I didn’t want to implement on Kotlin.

就我而言,我需要使用WebView,因为有一些我不想在Kotlin上实现JavaScript代码。

Image for post
Source 资源

The four things above are used to load content via WebView. The most widely used is, of course, loadUrl, as typically content is served somewhere on a server.

上面的四件事用于通过WebView加载内容。 当然,使用最广泛的是loadUrl ,因为通常在服务器上某处提供内容。

互动类型 (Types of Interactions)

Actually, there are two types of interactions between JavaScript (via WebView) and an Android application:

实际上,JavaScript(通过WebView)和Android应用程序之间存在两种类型的交互:

  • Calling Kotlin function from JavaScript

    从JavaScript调用Kotlin函数
  • Calling JavaScript function from Kotlin

    从Kotlin调用JavaScript函数

使用JavaScript调用Kotlin函数 (Calling Kotlin Functions With JavaScript)

The things we need to do to call Kotlin functions with JS:

我们需要用JS调用Kotlin函数要做的事情:

  • Write a special interface

    写一个特殊的界面
  • Add it to WebView

    将其添加到WebView
  • Call an interface function from the JS

    从JS调用接口函数

First of all, we create a special interface. Let’s name it AndroidJSInterface.

首先,我们创建一个特殊的界面。 让我们将其命名为AndroidJSInterface

object AndroidJSInterface: KoinComponent {


    @JavascriptInterface
    fun onPerformed() {
       Timber.i("It was called")
    }
}

As you can see, a function that’ll be called from JavaScript has the special annotation @JavascriptInterface, which indicates to WebView that this function can be called from JS.

如您所见,将从JavaScript调用的函数具有特殊的注释@JavascriptInterface ,该注释向WebView指示可以从JS调用此函数。

The next thing to do is to add this interface to WebView. Here we name it Android, but you can name it as you want.

下一步是将该接口添加到WebView。 在这里,我们将其命名为Android ,但是您可以根据需要命名。

webView.addJavascriptInterface(AndroidJSInterface, "Android")

Now we need to call this function from JS code:

现在我们需要从JS代码调用此函数:

window.Android.onPerformed();

从Kotlin调用JavaScript函数 (Calling JavaScript Functions From Kotlin)

In most cases, calling JavaScript is also pretty simple:

在大多数情况下,调用JavaScript也非常简单:

webView.loadUrl("javascript:callingFunction()");

So here we call a function named callingFunction().

因此,在这里我们调用了一个名为callingFunction()的函数。

但是,如果将JavaScript缩小,该怎么办? (But what if JavaScript is minified?)

There are a variety of JavaScript minifiers: For example, a production build of React uses minified JS.

有很多JavaScript缩小器:例如,React的生产版本使用缩小的JS。

Image for post
How minified JS looks like
缩小的JS的样子

The problem is after minification, the function names are changed, and that’s why you can’t call them directly.

问题是缩小后,函数名称已更改,这就是为什么您不能直接调用它们的原因。

My first idea was to somehow note at config to skip optimizing certain functions in order to save their names, but there’s no way to do it.

我的第一个想法是在config上以某种方式注释以跳过优化某些功能以保存其名称的方法,但是没有办法做到这一点。

Another idea was to rename the function back in order to have its name saved, but it’d be too time-consuming.

另一个想法是重命名该函数以保存其名称,但这会很费时。

这是一个解决方案 (Here’s a solution)

  1. Add a special event listener inside the JavaScript code, and call a function when an event is dispatched.

    在JavaScript代码内添加一个特殊的事件侦听器,并在调度事件时调用一个函数。
  2. Dispatch the event from Android.

    从Android发送事件。

“The Event interface represents an event which takes place in the DOM.

Event接口表示在DOM中发生的事件。

An event can be triggered by the user action e.g. clicking the mouse button or tapping keyboard, or generated by APIs to represent the progress of an asynchronous task. It can also be triggered programmatically, such as by calling the HTMLElement.click() method of an element, or by defining the event, then sending it to a specified target using EventTarget.dispatchEvent().”

事件可以由用户操作触发,例如单击鼠标按钮或敲击键盘,也可以由API生成以表示异步任务的进度。 也可以通过编程方式触发它,例如,通过调用元素的HTMLElement.click()方法或定义事件,然后使用EventTarget.dispatchEvent()将其发送到指定的目标。”

MDN Web Docs

MDN Web文档

Here we dispatch an event called event.

在这里,我们调度了一个名为event

webView.evaluateJavascript(
  "(function() { window.dispatchEvent(event); })();"
) { }

And here we add a listener and do something when the event happens.

在这里,我们添加了一个侦听器,并在event发生时执行一些操作。

For example, we can call the function we wanted to call.

例如,我们可以调用我们要调用的函数。

window.event = new Event('event');


window.addEventListener('event', function() {
    // something is performed
}, false);

结论 (Conclusion)

Sites are loaded into WebView using the loadUrl function and the site URL passed as a parameter.

使用loadUrl函数和作为参数传递的网站URL将网站加载到WebView中。

您可以从Kotlin调用JavaScript函数 (You can call a JavaScript function from Kotlin)

  • Directly by its name using javascript:functionName() passed to the loadUrl function

    使用javascript:functionName()直接按其名称传递给loadUrl函数

  • Using events: calling the evalutateJavascript function with a special thing passed as a parameter

    使用事件:以传递为参数的特殊方式调用evalutateJavascript函数

您可以从JavaScript调用Kotlin函数 (You can call Kotlin function from JavaScript)

  • Write a special function annotated with @JavascriptInterface

    编写一个带有@JavascriptInterface注释的特殊函数

  • Call addJavascriptInterface, pass an object with the special function inside as a parameter, and name it somehow (for example, “Android”)

    调用addJavascriptInterface ,将内部带有特殊功能的对象作为参数传递,并以某种方式对其进行命名(例如,“ Android”)

  • Call the function from JavaScript using window.Android.functionName();

    使用window.Android.functionName();从JavaScript调用函数window.Android.functionName();

Happy coding, guys. Thank you for reading the article.

各位,祝大家编程愉快。 感谢您阅读这篇文章。

翻译自: https://medium.com/better-programming/react-webviews-and-how-to-communicate-with-javascript-on-android-70543c35d37d

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值