首页 > 其他分享 >Android 音视频开发 - VideoView

Android 音视频开发 - VideoView

时间:2024-04-07 17:11:59浏览次数:16  
标签:mMediaPlayer setVideoURI MediaController 音视频 start STATE Android VideoView

Android 音视频开发 - VideoView

本篇文章主要介绍下Android 中的VideoView.

1: VideoView简介

VideoView是一个用于播放视频的视图组件,可以方便地在应用程序中播放本地或网络上的视频文件。

VideoView可以直接在布局文件中使用,也可以在代码中动态创建。

它封装了MediaPlayer和SurfaceView,提供了简单的接口来控制视频的播放和显示。

它提供了一系列方法来控制视频的播放、暂停、停止等操作,并且支持全屏播放和视频控制器的显示。

VideoView播放视频非常简单,只需要指定视频的URL或本地路径.

2: 使用

以下是VideoView的简单使用:

2.1 布局

在XML布局文件中添加VideoView组件.

<VideoView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    android:id="@+id/videoview"
    />

2.2 设置视频源

代码如下:

videoView = findViewById(R.id.videoview);
videoView.setVideoPath("sdcard/test.mp4");

除了setVideoPath外,我们还可以调用:

  1. setVideoURI(Uri uri)
  2. setVideoURI(Uri uri, Map<String, String> headers)

当然不管是setVideoPath或者setVideoURI实际都是执行的setVideoURI(Uri uri, Map<String, String> headers).

源码如下:

/**
 * Sets video path.
 *
 * @param path the path of the video.
 */
public void setVideoPath(String path) {
    setVideoURI(Uri.parse(path));
}

/**
 * Sets video URI.
 *
 * @param uri the URI of the video.
 */
public void setVideoURI(Uri uri) {
    setVideoURI(uri, null);
}

2.3 播放视频

videoView.start();

我们可以看下start()的源码:

@Override
public void start() {
    if (isInPlaybackState()) {
        mMediaPlayer.start();
        mCurrentState = STATE_PLAYING;
    }
    mTargetState = STATE_PLAYING;
}

可以看到实际上调用mMediaPlayer.start();另外设置了当前的状态为STATE_PLAYING.

这里直接调用了mMediaPlayer.start();那mMediaPlayer是什么时机初始化的呢?

查看源码可以看到:

private void openVideo() {
    if (mUri == null || mSurfaceHolder == null) {
        // not ready for playback just yet, will try again later
        return;
    }
    // we shouldn't clear the target state, because somebody might have
    // called start() previously
    release(false);

    if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
        // TODO this should have a focus listener
        mAudioManager.requestAudioFocus(null, mAudioAttributes, mAudioFocusType, 0 /*flags*/);
    }

    try {
        mMediaPlayer = new MediaPlayer();
        // TODO: create SubtitleController in MediaPlayer, but we need
        // a context for the subtitle renderers
        final Context context = getContext();
        final SubtitleController controller = new SubtitleController(
                context, mMediaPlayer.getMediaTimeProvider(), mMediaPlayer);
        controller.registerRenderer(new WebVttRenderer(context));
        controller.registerRenderer(new TtmlRenderer(context));
        controller.registerRenderer(new Cea708CaptionRenderer(context));
        controller.registerRenderer(new ClosedCaptionRenderer(context));
        mMediaPlayer.setSubtitleAnchor(controller, this);

        if (mAudioSession != 0) {
            mMediaPlayer.setAudioSessionId(mAudioSession);
        } else {
            mAudioSession = mMediaPlayer.getAudioSessionId();
        }
        mMediaPlayer.setOnPreparedListener(mPreparedListener);
        mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
        mMediaPlayer.setOnCompletionListener(mCompletionListener);
        mMediaPlayer.setOnErrorListener(mErrorListener);
        mMediaPlayer.setOnInfoListener(mInfoListener);
        mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
        mCurrentBufferPercentage = 0;
        mMediaPlayer.setDataSource(mContext, mUri, mHeaders);
        mMediaPlayer.setDisplay(mSurfaceHolder);
        mMediaPlayer.setAudioAttributes(mAudioAttributes);
        mMediaPlayer.setScreenOnWhilePlaying(true);
        mMediaPlayer.prepareAsync();

        for (Pair<InputStream, MediaFormat> pending: mPendingSubtitleTracks) {
            try {
                mMediaPlayer.addSubtitleSource(pending.first, pending.second);
            } catch (IllegalStateException e) {
                mInfoListener.onInfo(
                        mMediaPlayer, MediaPlayer.MEDIA_INFO_UNSUPPORTED_SUBTITLE, 0);
            }
        }

        // we don't set the target state here either, but preserve the
        // target state that was there before.
        mCurrentState = STATE_PREPARING;
        attachMediaController();
    } catch (IOException ex) {
        Log.w(TAG, "Unable to open content: " + mUri, ex);
        mCurrentState = STATE_ERROR;
        mTargetState = STATE_ERROR;
        mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
        return;
    } catch (IllegalArgumentException ex) {
        Log.w(TAG, "Unable to open content: " + mUri, ex);
        mCurrentState = STATE_ERROR;
        mTargetState = STATE_ERROR;
        mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
        return;
    } finally {
        mPendingSubtitleTracks.clear();
    }
}

可以看到openVideo()

  1. release()方法释放正在播放的视频.
  2. 初始化mMediaPlayer,传入Uri,设置状态 STATE_PREPARING。
  3. attachMediaController()绑定MediaPlayer与VideoView。

最后openVideo()则是在setVideoURI(Uri uri, Map<String, String> headers)内调用。

这样其实已经可以播放指定的视频了。

下面的方法可选。

2.4 MediaController控制器

MediaController是一个用于控制媒体播放器的视图组件。

MediaController的使用步骤如下:

  1. 创建一个MediaController对象:MediaController mediaController = new MediaController(context);
  2. 将MediaController与媒体播放器组件关联:mediaController.setMediaPlayer(mediaPlayer);
  3. 将MediaController添加到布局中:layout.addView(mediaController);
videoView.setMediaController(new MediaController(this));
videoView.start().

直接调用setMediaController,运行后我们可以看到与之前直接调用start()的区别就是多了个控制器的显示。其中包含一组常用的媒体控制按钮,如播放/暂停、快进/快退、前进/后退等,并且可以与MediaPlayer或VideoView等媒体播放器组件进行关联.

我们可以看下源码:

public void setMediaController(MediaController controller) {
    if (mMediaController != null) {
        mMediaController.hide();
    }
    mMediaController = controller;
    attachMediaController();
}

可以看到做的操作如下:

  1. 如果存在mMediaController,则调用hide方法。
  2. 对mMediaController赋值
  3. attachMediaController

本文由博客一文多发平台 OpenWrite 发布!

标签:mMediaPlayer,setVideoURI,MediaController,音视频,start,STATE,Android,VideoView
From: https://www.cnblogs.com/zhjing/p/18119450

相关文章

  • uni-app项目运行到Android Studio模拟器
    1.启动模拟器①可以在AndroidStudio中打开安装好的模拟器②也可以不通过AndroidStudio,使用指令直接启动模拟器首先找到AndroidStudio模拟器安装位置,一般如下图:AppData文件夹默认隐藏,需要设置可见。然后再该路径下打开cmd控制台,输入指令emulator.exe-list-avds可......
  • Android音视频开发 - MediaMetadataRetriever 相关
    Android音视频开发-MediaMetadataRetriever相关MediaMetadataRetriever是android中用于从媒体文件中提取元数据新的类.可以获取音频,视频和图像文件的各种信息,如时长,标题,封面等.1:初始化对象privateMediaMetadataRetrievermediaMetadataRetriever=newMediaMetadat......
  • Android查找启动类名和启动方法
    1.将APK安装到手机上2.连接WIFI,使手机和电脑在同一个局域网内,查看手机IP3.连接手机,命令:adbconnect手机IP地址4.查看APK启动类名,命令:abddumpsyspackage包名如图:5.启动命令:adbshellamstart-n类名备注:如果提示adb命令不存在,可以选择以下两种处理方式1.直接......
  • android studio汉化
    汉化androidstudio开发软件由于androidstudio默认的插件商店里面没有插件Chinese​(Simplified)​LanguagePack,所以需要手动下载插件并且放到指定位置。非常简单。步骤到JetBrains的插件网站搜索Chinese​(Simplified)​LanguagePack/中文语言包。在插件页面中找到......
  • AndroidStudio学习记录(4):单选按钮控件RadioButton
    用于应用二选一等多选选项的设置<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical">&l......
  • Android车载设备开发相关名词介绍
    一、通讯相关1、ECALL        如遭遇紧急情况,用户可按下该键以最高优先级接通呼叫中心,人工坐席将同时获取客户车辆的重要数据并协助驾驶员脱离危险。实现原理        E-Call的核心思想是利用车载卫星定位系统获取车辆的位置信息,在事故发生后,由传感器检测......
  • Android Binder——Java服务注册(九)
           对于Java端使用Binder服务,主要就是注册服务和获取服务,入口都是通过ServiceManager.java中的对应方法实现。这里我们就先介绍一下Java注册Binder服务的流程。一、ServiceManager代理       无论是ServiceManager.addService()还是Service......
  • 19.14.Android四大组件之一活动单元Activity 下
    任务栈和启动模式Fragment1.关于任务栈和启动模式(了解)Android中的任务栈压栈和出栈即开启的往里面压位于最上面找哪个上面的被弹出启动模式四种模式:standard每启动一个Activity就创建一个实例singleTop模式判断是否存在Activity位于栈顶如果存在直接复......
  • android 【存储相关】preserveLegacyExternalStorage,requestLegacyExternalStorage
    这两个属性是与Android10(API级别29)及更高版本中的外部存储访问权限限制相关的属性。android:preserveLegacyExternalStorage="true"这个属性用于在Android10及更高版本上保留旧版的外部存储访问模式。在Android10及更高版本中,默认情况下,应用程序只能访问自己......
  • Android Graphics 多屏同显/异显 - C++示例程序(标准版)
    ”为了理解Android多屏同显/异显的基本原理,我们将从NativeLevel入手,基于GraphicsAPIs写作一个简单的C++版本的多屏显示互动的演示程序。通过这个程序我们将了解常用的多屏显示相关的接口的使用方法。“  01多屏显示C++示例概况 源码下载请查看文章末尾源码下载方......