使用MediaPlayer播放音視訊精煉詳解
一、前期基礎知識儲備
MediaPlayer是一個支援音訊及視訊檔案播放的Android類,可播放不同來源(本地 網路)、多種格式(如WAV/MP3/MPEG-4/3GPP/Ogg Vorbis)的多媒體檔案。
多媒體檔案可以是儲存在應用程式的 res/raw 資料夾下,也可以是儲存在手機的檔案系統中,甚至可以是來自與網路的流媒體。raw資料夾負責存放那些不需要Android編譯系統特別處理的各類檔案,res下預設是沒有raw資料夾的,建立方法如下:
例項化一個MediaPlayer物件一共有三種方法:
1)create(Context context, Uri uri, SurfaceHolder holder)
Convenience method to create a MediaPlayer for a given Uri.
2)create
Convenience method to create a MediaPlayer for a given resource id.
3)create(Context context, Uri uri)
Convenience method to create a MediaPlayer for a given Uri.
注意: 你只能通過標準輸出裝置來播放音訊檔案。目前來講,就是通過手機的揚聲器和藍芽耳機。 不能在通話時播放音訊檔案。
使用MediaPlayer時申請的許可權:
1)
<uses-permission android:name="android.permission.INTERNET" />
2)
<uses-permission android:name="android.permission.WAKE_LOCK" />
Wake Lock Permission - 如果你想要應用不滅屏或者程序不進入休眠狀態,或者你像要在你的應用程式中使用 MediaPlayer.setScreenOnWhilePlaying() 方法或 MediaPlayer.setWakeMode() 方法, 你需要新增這個許可權
二、上程式碼,具體實現
以下是程式碼的整體設計圖:
從圖中可以看到程式碼中包含一個Fragment即一個用於託管Fragemnt的Activity。MyAudioMediaPlayer是我們編寫的類,用於封裝MediaPlayer類。也可以選擇不封裝MediaPlayer類,而讓Fragment直接與MediaPLayer進行互動。不過,為了保持程式碼的整潔與獨立,這裡使用了封裝MediaPlayer類的設計。
(1)Fragment程式碼及Fragemnt的佈局檔案;
public class HelloMoonFragment extends Fragment {
private MyAudioPlayer mPlayer;
private Button mPlayButton;
private Button mStopButton;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_hello_moon, container, false);
mPlayButton = (Button) view.findViewById(R.id.hellomoon_playBtn);
mPlayButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPlayer.play(getActivity());
}
});
mStopButton = (Button) view.findViewById(R.id.hellomoon_stopBtn);
mStopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPlayer.stop();
}
});
return view;
}
@Override
public void onDestroy() {
super.onDestroy();
mPlayer.stop();
}
}
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:src="@drawable/bv"
android:contentDescription="圖片也可以有文字屬性?"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerInside"
android:layout_weight="1"/>
<TableRow
android:gravity="center|bottom"
android:layout_weight="0">
<Button
android:id="@+id/hellomoon_playBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="play"/>
<Button
android:id="@+id/hellomoon_stopBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="stop"/>
</TableRow>
</TableLayout>
使用MediaPlayer之後,Fragment中要覆寫onDestroy()方法,這是因為MediaPlayer執行在一個不同的執行緒中,這裡在Fragment的銷燬方法中呼叫MediaPlayer的銷燬方法,防止MediaPlayer一直佔用著音訊解碼硬體及其他系統資源,而這些系統資源是由所有應用所共享的。
(2)Activity程式碼及Activity的佈局檔案;
public class PaintPositionInTest extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PaintPositionIn paintPositionIn = new PaintPositionIn(this);
setContentView(R.layout.activity_hello_moon);
}
}
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/helloMoonFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.example.administrator.animation_practice.fragment.HelloMoonFragment">
</fragment>
這裡用Fragemnt的靜態載入方法,將其直接新增進Activity的佈局檔案,使用靜態載入Fragment的方式失去了靈活性和掌控能力,但是對於Activity的靜態部分而言,靜態載入也是一個不錯的選擇。
(3)封裝MediaPlayer類的MyAudioPlayer類;
public class MyAudioPlayer {
private MediaPlayer mPlayer;
public void stop(){
if (mPlayer != null){
mPlayer.release();
mPlayer = null;
}
}
public void play(Context c){
stop();
mPlayer = MediaPlayer.create(c, R.raw.one_small_step);
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
stop();
}
});
try {
mPlayer.prepare(); //預載入音訊 使用時放置在try catch中
} catch (IOException e) {
e.printStackTrace();
}
mPlayer.start(); //正式載入音訊
}
}
在play()方法中,呼叫對應的create(Context context, int resid)建立mPlayer例項;並且在方法的開頭呼叫stop()方法,可避免使用者多次點選Play按鈕建立多個MediaPlayer例項的情況的發生。同時設立監聽器,音訊檔案播放完之後,立即呼叫stop()方法,儘可能快遞釋放MediaPlayer例項及其佔用的資源。
在stop()方法中,釋放MediaPlayer例項並將mPlayer變數設定為null,呼叫Media.release()方法,銷燬該例項。
封裝MediaPlayer之後,之後管理播放器的狀態會更加的方便,實際開發中,相機、音訊播放、視訊播放等多媒體行為,生命週期、狀態非常多,需要多重控制,封裝程式碼之後可以更加方便的管理。
三、使用MediaPlayer播放視訊
在Android系統中,快速重新整理顯示的可檢視像(比如視訊、相機預覽)是在SurfaceView中顯示的,準確地說,是在SurfaceView內嵌的Surface中顯示的。通過SurfaceView的SurfaceHolder,可實現Surface上顯示視訊。使用MediaPlayer播放視訊的關鍵程式碼在於將MediaPlayer類與SurfaceHolder關聯起來,方法為:
MediaPlayer.setDisplay(SurfaceHolder);
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback{
...
private SurfaceView mSurfaceView;
private String mMediaPath;
private MediaPlayer mMediaPlayer;
private SurfaceHolder mSurfaceHolder;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//6.0及以上系統請求執行時許可權 利用許可權申請工具類
requestCameraAndStoragePermission();
mSurfaceView = (SurfaceView) findViewById(R.id.surface_view);
mSurfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); //必須-設定Surface不需要維護自己的緩衝區
initBtnClick();
SurfaceHolder holder = mSurfaceView.getHolder();
holder.addCallback(this);
}
private void requestCameraAndStoragePermission() {
...
...
};
......
......
private void initBtnClick() {
mPlayBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mMediaPlayer == null) {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.reset();
Uri uri = Uri.parse(mMediaPath);
mMediaPlayer = MediaPlayer.create(MainActivity.this,uri);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setDisplay(mSurfaceHolder);
try{
mMediaPlayer.prepare();
}catch (Exception e){
e.printStackTrace();
}
mMediaPlayer.start();
}
}
});
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
mSurfaceHolder = surfaceHolder;
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
mSurfaceHolder = surfaceHolder;
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
mSurfaceView = null;
mSurfaceHolder = null;
releaseMediaRecorder();
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
if (mMediaPlayer != null){
mMediaPlayer.release();
mMediaPlayer = null;
}
}
}
通常來說,使用VideoView例項播放視訊更加容易些,不同於SurfaceView同MediaPlayer的互動,VideoView是與MediaController互動的,這樣可以方便地提供視訊播放介面。
相關推薦
使用MediaPlayer播放音視訊精煉詳解
一、前期基礎知識儲備 MediaPlayer是一個支援音訊及視訊檔案播放的Android類,可播放不同來源(本地 網路)、多種格式(如WAV/MP3/MPEG-4/3GPP/Ogg Vorbis)的多媒體檔案。 多媒體檔案可以是儲存在應用程式的 re
Android劉海屏適配精煉詳解
一、前期基礎知識儲備 話不多說,這麼多劉海屏手機今年集中爆發,所以儘管劉海屏不好看,但是還是要適配。 2017年蘋果X開啟了劉海屏時代,2018年集中爆發,紛紛採取劉海屏這一策略來實現全面屏的概念,所以Android手機對於劉海屏的適配也是比較重要的。所謂適配劉海屏,其實就是處理與
SQLite資料庫精煉詳解
一、前期基礎知識儲備 Android本地化儲存三種方式: ①檔案儲存,儲存簡單二進位制資料和文字資料; ②SharedPreference儲存,鍵值對儲存,儲存資料型別多樣,儲存方式單一; ③SQLite資料庫儲存,Android內建資料庫,儲存複雜關係型資料,質的飛躍。 SQLi
Android提高第二十一篇之MediaPlayer播放網路視訊
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
振鈴訊號、撥號音、回鈴音、忙音詳解
轉自:https://www.cnblogs.com/sddai/p/8847950.html 1、振鈴訊號 用來呼叫被叫使用者。鈴流為25±3Hz正弦波,諧波失真不大於10%,輸出電壓有效值90+-15V,振鈴採用5s斷續,即一秒送,4s斷,斷、續時間偏差不超過±10%。 2、撥號音
Android FFmpeg系列——4 子執行緒播放音視訊
利用工作閒餘時間,終於實現在子執行緒播放音視訊! 上一接學習了在 C 使用多執行緒,接著就是利用 C 多執行緒同時播放音視訊(暫時還不同步)。 不多說,直接上碼。 程式碼 // C 層播放器結構體 typedef struct _Player { //
程序間通訊(IPC機制)精煉詳解
一、前期基礎知識儲備IPC定義:IPC是intent-Process Communication的縮寫,含義為程序間通訊或者跨程序通訊,是指兩個程序之間進行資料交換的過程。IPC不是Android所獨有的,任何一個作業系統都需要有相應的IPC機制,比如Windows上可以通過
Java執行緒阻塞方法sleep()和wait()精煉詳解
一、前期基礎知識儲備 sleep()和wait()方法都是Java中造成執行緒阻塞的方法。感興趣的讀者可以參見筆者之前的文章《Java中什麼方法導致執行緒阻塞》,裡面詳細講述了為什麼Java要造成執行緒阻塞和Java中造成執行緒阻塞的幾種方法。 執行緒的生命週期 這
讀寫(read&write)視訊(video) 詳解 及 程式碼
讀取(read&write)視訊(video) 詳解 及 程式碼本文地址: http://blog.csdn.net/caroline_wendy/article/details/1708439
Android程序保活精煉詳解
一、前期基礎知識儲備在之前的文章《如何保證Service在後臺不被殺死?》中,筆者分析了為什麼要保活Service、Service的幾種保活方法和Service保活的意義。今天的這篇文章就更進一步,講解程序保活的方法和意義。(1)什麼是程序保活?拿我們的手機應用程式QQ來說,
C# 使用SDL2實現Mp4檔案播放音視訊
播放音視訊的關鍵:視訊的格式是H264,音訊的格式是AAC。使用ffmpeg探測流的方式來實現音視訊流的解碼播放。資料處理邏輯:H264->YUV AAC->PCM。SDL2工具類using SDL2; using System; using System
Android之MediaPlayer播放網路視訊的實現方法
前段時間忙於工作,現在有時間來分享一下: 這篇文章主要介紹了Android的MediaPlayer播放網路視訊的實現方法,是一個非常實用的功能,需要的朋友可以參考下 前面講解了MediaPlayer播放網路音訊,主要介紹了MediaPlayer關於網路音訊
【視訊】詳解小程式wx.requestpayment用法,實現小程式線上支付功能
開發小程式商城,外賣小程式,銷售型小程式等,具有線上支付功能的,都會使用wx.requestpayment()這個介面。好多學員反饋說這個介面很難,今天子恆老師跟你分享一下,怎麼使用wx.requestpayment實現微信支付。一、 使用wx.requestpayment實
ubuntu下 gstreamer 的配置及播放音視訊例子
Gstreamer安裝: 使用sudo apt-get install 安裝 sudo apt-get install libgstreamer0.10-dev gstreamer-tools gstreamer0.10-tools gstreamer0.10-
Android使用GPUImage實現濾鏡效果精煉詳解(一)
一、前期基礎知識詳解 “濾鏡通常用於相機鏡頭作為調色、新增效果之用。如UV鏡、偏振鏡、星光鏡、各種色彩濾光片。濾鏡也是繪圖軟體中用於製造特殊效果的工具統稱,以Photoshop為例,它擁有風格化、畫筆描邊、模糊、扭曲、銳化、視訊、素描、紋理、畫素化、渲染、藝術效果、其他
QT QMediaPlayer 播放音視訊檔案
QMediaPlayer類是QT自帶的多媒體類。 實現簡單的音視訊播放是很簡單的。 QMediaPlayer qtaudioPlayer; qtaudioPlayer->setMedia(QUrl::fromLocalFile(filePath)); qtaudio
視訊採集詳解
為了管理從相機或者麥克風等這樣的裝置捕獲到的資訊,我們需要輸入物件(input)和輸出物件(output),並且使用一個會話(AVCaptureSession)來管理 input 和 output 之前的資料流: 類名 簡介 AVC
Android中記憶體洩漏超級精煉詳解
一、前期基礎知識儲備 (1)什麼是記憶體? JAVA是在JVM所虛擬出的記憶體環境中執行的,JVM的記憶體可分為三個區:堆(heap)、棧(stack)和方法區(method)。 棧(stack):是簡單的資料結構,但在計算機中使用廣泛。棧最顯著的特徵是:LIF
Android混淆精煉詳解+常用庫混淆+通用混淆模板
一、前期基礎知識詳解 筆者最近開發一個專案,是在開源專案基礎上構築的,在最近一個版本釋出前夕,出現了一個奇怪的問題:在測試手機上執行的應用,功能正常,但是在打出release正式包之後,測試時發現上傳功能失效,不能上傳資料,即debug包功能正常,release
SharedPreference儲存精煉詳解
前期基礎知識儲備 之前做應用時碰到一個問題:在使用者初次進入某個介面時,需要彈出一個提示,或者在EditText上顯示一個hint;而使用者之後進入就不再彈出提示了。思考之後就選擇了SharedPreferences這個輕型的資料儲存方式。儲存一個布林型值作為ke