Android MediaPlayer 基礎簡介

来源:https://www.cnblogs.com/rustfisher/archive/2019/09/20/11554873.html
-Advertisement-
Play Games

本文鏈接: "Android MediaPlayer 基礎簡介" 簡單介紹MediaPlayer的基本概念,狀態,常用的方法與監聽器。 什麼是MediaPlayer MediaPlayer類可以用來播放音視頻文件,或者是音頻流。開發者可以用它來播放本地音頻,或者是網路線上音頻。 MediaPlaye ...


本文鏈接: Android MediaPlayer 基礎簡介

簡單介紹MediaPlayer的基本概念,狀態,常用的方法與監聽器。

什麼是MediaPlayer

MediaPlayer類可以用來播放音視頻文件,或者是音頻流。開發者可以用它來播放本地音頻,或者是網路線上音頻。

MediaPlayer屬於android.media包。

MediaPlayer的狀態

播放控制由狀態機控制。在日常生活中,我們常見的音頻狀態有播放中,暫停,停止,緩衝等等。
MediaPlayer的狀態有如下幾種:

  • Idle
  • End
  • Error
  • Initialized
  • Preparing
  • Prepared
  • Started
  • Stopped
  • Paused
  • PlaybackCompleted

狀態的切換參考官方圖例。
這裡稍微解釋一下狀態轉換圖片。橢圓代表MediaPlayer可能停留的狀態。橢圓之間的箭頭表示方法調用,狀態切換的方向。單箭頭表示方法同步調用,雙箭頭表示非同步調用。

mediaplayer_state_diagram

從圖中我們可以看出狀態切換的路徑和涉及到的方法。

Idle與End狀態

當new一個MediaPlayer或者調用了reset方法,當前MediaPlayer會處於Idle狀態。調用release後,會處於End狀態。在這2個狀態之間的狀態可以看做是MediaPlayer對象的生命周期。

在新創建MediaPlayer和調用reset的MediaPlayer之間有一些細微的差別。
這兩種情況都處於Idle狀態,調用 getCurrentPosition(), getDuration(), getVideoHeight(), getVideoWidth(), setAudioAttributes(android.media.AudioAttributes), setLooping(boolean), setVolume(float, float), pause(), start(), stop(), seekTo(long, int), prepare() 或 prepareAsync()方法都會拋出錯誤,如果是新實例化的MediaPlayer,不會回調 OnErrorListener.onError();但如果是reset後的MediaPlayer,會回調 OnErrorListener.onError()並且轉換到Error狀態。

如果MediaPlayer對象不再使用了,立即調用release()方法,釋放內部播放器占用的資源。這些資源可能是唯一的,比如硬體加速組件。如果調用release失敗,可能會引起一連串的MediaPlayer實例失效。當MediaPlayer處於End狀態,它就不能再轉移到其它狀態了。

new一個MediaPlayer,處於Idle狀態。如果用create方法創建實例,當創建完成時處於Prepared狀態。

發生錯誤

一些情形可能會讓MediaPlayer操作失敗,比如不支持的音視頻格式,解析度過高,網路超時等等。
因此在這些情形下錯誤處理和恢復非常重要。有時候編程錯誤也會導致MediaPlayer操作錯誤。
開發者可以設置錯誤監聽器setOnErrorListener(android.media.MediaPlayer.OnErrorListener)。當錯誤發生時,會調用用戶實現的OnErrorListener.onError()方法。

不管有沒有設置監聽器,錯誤發生時MediaPlayer會進入Error狀態。

為了重覆使用同一個MediaPlayer對象,可以使用reset()方法把它從Error狀態恢復到Idle狀態。
設置錯誤監聽器OnErrorListener是一個好的編程習慣。開發者可以監聽到播放引擎的錯誤通知。
有時候會拋出IllegalStateException異常,比如在錯誤的狀態調用了prepare(), prepareAsync()方法,或是setDataSource方法。

設置音源 setDataSource

調用setDataSource(java.io.FileDescriptor), 或者 setDataSource(java.lang.String), 或者 setDataSource(android.content.Context, android.net.Uri), 或者 setDataSource(java.io.FileDescriptor, long, long), 或者 setDataSource(android.media.MediaDataSource) 可以將MediaPlayer的狀態從Idle轉到Initialized狀態。
如果在Idle狀態之外的狀態調用了setDataSource(),會拋出IllegalStateException異常。
開發者應該留意setDataSource方法拋出的IllegalArgumentException和IOException異常。

播放音頻前必須在Prepared狀態

MediaPlayer在開始播放音頻前必須處於Prepared狀態。

MediaPlayer有同步和非同步2種方式來進入Prepared狀態。如果是非同步的方式,會先轉到Preparing狀態,再轉到Prepared狀態。
當準備完成時,內部的播放引擎會回調用戶之前設置的OnPreparedListener的onPrepared()方法。

開發者必須註意的是,Preparing狀態是一個過渡狀態(transient state)。

處於Prepared狀態時,可以通過相對應的方法設置音量,屏幕常亮,播放迴圈等。

開始播放

播放音頻必須調用start()方法。調用start()返回成功後,MediaPlayer處於Started狀態。
可以通過isPlaying()來判斷當前是否在Started狀態。

如果開發者設置了OnBufferingUpdateListener,Android內部播放器會向外傳遞buffer信息。

如果當前處於Started狀態,再調用start()方法沒有效果。

暫停播放與繼續播放

音頻可以被暫停播放和繼續播放,也可以調整播放的位置。通過pause()方法來暫停音頻播放。
成功調用pause()方法後,MediaPlayer進入Paused狀態。
應當註意的是,MediaPlayer在Started狀態與Paused狀態之間切換是非同步的。播放音頻流的時候,這個轉換過程可能會需要幾秒鐘。

MediaPlayer暫停時,start()方法可以從暫停的位置繼續播放。成功調用start方法後會進入Started狀態。

處於Paused狀態時,調用pause()方法沒有效果。

停止

調用stop()方法讓MediaPlayer從Started, Paused, Prepared 或 PlaybackCompleted 狀態進入 Stopped 狀態。

在Stopped狀態時,必須先調用prepare() 或 prepareAsync()進入Prepared狀態後,才能播放音頻。

處於Stopped狀態時,調用stop()方法沒有效果。

調整播放位置

調用seekTo(long, int)來調整播放位置。

seekTo(long, int)是一個非同步方法,雖然它能立刻返回,但實際的位置調整可能會消耗一段時間,特別是在播放音頻流的時候。當實際播放位置調整後,內部播放器會回調開發者設置的OnSeekComplete.onSeekComplete()。

在Prepared, Paused 和 PlaybackCompleted狀態中,都可以調用seekTo方法。

可以通過getCurrentPosition()方法來獲取當前播放位置。開發者可以得知當前播放的進度等等。

播放完畢

音頻播放完成後,播放完畢。

如果調用setLooping(boolean)為true,MediaPlayer會停留在Started狀態。

如果setLooping為false,內部播放器會調用開發者設置的OnCompletion.onCompletion(),並且進入PlaybackCompleted狀態。

處於PlaybackCompleted狀態時,調用start()方法可以從頭開始播放音頻。

常用監聽器

開發者可以設置一些監聽器,監聽MediaPlayer的狀態,錯誤事件等等。開發者應在同一個線程中創建MediaPlayer與設置的監聽器。

setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener)
監聽MediaPlayer準備完成。一般與prepareAsync配合使用。

setOnVideoSizeChangedListener(android.media.MediaPlayer.OnVideoSizeChangedListener)
獲知video大小或video大小改變時的監聽。

setOnSeekCompleteListener(android.media.MediaPlayer.OnSeekCompleteListener)
監聽調整位置完成。

setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener)
播放完成。

mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
    @Override
    public void onCompletion(MediaPlayer mediaPlayer) {
        // 當前播放完畢
    }
});

setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener)
監聽緩衝進度。在播放網路音頻時常用。

緩衝監聽器OnBufferingUpdateListener

    mMediaPlayer.prepareAsync();
    mMediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
        @Override
        public void onBufferingUpdate(MediaPlayer mp, int percent) {
            // 例如在這裡更新UI
        }
    });

setOnInfoListener(android.media.MediaPlayer.OnInfoListener)
監聽普通信息或者警告信息。

setOnErrorListener(android.media.MediaPlayer.OnErrorListener)
監聽錯誤信息。錯誤發生時,可以在這裡處理錯誤。

mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
    @Override
    public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
        LogUtil.e(TAG_PREFIX + " onERR i = " + i + " i1 = " + i1);
        return true; // 返回true表示在此處理錯誤,不會回調onCompletion
    }
});

註意onError的返回值。可以選擇自己處理error。

         * @return True if the method handled the error, false if it didn't.
         * Returning false, or not having an OnErrorListener at all, will
         * cause the OnCompletionListener to be called.
         */
        boolean onError(MediaPlayer mp, int what, int extra);

需要的許可權

播放網路音頻時需要Manifest.permission.INTERNET許可權。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 問題經濟學上有個“海盜分金”模型:是說5個海盜搶得100枚金幣,他們按抽簽的順序依次提方案:首先由1號提出分配方案,然後5人表決,超過半數同意方案才被通過,否則他將被扔入大海喂鯊魚,依此類推,假設海盜是足夠聰明的先利己再傷人,最後方案是怎樣的?網上百度來的的代碼with a as (select 1... ...
  • 參考官方文檔Net Services Reference的7 Oracle Net Listener Parameters (listener.ora)1 監聽概念oracle監聽,是個伺服器端進程,負責監聽客戶端發來的請求監聽器可以不必駐留在資料庫主機上,即可以把實例註冊到遠程主機上的監聽監聽是o... ...
  • 引用:https://blog.csdn.net/u012615705/article/details/78321022 文章轉自上述地址,內部有稍許改動,如有需要請查看原文。 oracle樹狀結構查詢即層次遞歸查詢,是sql語句經常用到的,在實際開發中組織結構實現及其層次化實現功能也是經常遇到的。... ...
  • 問題描述: 早上巡檢是發現一套RAC的ora.chad一個節點的狀態是offline,其他的均正常。 crsctl stat res -t ora.chad ONLINE ONLINE csdb2-bm001 STABLE OFFLINE OFFLINE csdb2-bm002 STABLE 解決: ...
  • [toc] ansible變數 定義變數的方式 命令行 playbook 主機清單 如何定義變數 1.在playbook中定義變數 2.使用vars_files定義變數 3.使用ansible內置變數 4.使用主機清單定義變數 調用變數 5.官方推薦方式 6.命令行定義變數 ansible變數優先順序 ...
  • PostgreSQL觸發器,日誌審計小神器 最近遇到的項目問題,審計日誌記錄不夠詳細,比如某用戶編輯了某台設備,只記錄了用戶操作的設備名、操作時間、登錄用戶和登錄IP,至於設備其他屬性編輯前和編輯後的信息就沒有更詳細的對比了,審計粒度不夠細,顯然是不能讓客戶滿意的,秉承客戶滿意優先原則,只好技術加持 ...
  • 這三個不同的數據模型之間既相互獨立,又存在著關聯。從現實世界到概念 模型的轉換是由資料庫設計人員完成的;從概念模型到邏輯模型的轉換可以 由資料庫設計人員完成,也可以用資料庫設計工具協助設計人員完成;從邏 輯模型到物理模型的轉換主要是由資料庫管理系統完成的。 ...
  • 版權聲明:本文為xing_star原創文章,轉載請註明出處! 本文同步自http://javaexception.com/archives/218 kotlin之變數的可空與非空 上面一篇文章,介紹了kotlin的變數與常量,以及修飾為常量或者是變數的評估標準。本篇文章主要想說的是一個變數的可空與非 ...
一周排行
    -Advertisement-
    Play Games
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...