在进行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>