Android 音視頻開(kāi)發(fā) - VideoView

Android 音視頻開(kāi)發(fā) - VideoView

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

1: VideoView簡(jiǎn)介

VideoView是一個(gè)用于播放視頻的視圖組件,可以方便地在應(yīng)用程序中播放本地或網(wǎng)絡(luò)上的視頻文件镐确。

VideoView可以直接在布局文件中使用迈倍,也可以在代碼中動(dòng)態(tài)創(chuàng)建。

它封裝了MediaPlayer和SurfaceView,提供了簡(jiǎn)單的接口來(lái)控制視頻的播放和顯示坟瓢。

它提供了一系列方法來(lái)控制視頻的播放鳞仙、暫停、停止等操作峭判,并且支持全屏播放和視頻控制器的顯示开缎。

VideoView播放視頻非常簡(jiǎn)單,只需要指定視頻的URL或本地路徑.

2: 使用

以下是VideoView的簡(jiǎn)單使用:

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 設(shè)置視頻源

代碼如下:

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

除了setVideoPath外,我們還可以調(diào)用:

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

當(dāng)然不管是setVideoPath或者setVideoURI實(shí)際都是執(zhí)行的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;
}

可以看到實(shí)際上調(diào)用mMediaPlayer.start();另外設(shè)置了當(dāng)前的狀態(tài)為STATE_PLAYING.

這里直接調(diào)用了mMediaPlayer.start();那mMediaPlayer是什么時(shí)機(jī)初始化的呢?

查看源碼可以看到:

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,傳入U(xiǎn)ri,設(shè)置狀態(tài) STATE_PREPARING林螃。
  3. attachMediaController()綁定MediaPlayer與VideoView奕删。

最后openVideo()則是在setVideoURI(Uri uri, Map<String, String> headers)內(nèi)調(diào)用。

這樣其實(shí)已經(jīng)可以播放指定的視頻了疗认。

下面的方法可選完残。

2.4 MediaController控制器

MediaController是一個(gè)用于控制媒體播放器的視圖組件。

MediaController的使用步驟如下:

  1. 創(chuàng)建一個(gè)MediaController對(duì)象:MediaController mediaController = new MediaController(context);
  2. 將MediaController與媒體播放器組件關(guān)聯(lián):mediaController.setMediaPlayer(mediaPlayer);
  3. 將MediaController添加到布局中:layout.addView(mediaController);
videoView.setMediaController(new MediaController(this));
videoView.start().

直接調(diào)用setMediaController,運(yùn)行后我們可以看到與之前直接調(diào)用start()的區(qū)別就是多了個(gè)控制器的顯示横漏。其中包含一組常用的媒體控制按鈕谨设,如播放/暫停、快進(jìn)/快退缎浇、前進(jìn)/后退等扎拣,并且可以與MediaPlayer或VideoView等媒體播放器組件進(jìn)行關(guān)聯(lián).

我們可以看下源碼:

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

可以看到做的操作如下:

  1. 如果存在mMediaController,則調(diào)用hide方法素跺。
  2. 對(duì)mMediaController賦值
  3. attachMediaController

本文由博客一文多發(fā)平臺(tái) OpenWrite 發(fā)布二蓝!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市指厌,隨后出現(xiàn)的幾起案子刊愚,更是在濱河造成了極大的恐慌,老刑警劉巖踩验,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鸥诽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡晰甚,警方通過(guò)查閱死者的電腦和手機(jī)衙传,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)厕九,“玉大人蓖捶,你說(shuō)我怎么就攤上這事”庠叮” “怎么了俊鱼?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵刻像,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我并闲,道長(zhǎng)细睡,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任帝火,我火速辦了婚禮溜徙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘犀填。我一直安慰自己蠢壹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布九巡。 她就那樣靜靜地躺著图贸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪冕广。 梳的紋絲不亂的頭發(fā)上疏日,一...
    開(kāi)封第一講書(shū)人閱讀 49,784評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音撒汉,去河邊找鬼沟优。 笑死,一個(gè)胖子當(dāng)著我的面吹牛睬辐,可吹牛的內(nèi)容都是我干的净神。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼溉委,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了爱榕?” 一聲冷哼從身側(cè)響起瓣喊,我...
    開(kāi)封第一講書(shū)人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎黔酥,沒(méi)想到半個(gè)月后藻三,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡跪者,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年棵帽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片渣玲。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逗概,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出忘衍,到底是詐尸還是另有隱情逾苫,我是刑警寧澤卿城,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站铅搓,受9級(jí)特大地震影響瑟押,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜星掰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一多望、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧氢烘,春花似錦怀偷、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至黎棠,卻和暖如春晋渺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背脓斩。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工木西, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人随静。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓八千,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親燎猛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子恋捆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容