使用JSBridge框架来实现Android与H5(JS)交互

这篇具有很好参考价值的文章主要介绍了使用JSBridge框架来实现Android与H5(JS)交互。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.首先我们来了解一下什么是JSBridge?

在开发中,为了追求开发的效率以及移植的便利性,一些展示性强的页面我们会偏向于使用h5来完成,功能性强的页面我们会偏向于使用native来完成,而一旦使用了h5,为了在h5中尽可能的得到native的体验,我们native层需要暴露一些方法给js调用,比如,弹Toast提醒,弹Dialog,分享等等,有时候甚至把h5的网络请求放到native去完成。

JSBridge做得好的一个典型就是微信,微信给开发者提供了JS SDK,该SDK中暴露了很多微信native层的方法,比如支付,定位等。

请注意:使用JSBridge框架来实现Android与H5交互和

普通的Android与H5交互(详见混合开发:Android和H5(Js)交互_android和h5混合开发_ErwinNakajima的博客-CSDN博客)是不一样的,Android端和H5端写法都不一样,所以如果Android端使用JSBridge框架写了Android与H5交互,要同步到H5端,让他也改成这种方式,不然Android与H5交互无法生效。

2.引入jsbridge依赖,在app的build.gradle中添加依赖

dependencies {
api "com.github.lzyzsd:jsbridge:1.0.4"
}

在项目的build.gradle中添加,然后同步项目。

repositories {
    maven { url "https://jitpack.io" }
}

3.xml中的代码,这里用的ViewDataBinding方式写的:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".ui.JsbridgeActivity">

    <data>

        <import type="android.view.View" />

    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:ignore="UselessLeaf">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_73"
            android:background="@color/color_FFFFFFFF"
            app:contentInsetStart="0dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <View
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/dp_25" />

                <FrameLayout
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/dp_48"
                    tools:ignore="UselessLeaf">

                    <FrameLayout
                        android:id="@+id/layout_back"
                        android:layout_width="wrap_content"
                        android:layout_height="match_parent">

                        <ImageView
                            android:id="@+id/imv_back"
                            android:layout_width="@dimen/dp_9"
                            android:layout_height="@dimen/dp_16"
                            android:layout_gravity="center_vertical"
                            android:layout_marginStart="@dimen/dp_12"
                            android:layout_marginEnd="@dimen/dp_12"
                            android:src="@mipmap/icon_arrowhead_left"
                            android:visibility="visible"
                            tools:ignore="ContentDescription" />

                    </FrameLayout>

                    <TextView
                        android:id="@+id/tev_title"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center"
                        android:text="@string/mounting"
                        android:textColor="@color/color_80000000"
                        android:textSize="@dimen/sp_18" />

                </FrameLayout>

            </LinearLayout>

        </androidx.appcompat.widget.Toolbar>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:id="@+id/tev_function_to_js"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@color/color_FFD0D6EC"
                android:padding="@dimen/dp_10"
                android:text="@string/function_to_js"
                android:textColor="@color/color_FF198CFF"
                android:textSize="@dimen/sp_16" />

            <View
                android:layout_width="match_parent"
                android:layout_height="@dimen/dp_1"
                android:background="@color/color_80000000" />

            <TextView
                android:id="@+id/tev_function_to_js2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@color/color_FFD0D6EC"
                android:padding="@dimen/dp_10"
                android:text="@string/function_to_js2"
                android:textColor="@color/color_FF198CFF"
                android:textSize="@dimen/sp_16" />

        </LinearLayout>

        <View
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_1"
            android:background="@color/color_80000000" />

        <com.github.lzyzsd.jsbridge.BridgeWebView
            android:id="@+id/web_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </LinearLayout>

</layout>

4.BaseActivity中的代码:

package com.phone.library_common.base

import android.app.ActivityManager
import android.content.Intent
import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.Color
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.os.Looper
import android.os.Process
import android.view.Gravity
import android.view.View
import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.TextView
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import com.gyf.immersionbar.ImmersionBar
import com.phone.library_common.BaseApplication
import com.phone.library_common.R
import com.phone.library_common.manager.ActivityPageManager
import com.phone.library_common.manager.CrashHandlerManager
import com.phone.library_common.manager.LogManager
import com.phone.library_common.manager.ResourcesManager
import com.phone.library_common.manager.ToolbarManager
import com.phone.library_common.manager.ToolbarManager.Companion.assistActivity
import com.qmuiteam.qmui.widget.QMUILoadingView
import com.trello.rxlifecycle3.components.support.RxAppCompatActivity

abstract class BaseBindingRxAppActivity<DB : ViewDataBinding> : RxAppCompatActivity(), IBaseView {

    private val TAG = BaseBindingRxAppActivity::class.java.simpleName
    protected lateinit var loadView: QMUILoadingView
    protected lateinit var layoutParams: FrameLayout.LayoutParams

    //该类绑定的ViewDataBinding
    protected lateinit var mDatabind: DB
    protected lateinit var mRxAppCompatActivity: RxAppCompatActivity
    protected lateinit var mBaseApplication: BaseApplication
    private var mActivityPageManager: ActivityPageManager? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mRxAppCompatActivity = this
        mBaseApplication = application as BaseApplication
        mActivityPageManager = ActivityPageManager.get()
        mActivityPageManager?.addActivity(this)

        mDatabind = DataBindingUtil.setContentView(this, initLayoutId())
        mDatabind.lifecycleOwner = mRxAppCompatActivity
        initData()
        initViews()
        loadView = QMUILoadingView(this)
        loadView.also {
            it.visibility = View.GONE
            it.setSize(100)
            it.setColor(ResourcesManager.getColor(R.color.color_333333))
        }
        layoutParams = FrameLayout.LayoutParams(
            FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT
        )
        layoutParams.gravity = Gravity.CENTER
        addContentView(loadView, layoutParams)
        initLoadData()
    }

    override fun onConfigurationChanged(newConfig: Configuration) {
        //非默认值
        if (newConfig.fontScale != 1f) {
            resources
        }
        super.onConfigurationChanged(newConfig)
    }

    override fun getResources(): Resources? { //还原字体大小
        val res = super.getResources()
        //非默认值
        if (res.configuration.fontScale != 1f) {
            val newConfig = Configuration()
            newConfig.setToDefaults() //设置默认
            res.updateConfiguration(newConfig, res.displayMetrics)
        }
        return res
    }

    protected abstract fun initLayoutId(): Int

    protected open fun setToolbar(isDarkFont: Boolean) {
        if (isDarkFont) {
            ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(R.color.color_FFFFFFFF) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .keyboardEnable(true)
                .init()
        } else {
            ImmersionBar.with(this)
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(R.color.color_FF198CFF) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .keyboardEnable(true)
                .init()
        }
        ToolbarManager.assistActivity(findViewById(android.R.id.content))
    }

    protected open fun setToolbar(isDarkFont: Boolean, isResizeChildOfContent: Boolean) {
        if (isDarkFont) {
            ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(R.color.color_FFFFFFFF) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .keyboardEnable(true)
                .init()
        } else {
            ImmersionBar.with(this)
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(R.color.color_FF198CFF) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .keyboardEnable(true)
                .init()
        }
        if (isResizeChildOfContent) {
            ToolbarManager.assistActivity(findViewById(android.R.id.content))
        }
    }

    protected open fun setToolbar(isDarkFont: Boolean, color: Int) {
        if (isDarkFont) {
            ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(color) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .init()
        } else {
            ImmersionBar.with(this)
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(color) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .init()
        }
        ToolbarManager.assistActivity(findViewById(android.R.id.content))
    }

    protected open fun setToolbar(
        isDarkFont: Boolean,
        color: Int,
        isResizeChildOfContent: Boolean
    ) {
        if (isDarkFont) {
            ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(color) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .init()
        } else {
            ImmersionBar.with(this)
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(color) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .init()
        }
        if (isResizeChildOfContent) {
            ToolbarManager.assistActivity(findViewById(android.R.id.content))
        }
    }

    protected open fun setToolbar2(isDarkFont: Boolean, statusBarColor: Int) {
        if (isDarkFont) {
            ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(statusBarColor) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .keyboardEnable(true)
                .init()
        } else {
            ImmersionBar.with(this)
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(statusBarColor) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .keyboardEnable(true)
                .init()
        }
    }

    /**
     * 顶部栏吸顶专用
     */
    protected open fun setToolbar2(
        isDarkFont: Boolean,
        statusBarColor: Int,
        isResizeChildOfContent: Boolean
    ) {
        if (isDarkFont) {
            val window = window
            window.clearFlags(
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                        or WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
            )
            window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
            window.statusBarColor = Color.TRANSPARENT
            //        window.setNavigationBarColor(Color.TRANSPARENT);
            ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(statusBarColor) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .keyboardEnable(true)
                .init()
        } else {
            ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(statusBarColor) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .keyboardEnable(true)
                .init()
            val window = window
            window.clearFlags(
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                        or WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
            )
            window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
            window.statusBarColor = Color.TRANSPARENT
            //        window.setNavigationBarColor(Color.TRANSPARENT);
        }
        if (isResizeChildOfContent) {
            assistActivity(findViewById(android.R.id.content))
        }
    }

    protected abstract fun initData()

    protected abstract fun initViews()

    protected abstract fun initLoadData()

    protected open fun showToast(message: String?, isLongToast: Boolean) {
        //        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
        if (!mRxAppCompatActivity.isFinishing) {
            val toast: Toast
            val duration: Int
            duration = if (isLongToast) {
                Toast.LENGTH_LONG
            } else {
                Toast.LENGTH_SHORT
            }
            toast = Toast.makeText(mRxAppCompatActivity, message, duration)
            toast.setGravity(Gravity.CENTER, 0, 0)
            toast.show()
        }
    }

    protected open fun showCustomToast(
        left: Int, right: Int,
        textSize: Int, textColor: Int,
        bgColor: Int, height: Int,
        roundRadius: Int, message: String?,
        isLongToast: Boolean
    ) {
        val frameLayout = FrameLayout(this)
        val layoutParams = FrameLayout.LayoutParams(
            FrameLayout.LayoutParams.WRAP_CONTENT,
            FrameLayout.LayoutParams.WRAP_CONTENT
        )
        frameLayout.layoutParams = layoutParams
        val textView = TextView(this)
        val layoutParams1 = FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, height)
        textView.layoutParams = layoutParams1
        textView.setPadding(left, 0, right, 0)
        textView.textSize = textSize.toFloat()
        textView.setTextColor(textColor)
        textView.gravity = Gravity.CENTER
        textView.includeFontPadding = false
        val gradientDrawable = GradientDrawable() //创建drawable
        gradientDrawable.setColor(bgColor)
        gradientDrawable.cornerRadius = roundRadius.toFloat()
        textView.background = gradientDrawable
        textView.text = message
        frameLayout.addView(textView)
        val toast = Toast(this)
        toast.setView(frameLayout)
        if (isLongToast) {
            toast.duration = Toast.LENGTH_LONG
        } else {
            toast.duration = Toast.LENGTH_SHORT
        }
        toast.show()
    }

    open fun isOnMainThread(): Boolean {
        return Looper.getMainLooper().thread.id == Thread.currentThread().id
    }

    protected open fun startActivity(cls: Class<*>?) {
        val intent = Intent(this, cls)
        startActivity(intent)
    }

    protected open fun startActivityForResult(cls: Class<*>?, requestCode: Int) {
        val intent = Intent(this, cls)
        startActivityForResult(intent, requestCode)
    }

    open fun getActivityPageManager(): ActivityPageManager? {
        return mActivityPageManager
    }

    private fun killAppProcess() {
        LogManager.i(TAG, "killAppProcess")
        val manager =
            mBaseApplication.getSystemService(ACTIVITY_SERVICE) as ActivityManager
        val processInfos = manager.runningAppProcesses
        // 先杀掉相关进程,最后再杀掉主进程
        for (runningAppProcessInfo in processInfos) {
            if (runningAppProcessInfo.pid != Process.myPid()) {
                Process.killProcess(runningAppProcessInfo.pid)
            }
        }
        LogManager.i(TAG, "执行killAppProcess,應用開始自殺")
        val crashHandlerManager = CrashHandlerManager.get()
        crashHandlerManager?.saveTrimMemoryInfoToFile("执行killAppProcess,應用開始自殺")
        try {
            Thread.sleep(1000)
        } catch (e: InterruptedException) {
            LogManager.i(TAG, "error")
        }
        Process.killProcess(Process.myPid())
        // 正常退出程序,也就是结束当前正在运行的 java 虚拟机
        System.exit(0)
    }

    override fun onDestroy() {
        if (mActivityPageManager?.mIsLastAliveActivity?.get() == true) {
            killAppProcess()
        }
        mActivityPageManager?.removeActivity(mRxAppCompatActivity)
        super.onDestroy()
    }

}

5.Activity中的代码:

package com.phone.module_square.ui

import android.net.Uri
import android.os.Build
import android.webkit.ValueCallback
import android.webkit.WebChromeClient
import android.webkit.WebSettings
import android.webkit.WebView
import com.alibaba.android.arouter.facade.annotation.Route
import com.github.lzyzsd.jsbridge.CallBackFunction
import com.github.lzyzsd.jsbridge.DefaultHandler
import com.google.gson.Gson
import com.phone.library_common.base.BaseBindingRxAppActivity
import com.phone.library_common.bean.UserBean
import com.phone.library_common.manager.LogManager
import com.phone.library_common.manager.ResourcesManager
import com.phone.module_square.R
import com.phone.module_square.databinding.SquareActivityJsbridgeBinding


@Route(path = "/module_square/jsbridge")
class JsbridgeActivity : BaseBindingRxAppActivity<SquareActivityJsbridgeBinding>() {

    companion object {
        private val TAG = JsbridgeActivity::class.java.simpleName
    }

    override fun initLayoutId(): Int {
        return R.layout.square_activity_jsbridge
    }

    override fun initData() {

    }

    override fun initViews() {
        setToolbar(true)
        mDatabind.imvBack.setColorFilter(ResourcesManager.getColor(R.color.color_80000000))
        mDatabind.tevFunctionToJs.setOnClickListener {
            val userBean = UserBean()
            userBean.id = 1
            userBean.userId = "100"
            userBean.birthday = "1998.05.10"
            userBean.salary = 7000.0
            mDatabind.webView.callHandler(
                "functionToJs",
                Gson().toJson(userBean),
                CallBackFunction {
                    LogManager.i(TAG, "reponse data from JS $it")
                })
        }
        mDatabind.tevFunctionToJs2.setOnClickListener {
            mDatabind.webView.callHandler(
                "functionToJs2",
                "data from Android",
                CallBackFunction { data ->
                    LogManager.i(TAG, "reponse data from JS $data")
                })
        }
        mDatabind.webView.apply {
            setDefaultHandler(DefaultHandler())
            getSettings().setAllowFileAccess(true)
            getSettings().setAppCacheEnabled(true)
            getSettings().setDatabaseEnabled(true)
            // 允许网页定位
            // 允许网页定位
            getSettings().setGeolocationEnabled(true)
            // 允许网页弹对话框
            // 允许网页弹对话框
            getSettings().setJavaScriptCanOpenWindowsAutomatically(true)
            // 加快网页加载完成的速度,等页面完成再加载图片
            // 加快网页加载完成的速度,等页面完成再加载图片
            getSettings().setLoadsImagesAutomatically(true)
            // 开启 localStorage
            // 开启 localStorage
            getSettings().setDomStorageEnabled(true)
            // 设置支持javascript// 本地 DOM 存储(解决加载某些网页出现白板现象)
            // 设置支持javascript// 本地 DOM 存储(解决加载某些网页出现白板现象)
            getSettings().setJavaScriptEnabled(true)
            // 进行缩放
            // 进行缩放
            getSettings().setBuiltInZoomControls(true)
            // 设置UserAgent
            // 设置UserAgent
            getSettings().setUserAgentString(getSettings().getUserAgentString() + "app")

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                // 解决 Android 5.0 上 WebView 默认不允许加载 Http 与 Https 混合内容
                getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW)
            }
            webChromeClient = object : WebChromeClient() {
                fun openFileChooser(
                    uploadMsg: ValueCallback<Uri>, AcceptType: String?, capture: String?
                ) {
                    this.openFileChooser(uploadMsg)
                }

                fun openFileChooser(uploadMsg: ValueCallback<Uri>, AcceptType: String?) {
                    this.openFileChooser(uploadMsg)
                }

                fun openFileChooser(uploadMsg: ValueCallback<Uri>) {
//                    mUploadMessage = uploadMsg
//                    pictureSelector()
                }

                override fun onShowFileChooser(
                    webView: WebView,
                    filePathCallback: ValueCallback<Array<Uri>>,
                    fileChooserParams: FileChooserParams
                ): Boolean {
//                    mUploadMessageArray = filePathCallback
//                    pictureSelector()
                    return true
                }
            }
            loadUrl("file:///android_asset/jsbridge_js_java_interaction.html")


            registerHandler(
                "functionToAndroid"
            ) { data, function ->
                LogManager.i(
                    TAG,
                    "functionToAndroid handler = callNativeHandler, data from web = $data"
                )
                function.onCallBack("reponse data from Android 中文 from Java")
            }


            registerHandler(
                "functionToAndroid2"
            ) { data, function ->
                LogManager.i(
                    TAG,
                    "functionToAndroid2 handler = callNativeHandler, data from web = $data"
                )
                function.onCallBack("reponse data from Android 中文 from Java")
            }
        }
    }

    override fun initLoadData() {

    }

    override fun showLoading() {

    }

    override fun hideLoading() {

    }

}

6.JS的代码:

<html>
<head>
    <meta content="text/html; charset=utf-8" http-equiv="content-type">
    <title>
        js调用java
    </title>
</head>

<body>
<p>
    <xmp id="show">
    </xmp>
</p>
<p>
    <xmp id="init">
    </xmp>
</p>
<p>
    <input type="text" id="text1" value="用户名(username)"/>
</p>
<p>
    <input type="text" id="text2" value="password"/>
</p>
<!--        <p>-->
<!--            <input type="button" id="enter" value="发消息给Native" onclick="testClick();"-->
<!--            />-->
<!--        </p>-->
<p>
    <input type="button" id="enter1" value="调用Native方法" onclick="testClick1();"
    />
</p>
<p>
    <input type="button" id="enter2" value="调用Native方法2" onclick="testClick2();"
    />
</p>
<!--        <p>-->
<!--            <input type="button" id="enter2" value="显示html" onclick="testDiv();" />-->
<!--        </p>-->
<!--        <p>-->
<!--            <input type="file" value="打开文件" />-->
<!--        </p>-->
</body>
<script>
        function testDiv() {
            document.getElementById("show").innerHTML = document.getElementsByTagName("html")[0].innerHTML;
        }

<!--        function testClick() {-->
<!--            var str1 = document.getElementById("text1").value;-->
<!--            var str2 = document.getElementById("text2").value;-->

<!--            //send message to native-->
<!--            var data = {id: 1, content: "这是一个图片 <img src=\"a.png\"/> test\r\nhahaha"};-->
<!--            window.WebViewJavascriptBridge.send(-->
<!--                data-->
<!--                , function(responseData) {-->
<!--                    document.getElementById("show").innerHTML = "repsonseData from java, data = " + responseData-->
<!--                }-->
<!--            );-->

<!--        }-->

        function testClick1() {
            var str1 = document.getElementById("text1").value;
            var str2 = document.getElementById("text2").value;

            //call native method
            window.WebViewJavascriptBridge.callHandler(
                'functionToAndroid'
                , {'param': '中文测试'}

                , function(responseData) {
                    document.getElementById("show").innerHTML = "functionToAndroid send responseData from java, data = " + responseData
                }
            );
        }

        function testClick2() {
            var str1 = document.getElementById("text1").value;
            var str2 = document.getElementById("text2").value;

            //call native method
            window.WebViewJavascriptBridge.callHandler(
                'functionToAndroid2'
                , {'param': '中文测试2'}

                , function(responseData) {
                    document.getElementById("show").innerHTML = "functionToAndroid2 send responseData from java, data = " + responseData
                }
            );
        }

<!--        function bridgeLog(logContent) {-->
<!--            document.getElementById("show").innerHTML = logContent;-->
<!--        }-->

        function connectWebViewJavascriptBridge(callback) {
            if (window.WebViewJavascriptBridge) {
                callback(WebViewJavascriptBridge)
            } else {
                document.addEventListener(
                    'WebViewJavascriptBridgeReady'
                    , function() {
                        callback(WebViewJavascriptBridge)
                    },
                    false
                );
            }
        }

        connectWebViewJavascriptBridge(function(bridge) {
            bridge.init(function(message, responseCallback) {
                console.log('JS got a message', message);
                var data = {
                    'Javascript Responds': '测试中文!'
                };
                if (responseCallback) {
                    console.log('JS responding with', data);
                    responseCallback(data);
                }

                var data2 = {
                    'Javascript Responds': '测试中文2!'
                };
                if (responseCallback) {
                    console.log('JS responding with', data2);
                    responseCallback(data2);
                }
            });

            bridge.registerHandler("functionToJs", function(data, responseCallback) {
                document.getElementById("show").innerHTML = ("data from Java: = " + data);
                if (responseCallback) {
                    var responseData = "Javascript Says Right back aka!";
                    responseCallback(responseData);
                }
            });

            bridge.registerHandler("functionToJs2", function(data2, responseCallback) {
                document.getElementById("show").innerHTML = ("data2 from Java: = " + data2);
                if (responseCallback) {
                    var responseData = "Javascript2 Says Right back aka!";
                    responseCallback(responseData);
                }
            });
        })

</script>

</html>

7.Android调用JS方法:

mDatabind.webView.callHandler(
                "functionToJs2",
                "data from Android",
                CallBackFunction { data ->
                    LogManager.i(TAG, "reponse data from JS $data")
                })

JS方法接收Android数据

bridge.registerHandler("functionToJs2", function(data2, responseCallback) {
                document.getElementById("show").innerHTML = ("data2 from Java: = " + data2);
                if (responseCallback) {
                    var responseData = "Javascript2 Says Right back aka!";
                    responseCallback(responseData);
                }
            });

8.JS调用Android方法:

function testClick2() {
            var str1 = document.getElementById("text1").value;
            var str2 = document.getElementById("text2").value;

            //call native method
            window.WebViewJavascriptBridge.callHandler(
                'functionToAndroid2'
                , {'param': '中文测试2'}

                , function(responseData) {
                    document.getElementById("show").innerHTML = "functionToAndroid2 send responseData from java, data = " + responseData
                }
            );
        }

Android方法接收JS数据

registerHandler(
                "functionToAndroid2"
            ) { data, function ->
                LogManager.i(
                    TAG,
                    "functionToAndroid2 handler = callNativeHandler, data from web = $data"
                )
                function.onCallBack("reponse data from Android 中文 from Java")
            }

如对此有疑问,请联系qq1164688204。

推荐Android开源项目

项目功能介绍:原本是RxJava2 和Retrofit2 项目,现已更新使用Kotlin+RxJava2+Retrofit2+MVP架构+组件化和
Kotlin+Retrofit2+协程+MVVM架构+组件化, 添加自动管理token 功能,添加RxJava2 生命周期管理,集成极光推送、阿里云Oss对象存储和高德地图定位功能。

项目地址:https://gitee.com/urasaki/RxJava2AndRetrofit2文章来源地址https://www.toymoban.com/news/detail-720393.html

到了这里,关于使用JSBridge框架来实现Android与H5(JS)交互的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • pywebview 通过 JSBridge 调用 TTS

    pip install pywin32 ; pip install pywebview ; 通过 JSBridge 调用本机 TTS pip install cefpython3 cefpython3-66.1-py2.py3-none-win_amd64.whl (69.0 MB) Successfully installed cefpython3-66.1 编写 pywebview_tts.py 如下 编写 index3.html 如下 web 服务程序参见:  python:mdict + bottle = web 查询英汉词典 记得:将其中 index.html

    2024年02月11日
    浏览(43)
  • Android与H5交互 -- 点击H5跳转到 Android原生 页面 ,webview与h5(js)交互

    Android与H5交互 app开发过程中,利用原生+h5模式来开发是比较常见的 下面案例演示的是:原生调起一个H5页面,然后H5点击跳转到原生 WebViewActivity页面 调用H5 ,点击H5链接 跳转到原生MainActivity页面 注意 别忘了 !-- 添加网络权限 -- 一、清单文件,增加的配置 data的数据就是H5

    2023年04月14日
    浏览(72)
  • 【微信小程序】[渲染层错误] [jsbridge] invoke getGlobalStorage fail: too eayly.

    在微信开发者工具上出现报错: 详细报错: 修改调试基础库版本,可调低或者调高版本 修改调试基础库步骤: ① 开发工具选择【详情】 ② 选择【本地设置】 ③ 选择调试基础库版本 ④ 根据当前出现问题的版本,选择低版本或者高版本 完毕!

    2024年02月11日
    浏览(41)
  • 【JoAPP】Android WebView与H5交互实现(JAVA+KOTLIN)

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

    2024年02月03日
    浏览(46)
  • Android中使用WebView与JS交互全解析

    首先,需要提出一个概念,那就是hybrid,主要意思就是native原生Android和h5混合开发。为什么要这样做呢?大家可以想象一下针对于同一个活动,如果使用纯native的开发方式,Android和iOS两边都要维护同一套界面甚至是逻辑,这样开发和维护的成本会很大,而使用hybrid的开发方式

    2024年04月09日
    浏览(79)
  • Vue(h5)与App(android,ios)端交互详解

    最近开发vue与app交互,总结了一下开发心得。我是一名Android开发者,vue开发这块也稍有涉足,在android或者IOS中展示h5可以减少工作量,也能满足用户体验性。下面主要以Android和Vue方法介绍为主。 上菜了     三、 vue代码 注意,Vue中的方法通常是写在vue实例的methods中的,ap

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

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

    2024年02月16日
    浏览(72)
  • 已解决:H5移动端网页实现录音功能,js实现录音功能,包括安卓webview接口也可以使用

    遇到一个需求,需要做一个手机网页录音的功能,嵌入到webview中去,用安卓原生录音倒是可以,但是想着尽量去安卓化开发,就想着用纯的js前端代码去实现录音功能。 在 Web 应用程序中,JavaScript 是运行在浏览器中的客户端脚本语言,不具有直接访问设备硬件的能力。因此

    2024年02月07日
    浏览(54)
  • 使用nodejs和web3js实现链接metamask钱包并实现合约交互

    在以太坊区块链上,metamask钱包是一个非常常用的钱包,用以管理以太币和其他以太坊资产。同时,它也是一个重要的以太坊智能合约交互工具。在本文中,我们将介绍如何使用nodejs和web3js实现链接metamask钱包并实现合约交互。 在开始之前,首先需要安装NodeJS和Web3JS。 NodeJS是

    2024年02月04日
    浏览(90)
  • 关于android和vue.js交互

    本文使用webview框架AgentWeb 使用的Vue版本为vue3 使用的android sdk版本为33 从android 11 开始想要访问sd卡下的数据需要权限 权限请求方法为 使用以下方法注册接口 根据Android与Vue的交互的方法示例这篇文章最后中提到的互调的坑中得知因为Vue的问题Android调用Vue方法需要在window中暴

    2024年02月11日
    浏览(38)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包