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>