Hybird开发,webview和H5交互

这篇具有很好参考价值的文章主要介绍了Hybird开发,webview和H5交互。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

H5调用原生功能

封装一个统一的接口,供H5页面调用原生的功能,比如获取设备信息、打开相机、分享内容等。这样,H5页面只需调用这个接口,而无需关心具体的原生实现细节。

//定义一个类,用@JavascriptInterface注解来注释一个方法,这个方法就可以被H5直接调用
public class NativeAPI {
    @JavascriptInterface
    public void getDeviceInfo() {
        // 假设获取设备信息的原生方法
        String deviceInfo = "Device: Android, Version: 11";
        // 将结果回调给H5页面
        String javascriptCode = "javascript:onDeviceInfoReceived('" + deviceInfo + "')";
        webView.loadUrl(javascriptCode);
    }
}

 // 添加 JavaScript 接口到 WebView 中
 webView.addJavascriptInterface(new NativeBridge(), "NativeBridge");

H5端调用:

function getDeviceInfo() {
  // 调用原生获取设备信息
  NativeAPI.getDeviceInfo();
}

原生调用H5

直接调用API:

String javascriptCode = "javascript:xxxx')";
webView.loadUrl(javascriptCode);
webView.evaluateJavascript("XXX")

原生回调H5

为了实现在 H5 页面中传递回调函数给原生代码,我们可以通过另外一种方式:使用随机生成的标识符来标记回调函数,并在原生代码中回调这个标识符对应的函数。

以下是修改后的示例代码,演示了在 H5 页面中调用复杂类型的 JavaScript 函数并传递回调函数标识符,然后在原生代码中通过标识符找到对应的回调函数并调用:

在 H5 页面中(例如 index.html):

<!DOCTYPE html>
<html>
<head>
    <title>Complex Function Callback Example</title>
</head>
<body>
    <h1>Complex Function Callback Example</h1>

    <script>
        // 用于保存回调函数
        var callbacks = {};

        // 定义复杂的 JavaScript 函数,返回一个包含多个属性的对象
        function getComplexData() {
            var complexData = {
                name: "John Doe",
                age: 30,
                address: {
                    city: "New York",
                    country: "USA"
                },
                interests: ["Reading", "Traveling", "Coding"]
            };
            return complexData;
        }

        // 示例:调用一个复杂的 JavaScript 函数,并传递回调函数
        function triggerComplexFunctionWithCallback() {
            var complexData = getComplexData();

            // 生成一个随机标识符作为回调函数的标识
            var callbackId = "cb_" + new Date().getTime();

            // 将回调函数保存到 callbacks 对象中,用于在原生代码中调用
            callbacks[callbackId] = function(result) {
                // 在回调函数中处理原生传递回来的复杂类型数据
                console.log("Received complex data from Native: ", result);
            };

            // 调用原生方法,并传递回调函数标识符
            window.NativeBridge.onComplexFunctionWithCallbackResult(complexData, callbackId);
        }
    </script>
</body>
</html>

在 Android 原生代码中:

import android.os.Bundle;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import androidx.appcompat.app.AppCompatActivity;
import org.json.JSONException;
import org.json.JSONObject;

public class MainActivity extends AppCompatActivity {

    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        webView = findViewById(R.id.webView);

        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);

        // 添加 JavaScript 接口到 WebView 中
        webView.addJavascriptInterface(new NativeBridge(), "NativeBridge");

        webView.setWebChromeClient(new WebChromeClient());
        webView.loadUrl("file:///android_asset/index.html");
    }

    // 定义一个 JavaScript 接口类,供 H5 页面调用
    private class NativeBridge {
        @JavascriptInterface
        public void onComplexFunctionWithCallbackResult(String jsonString, String callbackId) {
            // 在主线程中解析 JSON 字符串为复杂类型数据
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    try {
                        JSONObject json = new JSONObject(jsonString);
                        String name = json.getString("name");
                        int age = json.getInt("age");
                        JSONObject address = json.getJSONObject("address");
                        String city = address.getString("city");
                        String country = address.getString("country");
                        // 处理复杂类型数据
                        // ...

                        // 构造一个复杂类型数据的 JSON 字符串作为回调给 H5 页面
                        String result = "{ \"message\": \"Received complex data from Native\" }";

                        // 获取 H5 页面传递过来的回调函数标识符对应的回调函数
                        String callbackJs = "callbacks['" + callbackId + "']";

                        // 使用字符串拼接的方式将回调结果传递给 H5 页面的回调函数
                        webView.evaluateJavascript(callbackJs + "(" + result + ")", null);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
}

在上述示例中,我们在 H5 页面中定义了一个 JavaScript 对象 callbacks 来保存回调函数,并使用一个随机标识符来作为回调函数的键。在 triggerComplexFunctionWithCallback() 方法中,我们将回调函数保存到 callbacks 对象中,并传递回调函数的标识符给原生代码。

在原生代码中的 NativeBridge.onComplexFunctionWithCallbackResult(String jsonString, String callbackId) 方法中,我们获取到回调函数标识符,并通过字符串拼接的方式构造出相应的回调函数调用语句,从而正确地执行了 H5 页面传递过来的回调函数。

事件派发

封装一个事件派发机制,让原生和H5页面可以通过发送和监听事件来实现双向通信。这样可以在不直接调用对方方法的情况下,进行通信和数据交换。

在 Hybrid 开发中,事件派发是指从原生代码向 H5 页面发送消息或通知,让 H5 页面可以感知到某个事件的发生,从而执行相应的处理逻辑。事件派发是一种在原生和 H5 之间进行双向通信的手段之一。

以下是一种简单的实现方式,演示了如何在原生代码中派发一个事件给 H5 页面:

在 H5 页面中(例如 index.html):

<!DOCTYPE html>
<html>
<head>
    <title>Event Dispatch Example</title>
</head>
<body>
    <h1>Event Dispatch Example</h1>

    <script>
        // 监听自定义事件
        window.addEventListener("customEvent", function(event) {
            console.log("Received custom event:", event.detail);
            // 在这里可以执行相应的处理逻辑
            // ...
        });
    </script>
</body>
</html>

在 Android 原生代码中:

import android.os.Bundle;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        webView = findViewById(R.id.webView);

        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);

        webView.setWebChromeClient(new WebChromeClient());
        webView.loadUrl("file:///android_asset/index.html");

        // 派发事件到 H5 页面
        dispatchCustomEvent("Hello from Native!");
    }

    // 派发自定义事件到 H5 页面
    private void dispatchCustomEvent(String eventData) {
        // 使用 evaluateJavascript 方法调用 H5 页面中的 JavaScript 函数
        String script = "var event = new CustomEvent('customEvent', { detail: '" + eventData + "' });" +
                        "window.dispatchEvent(event);";
        webView.evaluateJavascript(script, null);
    }
}

我们在 H5 页面中使用 window.addEventListener 方法来监听名为 “customEvent” 的自定义事件。然后,在原生代码中的 dispatchCustomEvent 方法中,我们使用 webView.evaluateJavascript 方法执行 JavaScript 代码,从而派发一个名为 “customEvent” 的自定义事件,并传递事件数据给 H5 页面。

当原生代码执行 dispatchCustomEvent(“Hello from Native!”) 后,H5 页面中的监听器会捕获到该事件,并执行相应的处理逻辑。

需要注意的是,事件派发时,我们可以自定义事件的类型和传递的数据,并通过 JavaScript 的 CustomEvent 构造函数来创建自定义事件对象。在这个例子中,我们通过 CustomEvent(‘customEvent’, { detail: eventData }) 创建了一个自定义事件,其中 eventData 就是我们要传递给 H5 页面的事件数据。在原生代码中,我们将 eventData 作为字符串传递给 H5 页面,但你也可以将更复杂的数据结构转换为 JSON 字符串,然后传递给 H5 页面进行处理。

错误处理

设计统一的错误处理机制,让原生和H5页面能够更好地处理错误情况,并向对方传递错误信息。例如,当某个功能不支持时,通过错误回调通知H5页面。

在 Hybrid 开发中,为了解决回调函数的问题,我们可以使用一种约定的方式,让原生代码返回一个标识符给 H5 端,表示回调函数的唯一标识。然后,H5 端将这个标识符保存起来,并在需要的时候调用原生代码提供的另一个方法,传递这个标识符和需要回调的数据。原生代码根据标识符找到对应的回调函数,并执行回调处理。

以下是一个重新设计的例子,演示了如何在 Hybrid 开发中实现回调函数的传递和调用:

在 H5 页面中(例如 index.html):

<!DOCTYPE html>
<html>
<head>
    <title>Error Handling Example</title>
</head>
<body>
    <h1>Error Handling Example</h1>

    <script>
        // 保存回调函数的对象
        var callbacks = {};

        // 定义一个处理错误的回调函数
        function onError(errorMessage) {
            console.error("Received error message from Native:", errorMessage);
            // 在这里可以执行相应的错误处理逻辑
            // ...
        }

        // 定义一个注册回调函数的方法,返回一个唯一的标识符
        function registerCallback(callback) {
            var callbackId = "cb_" + new Date().getTime();
            callbacks[callbackId] = callback;
            return callbackId;
        }

        // 示例:调用原生方法,处理可能出现的错误
        function callNativeMethod() {
            // 注册回调函数,获取回调函数的标识符
            var callbackId = registerCallback(function(result) {
                // 检查 result 是否包含 error 字段
                if (result.error) {
                    // 如果 result 包含 error 字段,则触发错误处理回调
                    onError(result.error);
                } else {
                    // 否则,继续处理正常的结果
                    console.log("Received result from Native:", result);
                    // 在这里可以执行正常的处理逻辑
                    // ...
                }
            });

            // 调用原生方法,并传递回调函数的标识符
            window.NativeBridge.someFunction(callbackId);
        }
    </script>
</body>
</html>

在 Android 原生代码中:

import android.os.Bundle;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import androidx.appcompat.app.AppCompatActivity;
import org.json.JSONException;
import org.json.JSONObject;

public class MainActivity extends AppCompatActivity {

    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        webView = findViewById(R.id.webView);

        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);

        // 添加 JavaScript 接口到 WebView 中
        webView.addJavascriptInterface(new NativeBridge(), "NativeBridge");

        webView.setWebChromeClient(new WebChromeClient());
        webView.loadUrl("file:///android_asset/index.html");
    }

    // 定义一个 JavaScript 接口类,供 H5 页面调用
    private class NativeBridge {
        @JavascriptInterface
        public void someFunction(String callbackId) {
            try {
                // 假设这里出现了一个错误,我们模拟一个包含错误信息的 JSON 对象
                JSONObject errorObject = new JSONObject();
                errorObject.put("error", "Something went wrong!");

                // 获取回调函数的标识符对应的回调函数
                String callbackJs = "callbacks['" + callbackId + "']";

                // 使用字符串拼接的方式将错误信息传递给 H5 页面的回调函数
                webView.evaluateJavascript(callbackJs + "(" + errorObject.toString() + ")", null);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }
}

桥接封装

将原生代码和H5交互的桥接代码进行封装,使其更易用、更健壮,避免直接在业务逻辑中直接操作桥接代码,从而降低耦合性。

对于桥接代码,可以封装一个BridgeHelper类,用于处理原生和H5交互的细节,使得在业务逻辑中不直接操作桥接代码。

public class BridgeHelper {
    private WebView webView;

    public BridgeHelper(WebView webView) {
        this.webView = webView;
    }

    // 封装调用原生功能的方法
    public void callNativeFunction(String functionName) {
        // 构建JavaScript代码
        String javascriptCode = "javascript:" + functionName + "()";
        // 调用原生方法
        webView.loadUrl(javascriptCode);
    }
}
//其他地方调用
BridgeHelper bridgeHelper = new BridgeHelper(webView);
bridgeHelper.callNativeFunction("someNativeFunction");

安全处理

考虑安全性问题,确保对于原生和H5之间的通信,只暴露必要的接口,并对传递的数据进行验证和过滤,以防止潜在的安全风险。

在封装的API中,对于接收的参数进行验证,确保数据的有效性和安全性。

H5代码:

function sendDataToNative(data) {
  // 对数据进行验证,确保不为空且符合要求
  if (data !== null && typeof data === 'object') {
    // 调用原生方法并传递数据
    NativeAPI.sendData(data);
  } else {
    console.error("Invalid data format!");
  }
}

版本兼容

针对不同的原生和H5版本,可以进行一些兼容性处理,确保在不同平台和环境下都能正常运行。

调试日志

在桥接代码中添加调试日志,以便在开发和测试过程中更容易发现问题,对于某些复杂的交互,可以在日志中打印交互数据,方便排查问题。文章来源地址https://www.toymoban.com/news/detail-584894.html

到了这里,关于Hybird开发,webview和H5交互的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【JoAPP】Android WebView与H5交互实现(JAVA+KOTLIN)

           最近一个应急平台的项目移动端开发,原计划用UNI-APP实现,客户想着要集成语音、视频通话功能,基于经验判断需要买一套IM原生移动端框架去结合H5整合比较合适,没想到最后客户不想采购,而且语音视频通话功能也迟迟未能完全确认,H5部分所开发的业务功能已经

    2024年02月03日
    浏览(46)
  • 小程序webview组件,小程序和webview交互,小程序内联h5页面,小程序webview内网页实现微信支付

    小程序支持webview以后,我们开发的好多h5页面,就可以直接在小程序里使用了,比如我们开发的微信商城,文章详情页,商品详情页,就可以开发一套,多处使用了。我们今天来讲一讲。在小程序的webview里实现微信支付功能。因为微信不允许在小程序的webview里直接调起微信

    2024年02月09日
    浏览(63)
  • Vue.js uni-app 混合模式原生App webview与H5的交互

    在现代移动应用开发中,原生App与H5页面之间的交互已经成为一个常见的需求。本文将介绍如何在Vue.js框架中实现原生App与H5页面之间的数据传递和方法调用。我们将通过一个简单的示例来展示如何实现这一功能。 效果图如下: 首先,我们需要在Vue.js项目中引入原生App与H5页面

    2024年02月16日
    浏览(72)
  • 开发uniapp过程中对app、微信小程序与h5的webview调试

        因为在开发中使用到了webview,因为出现一些问题,所以需要对webview进行跟踪调试,但因为app,h5与微信小程序不一样,所以需要单独说一下。     一、H5     这个比较简单,因为都是在chrome,用F12就可以  二、对微信小程序       因为普通的uniapp页面上都能通过F12可以

    2024年02月11日
    浏览(69)
  • 原生app与uniapp开发的H5交互,H5写法

    一、h5调用原生app方法         1、先判断是安卓系统还是ios系统         2、调用原生app方法     toAppLogin 为调用原生app的方法                 1)   ios环境:window.webkit.messageHandlers.toAppLogin.postMessage();                 2)安卓环境:window.android.toAppLogin(); 二、原

    2024年01月21日
    浏览(45)
  • 小程序通过webView打开H5页面并传参(包含webView业务域名配置)、H5页面实现返回小程序并实现传参

    小程序内嵌webview实现跳转、传参 1、小程序通过webView打开H5页面并传参 2、H5接收小程序传参,H5返回小程序并实现传参,小程序接收H5传参 一、小程序通过webView打开H5页面并传参 在小程序中一般通过webview打开H5页面 常见问题: 1、小程序通过webview打开H5页面,需要配置业务域

    2024年02月12日
    浏览(47)
  • uniapp WebView与H5页面通信

    1、参数拼在url里 在h5页面里用window对象获取拼接的url   2、H5环境中 用window.postMessage传递数据    用window.addEventListener(\\\"message\\\", receiveMessage, false);   3、APP环境与微信小程序中 可以通过 uni.postMessage 在 HTML 中向应用发送消息 H5端 uni.postMessage参数格式,传递的消息信息必须在 d

    2024年02月11日
    浏览(37)
  • ArkTS-WebView内嵌H5页面

    访问在线网页时需添加网络权限: ohos.permission.INTERNET module.json5文件配置 踩坑日记 加载网页效果 无法在预览器中查看 ,需要 在模拟器或者真机中展示项目 Web组件的使用非常简单,只需要ArkTS文件中创建一个Web组件,传入两个参数就可以了。其中src指定引用的网页路径,co

    2024年01月15日
    浏览(41)
  • 安卓WebView(H5)调用原生相机及相册

    在开始叙述正文之前笔者先声明一下应用场景:例如在网页上的即时通讯需要能拍照或者从图库选择图片来进行上传,此场景下就可以用到这篇文章的内容 正文 首先,如果你已经把相机以及访问文件夹的权限都加上了并且WebView的基础操作都做完了,就差上传图片了的话那就参

    2024年02月11日
    浏览(46)
  • WebView交互架构项目实战(三):多进程WebView使用实践

    更新原理: 1、当浏览器首次请求资源的时候,服务器会返回200的状态码(ok),内容为请求的资源,同时response header会有一个ETag标记,该标记是服务器端根据容器(IIS或者Apache等等)中配置的ETag生成策略生成的一串唯一标识资源的字符串,ETag格式为 ETag:“856247206” 2、当浏览

    2024年04月15日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包