专业办证
专业办证
  • 发布:2026-10-15 21:52
  • 更新:2026-10-15 21:52
  • 阅读:43

【报Bug】最新版的HbuilderX-alpha版的,安卓端视频全屏播放的时候有报错,手机端直接闪退

分类:uni-app

产品分类: uniapp/App

PC开发环境操作系统: Windows

PC开发环境操作系统版本号: win11

HBuilderX类型: 正式

HBuilderX版本号: 5.31

手机系统: Android

手机系统版本号: Android 15

手机厂商: 模拟器

手机机型: 荣耀magic8

页面类型: nvue

vue版本: vue3

打包方式: 云端

项目创建方式: HBuilderX

操作步骤:

如果处于小屏幕情况下播放视频,然后点击全屏播放按钮,模拟器上面播放后hbuildx就会出现报错,手机的话就会出现闪退,但是将同样的代码回退到 HBuilderX.5.26.2026091802 这个版本的重新打包并安装就不会有那个问题。

预期结果:

无

实际结果:

无

bug描述:

<template>
<view v-if="visible" class="preview-overlay">
<view class="preview-header">
<text class="preview-close" @click="onClose">✕</text>
<text class="preview-name">{{ fileName }}</text>
<text class="preview-close" @click="onClose">✕</text>
</view>

    <view class="preview-body">  
        <video v-if="previewType == 'video'" id="previewVideo" ref="videoRef" class="preview-video"  
            :title="fileName" :src="streamUrl" :show-loading="false" controls autoplay  
            @fullscreenchange="onVideoFullscreenchange" @longpress="onVideoLongPress" @touchend="onVideoTouchEnd"  
            @touchcancel="onVideoTouchEnd" @fullscreenclick="onVideoTouchEnd" />  

        <scroll-view v-if="previewType == 'text'" class="preview-text-scroll" direction="vertical"  
            :show-scrollbar="true">  
            <text v-if="loading" class="preview-loading">加载中...</text>  
            <text v-else class="preview-text-content">{{ textContent }}</text>  
        </scroll-view>  

        <view v-if="previewType == 'audio'" class="preview-audio">  
            <text class="preview-audio-icon">?</text>  
            <text class="preview-audio-name">{{ fileName }}</text>  
            <video class="preview-audio-player" :src="streamUrl" controls autoplay />  
        </view>  

        <view v-if="previewType == 'other'" class="preview-other">  
            <text class="preview-other-name">{{ fileName }}</text>  
            <text class="preview-other-tip">暂不支持预览此格式</text>  
        </view>  
    </view>  

    <view v-if="isMedia" class="preview-nav">  
        <text class="preview-nav-btn" @click="onPrev">‹ 上一个</text>  
        <text class="preview-nav-count">{{ currentIndex }} / {{ total }}</text>  
        <text class="preview-nav-btn" @click="onNext">下一个 ›</text>  
    </view>  
</view>  

</template>

<script setup lang="uts">
import { PropType } from 'vue'
import { FileItem } from "@/common/api-types.uts"

const props = defineProps({  
    visible: { type: Boolean, default: false },  
    previewType: { type: String, default: 'other' },  
    streamUrl: { type: String, default: '' },  
    textContent: { type: String, default: '' },  
    loading: { type: Boolean, default: false },  
    previewFile: { type: Object as PropType<FileItem | null>, default: null },  
    currentIndex: { type: Number, default: 0 },  
    total: { type: Number, default: 0 },  
    // 图片原生预览(uni.previewImage)使用的 URL 列表;为空时仅预览当前 streamUrl  
    urls: { type: Array as PropType<string[]>, default: () : string[] => [] as string[] }  
})  

const emit = defineEmits(['close', 'prev', 'next'])  

// 由 previewFile 派生文件名,统一做 null 兼容,模板直接引用  
const fileName = computed(() : string => props.previewFile != null ? props.previewFile!.name : '')  

const isMedia = computed(() : boolean => props.previewType == 'video' || props.previewType == 'audio')  

// 图片预览改用 uni-app x 自带的 uni.previewImage(原生全屏查看器,自带双指缩放、双击放大与左右滑动切换):  
// 组件打开时若是图片,直接拉起原生预览并关闭自定义浮层,避免出现双层预览界面  
watch(() : boolean => props.visible, (val : boolean) : void => {  
    if (!val || props.previewType != 'image') return  
    const urls = props.urls.length > 0 ? props.urls : [props.streamUrl]  
    // 用当前 streamUrl 在列表中定位索引,避免与媒体列表的显示序号混淆  
    let current = 0  
    for (let i = 0; i < urls.length; i++) {  
        if (urls[i] == props.streamUrl) {  
            current = i  
            break  
        }  
    }  
    uni.previewImage({  
        urls: urls,  
        current: current,  
        // 顶部数字指示器与循环预览:App 端生效;Web 端原生查看器暂不支持这两个参数,会自动忽略  
        indicator: 'number',  
        loop: true,  
    })  
    emit('close')  
})  

const onClose = () : void => { emit('close') }  
const onPrev = () : void => { emit('prev') }  
const onNext = () : void => { emit('next') }  

const videoFullscreen = ref(false)  
const onVideoFullscreenchange = (e : UniVideoFullScreenChangeEvent) : void => {  
    videoFullscreen.value = e.detail.fullScreen  
}  

const onVideoLongPress = () : void => {  
    const ctx = uni.createVideoContext('previewVideo')  
    if (ctx != null) {  
        ctx!.playbackRate(4)  
    }  
}  

const onVideoTouchEnd = () : void => {  
    const ctx = uni.createVideoContext('previewVideo')  
    if (ctx != null) {  
        ctx!.playbackRate(1)  
    }  
}  

const handleBack = () : boolean => {  
    if (videoFullscreen.value) {  
        const ctx = uni.createVideoContext('previewVideo')  
        if (ctx != null) {  
            ctx!.exitFullScreen()  
        }  
        videoFullscreen.value = false  
        return true  
    }  
    if (props.visible) {  
        emit('close')  
        return true  
    }  
    return false  
}  

defineExpose({ handleBack })  

</script>

<style>
.preview-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 100;
background-color: #000000;
display: flex;
flex-direction: column;
}

.preview-header {  
    flex-direction: row;  
    align-items: center;  
    padding: 8px 12px;  
    background-color: rgba(0, 0, 0, 0.6);  
    /* #ifdef APP */  
    padding-top: 32px;  
    /* #endif */  
}  

.preview-name {  
    flex: 1;  
    font-size: 15px;  
    color: #FFFFFF;  
    lines: 1;  
    text-overflow: ellipsis;  
}  

.preview-close {  
    font-size: 28px;  
    color: #FF5252;  
    width: 44px;  
    height: 44px;  
    text-align: center;  
}  

.preview-body {  
    flex: 1;  
    height: 0;  
    width: 100%;  
    overflow: hidden;  
    display: flex;  
    flex-direction: column;  
    align-items: center;  
    justify-content: center;  
}  

.preview-video {  
    width: 100%;  
    /* #ifdef H5 */  
    flex: 1;  
    /* #endif */  

    /* #ifdef APP */  
    height: 100%;  
    /* #endif */  
}  

.preview-text-scroll {  
    flex: 1;  
    width: 100%;  
    height: 0;  
    box-sizing: border-box;  
    padding: 16px;  
    background-color: #1A1A1A;  
}  

.preview-loading {  
    font-size: 14px;  
    color: #AAAAAA;  
    text-align: center;  
}  

.preview-text-content {  
    font-size: 14px;  
    color: #E0E0E0;  
}  

.preview-audio {  
    flex: 1;  
    align-items: center;  
    justify-content: center;  
    width: 100%;  
}  

.preview-audio-icon {  
    font-size: 64px;  
    margin-bottom: 12px;  
}  

.preview-audio-name {  
    font-size: 15px;  
    color: #FFFFFF;  
    margin-bottom: 16px;  
}  

.preview-audio-player {  
    width: 100%;  
    height: 60px;  
}  

.preview-other {  
    flex: 1;  
    align-items: center;  
    justify-content: center;  
    width: 100%;  
}  

.preview-other-name {  
    font-size: 16px;  
    color: #FFFFFF;  
    margin-bottom: 8px;  
}  

.preview-other-tip {  
    font-size: 13px;  
    color: #999999;  
    margin-bottom: 20px;  
}  

.preview-nav {  
    flex-direction: row;  
    justify-content: space-between;  
    padding: 12px 16px;  
}  

.preview-nav-btn {  
    font-size: 15px;  
    color: #FFFFFF;  
    padding: 10px 20px;  
}  

.preview-nav-count {  
    font-size: 12px;  
    color: #FFFFFF;  
    opacity: 0.85;  
    padding: 10px 0;  
}  

</style>

上面是我的源码,当点击全屏进行视频播放的时候,安卓端出现闪退。
hbuilderX 也存在报错,播放异常。下面是编辑器的报错信息。

18:56:56.524 at java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:760)
18:56:56.524 at java.util.LinkedHashMap$LinkedKeyIterator.next(LinkedHashMap.java:783)
18:56:56.524 at io.dcloud.uniapp.runtime.UniElementImpl.updateStyle$lambda$8(r8-map-id-30b99926c1bcbd04d3e0305c5e8709edfe6b947b61cf5180093a67349bbdca04:2)
18:56:56.524 at io.dcloud.uniapp.runtime.UniElementImpl.$r8$lambda$BE6uhWU3JspkG5-0lH7eGpderpU(Unknown Source:0)
18:56:56.525 at io.dcloud.uniapp.runtime.UniElementImpl$$ExternalSyntheticLambda1.invoke(D8$$SyntheticClass:0)
18:56:56.525 at io.dcloud.uniapp.util.AppTimeTrace$Companion.recordTimeMethod(r8-map-id-30b99926c1bcbd04d3e0305c5e8709edfe6b947b61cf5180093a67349bbdca04:6)
18:56:56.525 at io.dcloud.uniapp.runtime.UniElementImpl.updateStyle(r8-map-id-30b99926c1bcbd04d3e0305c5e8709edfe6b947b61cf5180093a67349bbdca04:5)
18:56:56.525 at io.dcloud.px.p3.a(r8-map-id-30b99926c1bcbd04d3e0305c5e8709edfe6b947b61cf5180093a67349bbdca04:217)
18:56:56.525 at io.dcloud.px.p3$$ExternalSyntheticLambda0.onLayoutChange(D8$$SyntheticClass:0)
18:56:56.525 at android.view.View.layout(View.java:23221)
18:56:56.525 at android.view.ViewGroup.layout(ViewGroup.java:6412)
18:56:56.525 at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
18:56:56.525 at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
18:56:56.526 at android.view.View.layout(View.java:23203)
18:56:56.526 at android.view.ViewGroup.layout(ViewGroup.java:6412)
18:56:56.526 at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
18:56:56.527 at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
18:56:56.527 at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
18:56:56.528 at android.view.View.layout(View.java:23203)
18:56:56.528 at android.view.ViewGroup.layout(ViewGroup.java:6412)
18:56:56.529 at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
18:56:56.529 at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
18:56:56.529 at android.view.View.layout(View.java:23203)
18:56:56.529 at android.view.ViewGroup.layout(ViewGroup.java:6412)
18:56:56.530 at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
18:56:56.530 at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
18:56:56.530 at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
18:56:56.531 at android.view.View.layout(View.java:23203)
18:56:56.531 at android.view.ViewGroup.layout(ViewGroup.java:6412)
18:56:56.531 at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
18:56:56.532 at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
18:56:56.532 at com.android.internal.policy.DecorView.onLayout(DecorView.java:802)
18:56:56.532 at android.view.View.layout(View.java:23203)
18:56:56.533 at android.view.ViewGroup.layout(ViewGroup.java:6412)
18:56:56.533 at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3756)
18:56:56.533 at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3212)
18:56:56.533 at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2186)
18:56:56.534 at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8833)
18:56:56.534 at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1047)
18:56:56.534 at android.view.Choreographer.doCallbacks(Choreographer.java:845)
18:56:56.535 at android.view.Choreographer.doFrame(Choreographer.java:780)
18:56:56.535 at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1032)
18:56:56.535 at android.os.Handler.handleCallback(Handler.java:938)
18:56:56.535 at android.os.Handler.dispatchMessage(Handler.java:99)
18:56:56.536 at android.os.Looper.loopOnce(Looper.java:201)
18:56:56.536 at android.os.Looper.loop(Looper.java:288)
18:56:56.536 at io.dcloud.px.c3.a(r8-map-id-30b99926c1bcbd04d3e0305c5e8709edfe6b947b61cf5180093a67349bbdca04:66)
18:56:56.536 at io.dcloud.px.c3$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
18:56:56.536 at android.os.Handler.handleCallback(Handler.java:938)
18:56:56.536 at android.os.Handler.dispatchMessage(Handler.java:99)
18:56:56.537 at android.os.Looper.loopOnce(Looper.java:201)
18:56:56.537 at android.os.Looper.loop(Looper.java:288)
18:56:56.537 at android.app.ActivityThread.main(ActivityThread.java:8085)
18:56:56.537 at java.lang.reflect.Method.invoke(Native Method)
18:56:56.538 at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
18:56:56.538 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1091)

2026-10-15 21:52 负责人:无 分享
已邀请:

要回复问题请先登录或注册