Android和h5页面相互传参

WebAppInterface.java(必须存在)

java 复制代码
package com.example.chapter05;

import android.content.Context;
import android.webkit.JavascriptInterface;
import android.widget.Toast;

public class WebAppInterface {
    Context mContext;

    // 构造函数
    WebAppInterface(Context c) {
        mContext = c;
    }

    // 这个方法将被 JavaScript 调用
    @JavascriptInterface
    public void receiveDataFromAndroid(String data) {
        // 在这里处理接收到的数据
        Toast.makeText(mContext, "收到数据: " + data, Toast.LENGTH_SHORT).show();
        // 你可以将数据存储到变量、发送广播、更新UI等
    }

    // 你还可以添加更多方法,例如传递复杂数据(JSON)
    @JavascriptInterface
    public void receiveUserData(String name, int age, String jsonExtra) {
        // 处理更复杂的数据
    }
}
java 复制代码
package com.example.chapter05;

import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.WindowInsetsController;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import androidx.activity.OnBackPressedCallback;
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);

        // 设置透明状态栏
        View decorView = getWindow().getDecorView();
        getWindow().setStatusBarColor(Color.TRANSPARENT); // 保持状态栏透明
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            // Android 11+ 设置状态栏图标为深色(浅色背景)
            getWindow().getInsetsController().setSystemBarsAppearance(
                    WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS,
                    WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS);
        } else {
            // Android 10 及以下
            decorView.setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
                            View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
                            View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR // 状态栏图标变深色
            );
        }

        webView = findViewById(R.id.webview);
        webView.getSettings().setJavaScriptEnabled(true); // 启用JavaScript
        webView.getSettings().setDomStorageEnabled(true); // 启用DOM存储

        // 注入接口对象到 JavaScript 环境,允许 JS 调用 Android 方法
        webView.addJavascriptInterface(new WebAppInterface(this), "Android");

        // 设置 WebViewClient,以便在 WebView 内部加载页面,并监听页面加载状态
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageStarted(WebView view, String url, android.graphics.Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
                // 可选:显示加载动画或进度条
                Log.d("WebView", "页面开始加载: " + url);
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                Log.d("WebView", "页面加载完成: " + url);
                updateUIForUrl(url);

                // ✅ 关键修复:在页面加载完成后,再执行 JS 传参
                // 避免页面未加载时 JS 函数不存在
                String username = "your_username"; // 替换为实际用户名
                String password = "your_password"; // 替换为实际密码

                // 对单引号进行转义,防止 JS 语法错误
                String safeUsername = username.replace("'", "\\'");
                String safePassword = password.replace("'", "\\'");

                // 构造 JS 脚本,调用 H5 页面中的 receiveData 函数
                // 添加存在性检查,避免报错
                String jsCode = String.format(
                        "javascript:(function() {" +
                                "  if (typeof receiveData === 'function') {" +
                                "    receiveData('%s', '%s');" +
                                "  } else {" +
                                "    console.warn('H5 页面未定义 receiveData 函数');" +
                                "  }" +
                                "})();",
                        safeUsername, safePassword
                );

                // 执行 JS
                webView.evaluateJavascript(jsCode, null);
            }
        });

        // 加载 H5 页面(不通过 URL 传参)
        webView.loadUrl("http://xxx/h5/login");

        // 添加后退事件的回调处理
        OnBackPressedCallback callback = new OnBackPressedCallback(true) {
            @Override
            public void handleOnBackPressed() {
                if (webView.canGoBack()) {
                    webView.goBack(); // WebView 返回上一页
                } else {
                    setEnabled(false); // 禁用当前回调
                    MainActivity.this.onBackPressed(); // 交由 Activity 处理退出
                }
            }
        };
        getOnBackPressedDispatcher().addCallback(this, callback);

        // 获取并打印状态栏高度(调试用)
        float statusBarHeight = getStatusBarHeight();
        Log.d("MainActivity", "状态栏高度: " + statusBarHeight + "px");
    }

    /**
     * 根据当前加载的 URL 更新 UI,例如沉浸式状态栏
     */
    private void updateUIForUrl(String url) {
        if (url.contains("login")) {
        } else {
        }
    }


    /**
     * 获取状态栏高度(单位:px)
     *
     * @return 状态栏高度
     */
    public float getStatusBarHeight() {
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            return getResources().getDimension(resourceId);
        }
        return 0;
    }
}

h5页面 接收和传参

javascript 复制代码
<script setup>
import { ref } from 'vue';

const username = ref('');
const password = ref('');

// 定义接收数据的函数
function receiveData(u, p) {
  username.value = u;
  password.value = p;
  console.log('接收到数据 - 用户名: ' + u + ', 密码: ' + p);
}

// ✅ 关键:将函数挂载到 window 对象,供 Android 调用
// 这样 window.receiveData 就可以在 evaluateJavascript 中调用
window.receiveData = receiveData;

// ✅ 调用 Android 原生方法
function sendToAndroid() {
  if (window.Android) {
    window.Android.receiveDataFromAndroid('h5向Android发送数据');
  } else {
    console.error("Android 接口未注入,可能不在 App 环境");
    alert("当前不在 App 中,无法调用原生功能");
  }
}
// 可选:同时暴露给父组件(如果需要)
defineExpose({ receiveData });
</script>

<template>
  <div>
    <h2>登录页面</h2>
    <p>用户名: {{ username }}</p>
    <p>密码: {{ password }}</p>
    <button @click="sendToAndroid">向 Android 传参</button>
  </div>
</template>

<style scoped lang="less">
/* 你的样式 */
</style>
相关推荐
千里马学框架1 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台1 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone1 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc1 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo2 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077002 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼2 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone2 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen2 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone2 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui