首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android VideoView 連續播放多個視頻:OnCompletionListener 實現播放隊列

     編輯:程式設計綜合問答

Android VideoView 單次播放簡單,但需順序播放多個視頻時,需監聽播放完成事件,在回調中啟動下一個視頻。核心是實現 MediaPlayer.OnCompletionListener。

基礎實現:固定數組順序播放

public class VideoPlaylistActivity extends AppCompatActivity {
    private VideoView videoView;
    private int[] videoResIds = {R.raw.video1, R.raw.video2, R.raw.video3, R.raw.video4};
    private int currentIndex = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video_playlist);
        videoView = findViewById(R.id.videoView);
        playNext();
    }

    private void playNext() {
        if (currentIndex >= videoResIds.length) {
            // 播放結束,可選:循環、跳轉、釋放資源
            currentIndex = 0; // 循環播放
            // finish(); // 或結束 Activity
        }
        String uri = "android.resource://" + getPackageName() + "/" + videoResIds[currentIndex];
        videoView.setVideoURI(Uri.parse(uri));
        videoView.setOnCompletionListener(mp -> {
            currentIndex++;
            playNext();
        });
        videoView.start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (videoView != null) {
            videoView.stopPlayback(); // 釋放 MediaPlayer 資源
        }
    }
}

進階:支援網絡視頻、錯誤處理、載入指示器

public class AdvancedVideoPlaylistActivity extends AppCompatActivity {
    private VideoView videoView;
    private ProgressBar loadingBar;
    private List videoUrls = Arrays.asList(
        "https://example.com/video1.mp4",
        "https://example.com/video2.mp4",
        "https://example.com/video3.mp4"
    );
    private int currentIndex = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_advanced_playlist);
        videoView = findViewById(R.id.videoView);
        loadingBar = findViewById(R.id.loadingBar);
        
        videoView.setOnPreparedListener(mp -> loadingBar.setVisibility(View.GONE));
        videoView.setOnErrorListener((mp, what, extra) -> {
            loadingBar.setVisibility(View.GONE);
            Toast.makeText(this, "播放失敗: " + what, Toast.LENGTH_SHORT).show();
            playNext(); // 跳過錯誤視頻
            return true; // 已處理錯誤
        });
        videoView.setOnCompletionListener(mp -> playNext());
        
        playNext();
    }

    private void playNext() {
        if (currentIndex >= videoUrls.size()) {
            finish(); // 播放完畢
            return;
        }
        loadingBar.setVisibility(View.VISIBLE);
        videoView.setVideoPath(videoUrls.get(currentIndex++));
        videoView.start();
    }
}

XML 佈局

<FrameLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/black">

    <VideoView
        android:id="@+id/videoView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center" />

    <ProgressBar
        android:id="@+id/loadingBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:visibility="gone" />
</FrameLayout>

關鍵注意事項

問題解決方案
視頻切換黑屏/卡頓預加載下一個視頻:用 MediaPlayer 直接管理、或雙 VideoView 交換
內存洩漏/ANRonDestroy 中調用 stopPlayback(),釋放 MediaPlayer
網絡視頻緩衝久顯示 ProgressBar,setOnPreparedListener 隱藏
編碼格式不支援捕獲 OnErrorListener,記錄日誌、跳過或降級
全屏/旋轉處理鎖定橫屏 setRequestedOrientation,或用 ExoPlayer 支援更好

現代替代方案:ExoPlayer / Media3

Google 官方推薦 Media3 ExoPlayer,支援:

  • 自適應碼率 (DASH/HLS)
  • 媒體會話、離線下載、廣告插入
  • ConcatenatingMediaSource 原生支援無縫拼接播放
// ExoPlayer 播放列表
MediaItem[] items = urls.stream().map(MediaItem::fromUri).toArray(MediaItem[]::new);
ConcatenatingMediaSource playlist = new ConcatenatingMediaSource(
    Arrays.stream(items).map(item -> new ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(item)).toArray(MediaSource[]::new)
);
player.setMediaSource(playlist);
player.prepare();
player.playWhenReady = true;

簡單需求用 VideoView 足夠;複雜場景(直播、DRM、廣告、離線)請直接上 Media3 ExoPlayer。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved