Android手把手编写儿童手机远程监控App之agentweb如何实现全屏

概述

上节完成嘟妈vant ui部署。Vant 是有赞团队开源的移动端 Vue UI 组件库,vant 专门针对移动端优化。适用场景:

  • 手机 H5 页面
  • 微信公众号
  • 企业微信应用
  • 钉钉应用
  • UniApp H5 嘟宝是为监督孩子身边环境而创建的一套应用,它能够实现后台驻留长连接,随时接收嘟妈信令,建立音视频通道点对点通信,而不需要中转 服务器。嘟妈是一套WEB 应用,使用vue3编写,能够兼容app、小程序开发。目前为止,嘟宝完成的基本功能设计包括
  • MQTT 基础通信
  • 后台驻留
  • SQLite数据存储
  • 二维码显示身份识别码
  • 开启自启动前台服务
  • 任务栏消息发送与点击 嘟宝使用WebRtc与嘟妈建立音视频通信,它的核心需求包含以下部分:
    • 嘟妈获取嘟宝摄像头、麦克风音视频流
    • 获取嘟宝桌面共享内容
    • 嘟妈与嘟宝建立音视频通话 嘟妈采用vue3编写,使用agentweb在Android终端渲染,发现在拉去嘟宝视频流观看时,无法全屏。

agentweb如何实现全屏

  • 修改activity开启硬件加速,防止屏幕旋转时 Activity 重建
  • 需要一个容器(比如 FrameLayout)来展示全屏时的视频画面

创建DuMaActivity用于渲染vue3

修改 Manifest 清单文件

clike 复制代码
 <activity
    android:name=".DuMaActivity"
      android:hardwareAccelerated="true"
      android:configChanges="orientation|screenSize|keyboardHidden"
      android:theme="@style/Theme.AppCompat.Light.NoActionBar"
      android:exported="false" />

DuMaActivity源码

clike 复制代码
package com.zilong.dubao;

import androidx.appcompat.app.AppCompatActivity;

import android.content.pm.ActivityInfo;
import android.os.Build;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.FrameLayout;
import android.widget.LinearLayout;

import com.just.agentweb.AgentWeb;
import com.just.agentweb.WebChromeClient;

public class DuMaActivity extends AppCompatActivity {
    private AgentWeb mAgentWeb;
    private FrameLayout mFullscreenContainer;
    private View mCustomView;
    private WebChromeClient.CustomViewCallback mCustomViewCallback;
    // 2. 自定义 WebChromeClient
    private WebChromeClient mWebChromeClient = new WebChromeClient() {

        @Override
        public void onShowCustomView(View view, CustomViewCallback callback) {
            // 进入全屏
            if (mCustomView != null) {
                callback.onCustomViewHidden();
                return;
            }

            mCustomView = view;
            mCustomViewCallback = callback;

            // 将全屏视频 View 添加到容器中
            mFullscreenContainer.addView(view);
            mFullscreenContainer.setVisibility(View.VISIBLE);

            // 隐藏 AgentWeb 和标题栏等
            mAgentWeb.getWebCreator().getWebView().setVisibility(View.GONE);
            // 隐藏你的 Toolbar
//            getSupportActionBar().hide();

            // 可选:强制横屏
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }

        @Override
        public void onHideCustomView() {
            // 退出全屏
            if (mCustomView == null) {
                return;
            }

            // 移除全屏视频 View
            mFullscreenContainer.removeView(mCustomView);
            mFullscreenContainer.setVisibility(View.GONE);

            // 恢复 AgentWeb 和标题栏的显示
            mAgentWeb.getWebCreator().getWebView().setVisibility(View.VISIBLE);
            // 恢复显示你的 Toolbar
//            getSupportActionBar().show();

            // 恢复竖屏
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

            // 通知 WebView 全屏已退出
            mCustomViewCallback.onCustomViewHidden();

            mCustomView = null;
            mCustomViewCallback = null;
        }
    };



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_du_ma);
        LinearLayout container = findViewById(R.id.web_container);
        mFullscreenContainer = findViewById(R.id.fullscreen_container);

        // 2. 构建 AgentWeb 实例
        mAgentWeb = AgentWeb.with(this) // 传入 Activity
                .setAgentWebParent(container, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)) // 设置父控件和布局参数
                .useDefaultIndicator() // 使用默认进度条
                .setWebChromeClient(mWebChromeClient)
                .createAgentWeb() // 创建 AgentWeb 对象
                .ready() // 准备就绪
                .go(MyConfig.dumaURL);
        // 注意:如果 HTML 中使用了 JavaScript,需要手动启用
        if (mAgentWeb != null && mAgentWeb.getAgentWebSettings() != null) {
            mAgentWeb.getAgentWebSettings().getWebSettings().setJavaScriptEnabled(true);
        }
        WebView webView = mAgentWeb.getWebCreator().getWebView();
        WebSettings settings = webView.getSettings();
        settings.setAllowFileAccess(true);           // 允许访问文件
        settings.setAllowFileAccessFromFileURLs(true);  // 允许 file:// 下的跨文件访问
        settings.setAllowUniversalAccessFromFileURLs(true); // 允许所有 file:// 下的跨文件访问
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WebView.setWebContentsDebuggingEnabled(true);
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (mAgentWeb.handleKeyEvent(keyCode, event)) {
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mAgentWeb != null) {
            mAgentWeb.getWebLifeCycle().onDestroy();
        }
    }
}

DuMaActivity xml文件

clike 复制代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".DuMaActivity">
    <LinearLayout
        android:id="@+id/web_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" />
    <FrameLayout
        android:id="@+id/fullscreen_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />

</androidx.constraintlayout.widget.ConstraintLayout>

运行效果如下

总结

核心代码,继承 WebChromeClient 并重写 onShowCustomView 和 onHideCustomView 方法,以控制视频全屏时的界面切换。

  • Manifest 配置是前提:hardwareAccelerated="true" 和 configChanges 这两个属性缺一不可,否则视频可能无法渲染或屏幕旋转导致播放中断
  • 核心在于 WebChromeClient 的回调:onShowCustomView 负责接管视频视图并切换到全屏 UI,onHideCustomView 负责恢复
  • 妥善管理生命周期:需要在 onBackPressed 中判断并处理全屏退出逻辑,确保用户体验连贯。
相关推荐
miss38 分钟前
AI 改完不敢上线?OpenSpec 规约驱动开发实战
前端·代码规范·前端工程化
AiMan1 小时前
腾讯ima还是不可以导出左侧所有对话,只能单条导出,方法不对吗
前端
去伪存真1 小时前
并发量一高就装死?Agent 全链路“防猝死”手册
前端·agent
Moment1 小时前
AI 编程时代,聊聊我的 Mac mini 双屏桌面
前端·后端
AiMan2 小时前
先确认能不能一次把Microsofat Copilot所有内容打包一个文件导出
前端
总要学点什么2 小时前
第97篇:三维数据加载-城市建筑白模自定义着色器——让一条光带沿高度扫上去,快慢却由帧率说了算
前端·gis·webgl·cesium·着色器·空间分析·白模
上海懒图科技2 小时前
工厂厂区电子地图定位导航:厂区人车精准定位,安全合规双保障
前端·arcgis·vue
西安小哥2 小时前
端侧跑大模型,真正的门槛不在参数量:一次 596 秒到 10 秒的压缩路径复盘
前端·人工智能
陈随易3 小时前
Cloudflare 出钱,Vite 团队挑人,44 个维护者分 30 万美元
前端·后端·程序员
恋猫de小郭3 小时前
Flutter THLC 的 WebView 滚动终于从 70 FPS 提升到 120 FPS
android·前端·flutter