睿诚科技协会

android 播放 网络视频

目录

  1. 最简单的方式:使用 VideoView (适合快速开发)

    android 播放 网络视频-图1
    (图片来源网络,侵删)
    • 简介
    • 布局文件 (activity_main.xml)
    • Activity 代码 (MainActivity.kt)
    • 重要:网络权限配置
    • 优缺点分析
  2. 最专业的方式:使用 ExoPlayer (Google 官方推荐)

    • 简介
    • 添加依赖
    • 布局文件 (activity_main.xml)
    • Activity 代码 (MainActivity.kt)
    • ExoPlayer 核心概念
    • 优缺点分析
  3. 进阶与最佳实践

    • 横竖屏切换与全屏
    • 处理网络错误和加载状态
    • 自定义 UI 控件
    • 硬解码与性能优化
    • 使用缓存库 (如 AndroidVideoCache)

最简单的方式:使用 VideoView

VideoView 是 Android SDK 提供的一个高级组件,它封装了 MediaPlayer,使用起来非常简单,适合播放简单的、不需要复杂控制的视频。

简介

VideoView 负责显示视频,而 MediaController 是一个标准的控制器,提供了播放/暂停、进度条、快进快退等控件。

android 播放 网络视频-图2
(图片来源网络,侵删)

布局文件 (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <VideoView
        android:id="@+id/videoView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true" />
</RelativeLayout>

Activity 代码 (MainActivity.kt)

import android.net.Uri
import android.os.Bundle
import android.widget.MediaController
import android.widget.VideoView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val videoView = findViewById<VideoView>(R.id.videoView)
        // 1. 设置视频源的 URL
        // 注意:请替换为你的实际视频 URL
        val videoUrl = "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4"
        // 2. 创建 MediaController 并附加到 VideoView
        val mediaController = MediaController(this)
        mediaController.setAnchorView(videoView)
        videoView.setMediaController(mediaController)
        // 3. 设置视频 URI
        videoView.setVideoURI(Uri.parse(videoUrl))
        // 4. 开始播放
        videoView.start()
        // 可选:监听播放完成事件
        videoView.setOnCompletionListener {
            // 播放完成后的操作
        }
    }
}

重要:网络权限配置

AndroidManifest.xml 中必须添加网络访问权限,否则无法播放网络视频。

<manifest ...>
    <!-- 必须添加的权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <application ...>
        ...
    </application>
</manifest>

优缺点分析

  • 优点:
    • 简单易用: 几行代码就能实现播放功能。
    • 自带控制器: MediaController 提供了基本的播放控制。
  • 缺点:
    • 功能有限: 无法实现高度自定义的 UI。
    • 性能一般: 在处理高分辨率或复杂格式的视频时,性能可能不如 ExoPlayer
    • 扩展性差: 难以添加高级功能,如画中画、多清晰度切换等。

最专业的方式:使用 ExoPlayer

ExoPlayer 是 Google 官方推出的媒体播放器,它是基于 MediaPlayerMediaCodec 构建的,它功能强大、性能优异、高度可定制,是现代 Android 应用的首选。

简介

ExoPlayer 采用了组件化的设计,核心播放器只负责播放逻辑,而渲染、控制、数据加载等功能都由不同的组件提供,开发者可以根据需要自由组合。

添加依赖

app/build.gradle 文件的 dependencies 代码块中添加 ExoPlayer 依赖。

android 播放 网络视频-图3
(图片来源网络,侵删)
dependencies {
    // ExoPlayer 核心库
    implementation "androidx.media3:media3-exoplayer:1.3.1"
    // ExoPlayer 媒体数据加载器
    implementation "androidx.media3:media3-exoplayer-hls:1.3.1" // 如果播放 HLS (m3u8) 格式视频,需要这个
    // ExoPlayer UI 组件
    implementation "androidx.media3:media3-ui:1.3.1"
}

注意: HLS 是一种常见的网络视频流协议(常用于直播和点播),如果你的视频是 .m3u8 结尾的,必须添加 media3-exoplayer-hls 依赖。

布局文件 (activity_main.xml)

ExoPlayer 提供了一个 PlayerView 组件,它集成了 Surface(用于渲染视频)和一套标准的播放控制 UI。

<?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=".MainActivity">
    <com.google.android.exoplayer2.ui.PlayerView
        android:id="@+id/player_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:use_controller="true"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Activity 代码 (MainActivity.kt)

import android.net.Uri
import android.os.Bundle
import android.view.View
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.ui.PlayerView
class MainActivity : AppCompatActivity() {
    private lateinit var player: ExoPlayer
    private lateinit var playerView: PlayerView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        playerView = findViewById(R.id.player_view)
        // 1. 创建 ExoPlayer 实例
        player = ExoPlayer.Builder(this).build().also { exoPlayer ->
            // 2. 将 PlayerView 的播放器设置为我们创建的 ExoPlayer
            playerView.player = exoPlayer
            // 3. 创建 MediaItem 并设置给播放器
            // 注意:请替换为你的实际视频 URL
            val mediaItem = MediaItem.fromUri("https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4")
            exoPlayer.setMediaItem(mediaItem)
            // 4. 准备并播放
            exoPlayer.prepare()
            exoPlayer.play()
        }
        // 可选:监听播放状态变化
        player.addListener(object : Player.Listener {
            override fun onPlaybackStateChanged(playbackState: Int) {
                when (playbackState) {
                    Player.STATE_BUFFERING -> {
                        // 正在缓冲,可以显示加载动画
                        findViewById<View>(R.id.loading_indicator).visibility = View.VISIBLE
                    }
                    Player.STATE_READY -> {
                        // 准备就绪,可以隐藏加载动画
                        findViewById<View>(R.id.loading_indicator).visibility = View.GONE
                    }
                    Player.STATE_ENDED -> {
                        // 播放完成
                    }
                }
            }
        })
    }
    override fun onStart() {
        super.onStart()
        // 当 Activity 可见时,开始播放
        if (playerView.player != null) {
            playerView.player!!.playWhenReady = true
        }
    }
    override fun onStop() {
        super.onStop()
        // 当 Activity 不可见时,暂停播放以节省资源
        if (playerView.player != null) {
            playerView.player!!.playWhenReady = false
        }
    }
    override fun onDestroy() {
        super.onDestroy()
        // 释放
分享:
扫描分享到社交APP
上一篇
下一篇