ED_Sunny小王 2023-07-06 21:44 采纳率: 33.3%
浏览 24
已结题

关于Android开发获取视频流程序闪退问题,如何解决?

在进行Andriod开发过程中:使用libvlc获取远程视频流,通过搜索框输入视频地址获取视频流,第一次获取视频正常,第二次输入地址后直接闪退,并报如下错误:

2023-07-06 21:31:10.380 19206-19206/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: org.videolan.libvlctest, PID: 19206
    java.lang.IllegalStateException: Can't set view when already attached. Current state: 2, mSurfaces[ID_VIDEO]: org.videolan.libvlc.AWindow$SurfaceHelper@ef65577 / Surface(name=null)/@0xdf6d5e4, mSurfaces[ID_SUBTITLES]: null / null
        at org.videolan.libvlc.AWindow.ensureInitState(AWindow.java:227)
        at org.videolan.libvlc.AWindow.setView(AWindow.java:233)
        at org.videolan.libvlc.AWindow.setVideoView(AWindow.java:268)
        at org.videolan.libvlc.VideoHelper.attachViews(VideoHelper.java:89)
        at org.videolan.libvlc.MediaPlayer.attachViews(MediaPlayer.java:605)
        at org.videolan.libvlctest.MainActivity$1.onQueryTextSubmit(MainActivity.java:84)
        at android.widget.SearchView.onSubmitQuery(SearchView.java:1302)
        at android.widget.SearchView.access$1000(SearchView.java:101)
        at android.widget.SearchView$7.onEditorAction(SearchView.java:1279)
        at android.widget.TextView.onEditorAction(TextView.java:7070)
        at com.android.internal.widget.EditableInputConnection.performEditorAction(EditableInputConnection.java:138)
        at com.android.internal.view.IInputConnectionWrapper.executeMessage(IInputConnectionWrapper.java:363)
        at com.android.internal.view.IInputConnectionWrapper$MyHandler.handleMessage(IInputConnectionWrapper.java:93)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:236)
        at android.app.ActivityThread.main(ActivityThread.java:8168)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:656)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:967)

MainActivity.java代码:

package org.videolan.libvlctest;

import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.SearchView;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import org.videolan.libvlc.LibVLC;
import org.videolan.libvlc.Media;
import org.videolan.libvlc.MediaPlayer;
import org.videolan.libvlc.util.VLCVideoLayout;

import java.io.IOException;
import java.util.ArrayList;

//使用中libvlc中的MediaPlayer类+布局VLCVideoLayout 接收rtsp视频流

public class MainActivity extends AppCompatActivity  {
    //不使用TextureView渲染视频
    private static final boolean USE_TEXTURE_VIEW = false;

    //不显示视频流字幕
    private static final boolean ENABLE_SUBTITLES = false;

    private static final String ASSET_FILENAME = "bbb.m4v";

    private VLCVideoLayout mVideoLayout = null;
    private LibVLC mLibVLC = null;
    private MediaPlayer mMediaPlayer = null;

    private Button playButton = null;
//    private Button pauseButton = null;

    private SearchView searchView = null;

    private TextView GetVedioDes = null;

    //创建活动
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final ArrayList<String> args = new ArrayList<>();

        //开启调试选项,以在控制台输出详细的控制信息
        args.add("-vvv");
        mLibVLC = new LibVLC(this, args);

        mMediaPlayer = new MediaPlayer(mLibVLC);
        mVideoLayout = findViewById(R.id.video_layout);

        //播放按钮(由于搜索后即是播放,后续该按钮对应事件注释掉了)
        playButton = findViewById(R.id.play_button);

        //暂停按钮(未用)
//        pauseButton = findViewById(R.id.pause_button);

        searchView = findViewById(R.id.search_view);
        GetVedioDes = findViewById(R.id.get_vedio_des);
    }

    //开启活动
    @Override
    protected void onStart() {
        super.onStart();
        //设置搜索文本监听
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            //当点击键盘中搜索按钮时触发该方法
            @Override
            public boolean onQueryTextSubmit(String query) {
                if(mMediaPlayer.isPlaying()){
                   mMediaPlayer.stop();
                }

                //绑定布局mVideoLayout,不监听布局变化null,是否开启字幕ENABLE_SUBTITLES,是否使用渲染视频TextureView
                mMediaPlayer.attachViews(mVideoLayout, null, ENABLE_SUBTITLES, USE_TEXTURE_VIEW);

                // 根据输入网址播放对应视频流
                final Media media = new Media(mLibVLC, Uri.parse(query));
                mMediaPlayer.setMedia(media);
                media.release();
                mMediaPlayer.play();
                GetVedioDes.setText("获取视频流:"+query);
                return true;

            }

            //当搜索内容改变时触发该方法
            @Override
            public boolean onQueryTextChange(String newText) {
              return false;
            }
        });
    }

    //停止活动
    @Override
    protected void onStop() {
        super.onStop();
        mMediaPlayer.stop();
        mMediaPlayer.detachViews();
    }

    //销毁活动,释放资源
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(mMediaPlayer.isPlaying()){
            mMediaPlayer.stop();
        }
        mMediaPlayer.release();
        mLibVLC.release();
    }
}

布局文件activity_main.xml:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:keepScreenOn="true"
    android:background="@android:color/background_dark"
    >
    <!-- 搜索框 -->
    <SearchView
        android:id="@+id/search_view"
        android:background="@drawable/search_view"
        android:layout_width="370dp"
        android:layout_marginTop="10dp"
        android:layout_gravity="center_horizontal"
        android:layout_height="wrap_content"
        android:iconifiedByDefault="false"
        android:queryHint="请输入视频地址"
        android:elevation="100dp"/>
    
    <!-- 文字提示 -->
    <TextView
        android:id="@+id/get_vedio_des"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="70dp"
        android:layout_marginStart="20dp"
        android:text="@string/vedio_des"
        android:textSize="15sp"
        android:textColor="#fff"
        android:elevation="100dp"/>

    <!-- 视频流显示  -->
    <org.videolan.libvlc.util.VLCVideoLayout
        android:id="@+id/video_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="false">
    </org.videolan.libvlc.util.VLCVideoLayout>

    <!-- 播放按钮 -->
    <Button
        android:id="@+id/play_button"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="600dp"
        android:background="@drawable/play_button_selector"
        android:textAllCaps="false"
        android:text="@string/play_btn_des" />
</FrameLayout>
  • 写回答

1条回答 默认 最新

  • 故事不长丨 2023-07-07 09:56
    关注

    根据您提供的代码和错误信息,问题原因是在多次调用attachViews()方法后导致崩溃。这是由于每次在第二次搜索并尝试播放视频时,您都已经绑定了一个Surface视图,无法在已经连接的状态下重新设置一个新的View。

    解决方案是在每次开始播放视频之前,确保将原始的Surface视图与MediaPlayer分离。您可以在onQueryTextSubmit()方法中添加一行代码来实现:

    // 当点击键盘中搜索按钮时触发该方法
    @Override
    public boolean onQueryTextSubmit(String query) {
        if (mMediaPlayer.isPlaying()) {
           mMediaPlayer.stop();
        }
    
        // 分离现有的Surface视图和MediaPlayer
        mMediaPlayer.detachViews();
    
        // 绑定布局mVideoLayout,不监听布局变化null,是否开启字幕ENABLE_SUBTITLES, 是否使用渲染视频TextureView
        mMediaPlayer.attachViews(mVideoLayout, null, ENABLE_SUBTITLES, USE_TEXTURE_VIEW);
    
        // 根据输入网址播放对应视频流
        final Media media = new Media(mLibVLC, Uri.parse(query));
        mMediaPlayer.setMedia(media);
        media.release();
        mMediaPlayer.play();
        GetVedioDes.setText("获取视频流:" + query);
        return true;
    }
    

    通过使用mMediaPlayer.detachViews()方法分离原始的Surface视图和MediaPlayer,以确保每次播放新视频时都会正确重新绑定所需的View。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 7月15日
  • 已采纳回答 7月7日
  • 创建了问题 7月6日

悬赏问题

  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下
  • ¥15 setInterval 页面闪烁,怎么解决
  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动
  • ¥20 对于工程问题的非线性数学模型进行线性化
  • ¥15 Mirare PLUS 进行密钥认证?(详解)
  • ¥15 物体双站RCS和其组成阵列后的双站RCS关系验证
  • ¥20 想用ollama做一个自己的AI数据库