學習Android MediaPlayer

Android Media Playback

原文

The Android multimedia framework includes support for playing variety of common media types, so that you can easily integrate audio, video and images into your applications. You can play audio or video from media files stored in your application's resources (raw resources), from standalone files in the filesystem, or from a data stream arriving over a network connection, all using MediaPlayer APIs.

Android多媒體框架包含對多種常見媒體類型的支持,所以你可以容易的在自己的應用中集成音頻,視頻和圖片。你可以播放應用內的資源文件,或文件系統中獨立的文件,也可以通過網絡數據流來播放,這些功能都使用MediaPlayer APIs實現。

Note: You can play back the audio data only to the standard output device. Currently, that is the mobile device speaker or a Bluetooth headset. You cannot play sound files in the conversation audio during a call.

注意:你只能通過標準輸出設備播放音頻。當前,這包括移動設備的揚聲器或者藍牙耳機。你不能在用戶打電話時播放音頻。


The Basics

在Android Framework中,下面兩個類用來播放聲音和視頻:

MediaPlayer  此類是播放聲音和視頻的主要API。

AudioManager 此類管理音頻資源和音頻在設備上的輸出。


Manifest Declarations

Before starting development on your application using MediaPlayer, make sure your manifest has the appropriate declarations to allow use of related features.

在開始使用MediaPlayer之前,確保你的清單文件中聲明了與相關特性有關的權限:

  • Internet Permission - 如果你使用MediaPlayer播放網絡內容,應用需要網絡訪問權限。

  • Wake Lock Permission - 如果你的應用需要保持屏幕不變暗或者處理器不休眠,或者使用MediaPlayer.setScreenOnWhilePlaying()MediaPlayer.setWakeMode()方法,你需要請求以下權限:


Using MediaPlayer

One of the most important components of the media framework is the MediaPlayer class. An object of this class can fetch, decode, and play both audio and video with minimal setup. It supports several different media sources such as:

媒體框架中最重要的組件之一是MediaPlayer類。該類的對象可以用最少的步驟獲取,解碼和播放音頻和視頻。它支持多種媒體源,例如:

  • 本地資源

  • 內部URI,例如用于Content Resolver的URI

  • 外部URL(流)

Android支持的媒體類型,見此文檔:Android Supported Media Formats。

下面的例子顯示了如何播放本地raw資源(應用res/raw目錄下)

MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
mediaPlayer.start(); // no need to call prepare(); create() does that for you

本例中,一個“raw”資源是一個系統不會嘗試用特殊方式去解析的文件。然而,此資源的內容不能是原始音頻。它應該是根據支持的格式恰當編碼和格式化的文件。

下面的例子顯示如何通過本地URI播放:

Uri myUri = ....; // initialize Uri here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(getApplicationContext(), myUri);
mediaPlayer.prepare();
mediaPlayer.start();

下面的例子顯示如何通過HTTP訪問URL來播放:

String url = "http://........"; // your URL here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(url);
mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.start();

注意:如果你通過URL播放在線媒體文件,該文件必須可以漸近下載(Progressive download)。

警告:在使用setDataSource()時,必須捕獲或者傳遞IllegalArgumentException和IOException,因為你引用的文件可能不存在。


Asynchronous Preparation

Using MediaPlayer can be straightforward in principle. However, it's important to keep in mind that a few more things are necessary to integrate it correctly with a typical Android application. For example, the call to prepare() can take a long time to execute, because it might involve fetching and decoding media data. So, as is the case with any method that may take long to execute, you should never call it from your application's UI thread.

原則上,使用MediaPlayer是簡單直接的。然而集成在Android應用中時,有幾點需要注意。例如,調用prepare()可能會花費很長時間,因為此方法涉及到媒體數據的獲取和解碼,因此不應該在UI線程調用。

To avoid hanging your UI thread, spawn another thread to prepare the MediaPlayer and notify the main thread when done. However, while you could write the threading logic yourself, this pattern is so common when using MediaPlayer that the framework supplies a convenient way to accomplish this task by using the prepareAsync() method. This method starts preparing the media in the background and returns immediately. When the media is done preparing, the onPrepared() method of the MediaPlayer.OnPreparedListener, configured through setOnPreparedListener() is called.

要避免掛起UI線程,使用另一個線程來準備MediaPlaer,在完成時通知主線程。然而,雖然你可以自己寫線程邏輯,此框架提供了prepareAsync方法來簡化這一工作。此方法立刻返回,在后臺執行準備工作,完成后通過回調通知調用者。


Managing State

Another aspect of a MediaPlayer that you should keep in mind is that it's state-based. That is, the MediaPlayer has an internal state that you must always be aware of when writing your code, because certain operations are only valid when then player is in specific states. If you perform an operation while in the wrong state, the system may throw an exception or cause other undesireable behaviors.

關于MediaPlayer的另一個關注點是它是基于狀態的。也就是說,你寫代碼時必須始終意識到MediaPlayer有內部狀態,因為某些操作只在player處于特定狀態時才有效。如果你在錯誤的狀態下執行操作,系統可能會拋出異常或者引發其他不需要的行為。

MediaPlayer類文檔中展示了MediaPlayer的完整狀態圖。

Releasing the MediaPlayer

A MediaPlayer can consume valuable system resources. Therefore, you should always take extra precautions to make sure you are not hanging on to a MediaPlayer instance longer than necessary. When you are done with it, you should always call release() to make sure any system resources allocated to it are properly released. For example, if you are using a MediaPlayer and your activity receives a call to onStop(), you must release the MediaPlayer, because it makes little sense to hold on to it while your activity is not interacting with the user (unless you are playing media in the background, which is discussed in the next section). When your activity is resumed or restarted, of course, you need to create a new MediaPlayer and prepare it again before resuming playback.

MediaPlayer會消費寶貴的系統資源,所以必須注意不要保持MediaPlayer實例超過需要的時間。當你用完時,應該調用release()方法來確保分配給它的系統資源被合適的釋放了。例如,如果你正在使用MediaPlayer,而Activity收到了onStop()回調,則必須釋放MediaPlayer(除非你在后臺播放)。當Activity 重新獲得焦點或者重新開始時,你需要創建一個新的MediaPlayer實例,并在恢復播放前準備它。

將MediaPlayer釋放并制空:

mediaPlayer.release();
mediaPlayer = null;

As an example, consider the problems that could happen if you forgot to release the MediaPlayer when your activity is stopped, but create a new one when the activity starts again. As you may know, when the user changes the screen orientation (or changes the device configuration in another way), the system handles that by restarting the activity (by default), so you might quickly consume all of the system resources as the user rotates the device back and forth between portrait and landscape, because at each orientation change, you create a new MediaPlayer that you never release.

例如,如果你在Activity stop時忘了釋放MediaPlayer,但在Activity create時創建了新的實例,那在用戶反復旋轉屏幕時,可能會很快就耗盡所有的系統資源,因為每次方向改變,你都創建了新的MediaPlayer對象,但從來沒有釋放。

Using a Service with MediaPlayer

If you want your media to play in the background even when your application is not onscreen—that is, you want it to continue playing while the user is interacting with other applications—then you must start a Service and control the MediaPlayer instance from there. You should be careful about this setup, because the user and the system have expectations about how an application running a background service should interact with the rest of the system. If your application does not fulfil those expectations, the user may have a bad experience. This section describes the main issues that you should be aware of and offers suggestions about how to approach them.

如果想讓媒體文件在后臺播放,需要啟動一個Service,讓后再Service中控制MediaPlayer實例。用戶和系統對運行后臺服務的應用如何同系統其它部分交互有一些期望,如果你的應用無法滿足這些期望,用戶可能會有糟糕的體驗。本節描述了你需要注意的主要事項以及如何解決的建議。

Running asynchronously

First of all, like an Activity, all work in a Service is done in a single thread by default—in fact, if you're running an activity and a service from the same application, they use the same thread (the "main thread") by default. Therefore, services need to process incoming intents quickly and never perform lengthy computations when responding to them. If any heavy work or blocking calls are expected, you must do those tasks asynchronously: either from another thread you implement yourself, or using the framework's many facilities for asynchronous processing.

首先,同Activity一樣,默認情況下Service中的所有工作也是在主線程中完成的。因此,服務需要快速的處理傳入的intent,在響應意圖是不能執行長時間操作。如果有大量的工作或者阻塞式的調用,就需要異步的完成。

For instance, when using a MediaPlayer from your main thread, you should call prepareAsync() rather than prepare(), and implement a MediaPlayer.OnPreparedListener in order to be notified when the preparation is complete and you can start playing. For example:

例如,在主線程中使用MediaPlayer時,你應該調用prepareAsync()而不是prepare(),實現MediaPlayer.OnPreparedListener接口來通知準備已經完成。代碼如下:

public class MyService extends Service implements MediaPlayer.OnPreparedListener {private static final String ACTION_PLAY = "com.example.action.PLAY";MediaPlayer mMediaPlayer = null;public int onStartCommand(Intent intent, int flags, int startId) {...if (intent.getAction().equals(ACTION_PLAY)) {mMediaPlayer = ... // initialize it heremMediaPlayer.setOnPreparedListener(this);mMediaPlayer.prepareAsync(); // prepare async to not block main thread}}/** Called when MediaPlayer is ready */public void onPrepared(MediaPlayer player) {player.start();}
}

Handling asynchronous errors

On synchronous operations, errors would normally be signaled with an exception or an error code, but whenever you use asynchronous resources, you should make sure your application is notified of errors appropriately. In the case of a MediaPlayer, you can accomplish this by implementing a MediaPlayer.OnErrorListener and setting it in your MediaPlayer instance:

在同步的調用中,錯誤通常是通過異常或者錯誤碼表示,但在異步調用時,你應該確保正確的接收到錯誤。對于MediaPlayer來說,你可以實現MediaPlayer.OnErrorListener接口,設置給MediaPlayer實例:

public class MyService extends Service implements MediaPlayer.OnErrorListener {MediaPlayer mMediaPlayer;public void initMediaPlayer() {// ...initialize the MediaPlayer here...mMediaPlayer.setOnErrorListener(this);}@Overridepublic boolean onError(MediaPlayer mp, int what, int extra) {// ... react appropriately ...// The MediaPlayer has moved to the Error state, must be reset!}
}

It's important to remember that when an error occurs, the MediaPlayer moves to the Error state (see the documentation for the MediaPlayer class for the full state diagram) and you must reset it before you can use it again.

要記住當錯誤發生時,MediaPlayer轉變為Error狀態,在你使用它之前需要重置(reset)它。

轉載于:https://www.cnblogs.com/yuanchongjie/p/5089476.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/256145.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/256145.shtml
英文地址,請注明出處:http://en.pswp.cn/news/256145.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

spark2.0.1 安裝配置

1. 官網下載 wget http://d3kbcqa49mib13.cloudfront.net/spark-2.0.1-bin-hadoop2.7.tgz 2. 解壓 tar -zxvf spark-2.0.1-bin-hadoop2.7.tgz ln -s spark-2.0.1-bin-hadoop2.7 spark2 3. 環境變量 vi /etc/profile #Spark 2.0.1export SPARK_HOME/usr/local/spark2export PATH…

Spring Cloud各組件超時

Ribbon的超時 全局設置: ribbon:ReadTimeout: 60000ConnectTimeout: 60000局部設置: service-id:ribbon:ReadTimeout: 1000ConnectTimeout: 1000其中,service-id 是Ribbon所使用的虛擬主機名,一般和Eureka Server上注冊的服務名稱…

【圖像處理】——遍歷圖像所有像素的方法(for 循環和np.where遍歷)應用在模板制作

目錄 具體np.where的用法可以參見: 其他遍歷圖像的所有像素的方法: 模板制作流程 Python代碼

C++總結筆記(五)——構造函數和析構函數

文章目錄前言一、基本概念1 構造函數2 析構函數二、示例1. 構造函數和析構函數的簡單使用2. 拷貝構造函數的調用3. 淺拷貝和深拷貝前言 本文講述了構造函數和析構函數的概念以及對應的示例,以便加深理解。 一、基本概念 1 構造函數 構造函數用于初始化類的對象&a…

LINUX 更新

sudo apt-get dist-upgrade,更新所有的軟件轉載于:https://www.cnblogs.com/jackieron/p/5997805.html

python實戰===如何優雅的打飛機

這是一個打飛機的游戲,結構如下: 其中images中包含的素材為 命名為alien.png 命名為ship.png 游戲效果運行是這樣的: 敵軍,也就是體型稍微大點的,在上方左右移動,并且有規律向下移動。我軍目標,…

【圖像處理】——上采樣、下采樣、在模板匹配中的金字塔加速策略

目錄 1、下采樣 Python自帶函數 自定義函數 Python實現下采樣 2、上采樣 Python自帶函數 自定義函數<

C++總結筆記(六)——友元

文章目錄前言一、基本概念二、程序示例1.全局函數調用私有成員2. 外部類調用私有成員3. 外部類的成員函數調用私有成員總結前言 一、基本概念 友元是C中為了方便類外的類或者函數訪問類內私有成員而定義的一種特殊語法&#xff0c;用friend關鍵字進行修飾。 二、程序示例 友…

Java默認類型,類型轉換,常量與變量筆記

默認類型&#xff1a; 在java里整數默認是int類型&#xff0c;小數默認是double類型&#xff0c;單個字符默認是char類型&#xff0c;true、false自然默認的是boolean類型&#xff0c;字符串默認的是String類型。 變量和常量類型轉換&#xff1a; 因為有默認類型&#xff0c;在…

【圖像處理】——Python實現灰度特征提取

目錄 1、灰度特征 2、Python代碼 1、灰度特征 2、Python代碼 import cv2 import numpy as npdef gray_features(img):hist = cv2.calcHist([img],[0],None,[256],[0,255])#得到全局直方圖統計數據

C++總結筆記(七)—— 運算符重載

文章目錄一、概念二、程序示例1. 加減乘除重載2. 賦值運算符重載3. 遞增遞減運算符重載4. 關系運算符重載5. 左移運算符重載6. 函數調用運算符重載一、概念 C中運算符重載是為了實現對象之間進行各種運算的特定語法&#xff0c;在某些特定的場合起到重要的作用&#xff0c;新建…

asp.net 加載xml到menu

XML File <?xml version"1.0" encoding"utf-8" ?> <Area iAreaID "0" cAreaName"城市"><Province iAreaID "1" cAreaName"北京市"/><Province iAreaID "2" cAreaName"上海…

前端lvs訪問多臺nginx代理服務時出現404錯誤的處理

前端lvs訪問多臺nginx代理服務時出現404錯誤的處理 環境描述&#xff1a;app --> lvs --> nginx --> server app訪問頁面購買流量頁面(nginx服務器)代理到后端和服務器交互(多臺server)剛開始訪問沒有問題&#xff0c;流量變大為了避免出現問題&#xff0c;nginx配置了…

使用numpy出現DeprecationWarning: The normed argument is ignored when density is provided. 解決方法忽略警告的方法

目錄 1、從根本上進行解決 2、直接利用warning模塊忽略警告 1、從根本上進行解決 “DeprecationWarning: The normed argument is ignored when density is provided. In future passing both will result in an error.” 這種一般是因為函數庫或者是一些包package版本更新而…

iptables四個表與五個鏈間的處理關系

轉載自&#xff1a;http://www.linuxidc.com/Linux/2012-08/67505.htm netfilter/iptables IP 信息包過濾系統是一種功能強大的工具&#xff0c;可用于添加、編輯和除去規則&#xff0c;這些規則是在做信息包過濾決定時&#xff0c;防火墻所遵循和組成的規則。 這些規則存儲在專…

C++總結筆記(八)—— 菱形繼承

文章目錄一、基本概念二、程序舉例1. 虛繼承2. 內在邏輯一、基本概念 菱形繼承是指存在兩個子類繼承自同一個基類&#xff0c;同時有子類繼承這兩個子類。 二、程序舉例 1. 虛繼承 使用虛繼承可以解決菱形繼承資源浪費的問題&#xff0c;因為有兩個子類繼承基類&#xff0c…

Linux命令:mkdir

全稱&#xff1a;make directories 用途&#xff1a;創建新目錄 格式&#xff1a;mkdir [OPTION]... DIRECTORY... 類型&#xff1a;mkdir is hashed (/bin/mkdir) 說明&#xff1a; 創建文件目錄&#xff0c;較常用的選項參數有兩個&#xff1a; -m, --modeMODE&#xff1a;直…

InnoDB引擎與MyIASM的一點總結

InnoDB引擎&#xff1a; 提供了對數據庫ACID事務的支持&#xff0c;并且實現了SQL標準的四種隔離級別 提供了行級鎖和外鍵約束。 它的設計的目標是處理大容量數據庫系統&#xff0c;用于緩沖數據和索引。 不支持FULLTEXT類型的數據&#xff0c;沒有保存表的行數&#xff0c;當s…

C++總結筆記(九)—— 多態

文章目錄一、多態是什么&#xff1f;二、使用步驟2.1. 靜態多態2.1.1 函數重載2.1.2 模板2.2.動態多態2.2.1 示例2.2.2 原理分析總結一、多態是什么&#xff1f; 多態是面向對象的語言中都必須掌握的特性&#xff0c;其概念簡單講就是對同一種特性的方法有不同的實現功能&…

[轉]c++類的構造函數詳解

c構造函數的知識在各種c教材上已有介紹&#xff0c;不過初學者往往不太注意觀察和總結其中各種構造函數的特點和用法&#xff0c;故在此我根據自己的c編程經驗總結了一下c中各種構造函數的特點&#xff0c;并附上例子&#xff0c;希望對初學者有所幫助。 c類的構造函數詳解 …