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>
相关推荐
恋猫de小郭1 小时前
Flutter 发布官方 Skills ,Flutter 在 AI 领域再添一助力
android·前端·flutter
Kapaseker6 小时前
一杯美式搞懂 Any、Unit、Nothing
android·kotlin
黄林晴6 小时前
你的 Android App 还没接 AI?Gemini API 接入全攻略
android
恋猫de小郭16 小时前
2026 Flutter VS React Native ,同时在 AI 时代 VS Native 开发,你没见过的版本
android·前端·flutter
冬奇Lab17 小时前
PowerManagerService(上):电源状态与WakeLock管理
android·源码阅读
BoomHe1 天前
Now in Android 架构模式全面分析
android·android jetpack
二流小码农1 天前
鸿蒙开发:上传一张参考图片便可实现页面功能
android·ios·harmonyos
鹏程十八少1 天前
4.Android 30分钟手写一个简单版shadow, 从零理解shadow插件化零反射插件化原理
android·前端·面试
Kapaseker1 天前
一杯美式搞定 Kotlin 空安全
android·kotlin
三少爷的鞋1 天前
Android 协程时代,Handler 应该退休了吗?
android