1. android開發音樂播放器MediaPlayer.prepare()
MediaPlayer類可用於控制音頻/視頻文件或流的播放,我曾在《Android開發之基於Service的音樂播放器》一文中介紹過它的使用。下面讓我們看一下MediaPlayer類的詳細介紹。
一、類結構:
java.lang.Object
↳
android.media.MediaPlayer
二、構造方法和公有方法
構造方法:
Public Constructors
MediaPlayer()
默認構造方法。
公有方法:
Public Methods
static MediaPlayer
create(Context context, Uri uri, SurfaceHolder holder)
指定從資源ID對應的資源文件中來裝載音樂文件,同時指定了SurfaceHolder對象並返回MediaPlyaer對象。
static MediaPlayer
create(Context context, int resid)
指定從資源ID對應的資源文件中來裝載音樂文件,並返回新創建的MediaPlyaer對象。
static MediaPlayer
create(Context context, Uri uri)
從指定Uri裝在音頻文件,並返回新創建的MediaPlayer對象。
int
getCurrentPosition()
獲取當前播放的位置。
int
getDuration()
獲取音頻的時長。
int
getVideoHeight()
獲取視頻的高度。
int
getVideoWidth()
獲取視頻的寬度。
boolean
isLooping()
判斷MediaPlayer是否正在循環播放。
boolean
isPlaying()
判斷MediaPlayer是否正在播放。
void
pause()
暫停播放。
void
prepare()
准備播放(裝載音頻),調用此方法會使MediaPlayer進入Prepared狀態。
void
prepareAsync()
准備播放非同步音頻。
void
release()
釋放媒體資源。
void
reset()
重置MediaPlayer進入未初始化狀態。
void
seekTo(int msec)
尋找指定的時間位置。
void
setAudioStreamType(int streamtype)
設置音頻流的類型。
void
setDataSource(String path)
指定裝載path路徑所代表的文件。
void
setDataSource(Context context, Uri uri, Map<String, String headers)
指定裝載uri所代表的文件。
void
setDataSource(Context context, Uri uri)
指定裝載uri所代表的文件。
void
setDataSource(FileDescriptor fd, long offset, long length)
指定裝載fd所代表的文件中從offset開始長度為length的文件內容。
void
setDataSource(FileDescriptor fd)
指定裝載fd所代表的文件。
void
setDisplay(SurfaceHolder sh)
設置顯示方式。
void
setLooping(boolean looping)
設置是否循環播放。
void
setNextMediaPlayer(MediaPlayer next)
設置當前流媒體播放完畢,下一個播放的MediaPlayer。
void
setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener listener)
注冊一個回調函數,在網路視頻流緩沖變化時調用。
void
setOnCompletionListener(MediaPlayer.OnCompletionListener listener)
為Media Player的播放完成事件綁定事件監聽器。
void
setOnErrorListener(MediaPlayer.OnErrorListener listener)
為MediaPlayer的播放錯誤事件綁定事件監聽器。
void
setOnPreparedListener(MediaPlayer.OnPreparedListener listener)
當MediaPlayer調用prepare()方法時觸發該監聽器。
void
setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener listener)
當MediaPlayer調用seek()方法時觸發該監聽器。
void
setOnVideoSizeChangedListener(MediaPlayer.OnVideoSizeChangedListener listener)
注冊一個用於監聽視頻大小改變的監聽器。
void
setScreenOnWhilePlaying(boolean screenOn)
置是否使用SurfaceHolder來顯示。
void
setSurface(Surface surface)
設置Surface。
void
setVideoScalingMode(int mode)
設置視頻縮放的模式。
void
setVolume(float leftVolume, float rightVolume)
設置播放器的音量。
void
setWakeMode(Context context, int mode)
為MediaPlayer設置低級電源管理行為。.
void
start()
開始或恢復播放。
void
stop()
停止播放。
三、常用方法分析:
1.使用進度條:
進度條SeekBar可以用來顯示播放進度,用戶也可以利用SeekBar的滑塊來控制音樂的播放。
SeekBar需要使用的一些方法:
setProgress(int value):設置滑塊的位置方法為。
setMax(int value):設置進度條的最大長度。
setOnSeekBarChangeListener(OnSeekBarChangeListener l):設置SeekBar的進度改變事件。
MusicPlayer需要使用的一些方法:
getDuration():獲得音樂長度為。
getCurrentPosition():獲得現在播放的位置。
seekTo(int msec):調用seekTo()方法可以調整播放的位置。
seekTo(int)方法是非同步執行的,所以它可以馬上返回,但是實際的定位播放操作可能需要一段時間才能完成,尤其是播放流形式的音頻/視頻。當實際的定位播放操作完成之後,內部的播放引擎會調用客戶端程序員提供的OnSeekComplete.onSeekComplete()回調方法。可以通過setOnSeekCompleteListener(OnSeekCompleteListener)方法注冊。
seekTo(int)方法也可以在其它狀態下調用,比如Prepared,Paused和PlaybackCompleted狀態。此外,目前的播放位置,實際可以調用getCurrentPosition()方法得到,它可以幫助如音樂播放器的應用程序不斷更新播放進度。
創建並使用進度條的步驟:
第一步:創建一個進度條
//進度條
static SeekBarskbMusic;
skbMusic=(SeekBar)findViewById(R.id.skbMusic);
第二步:為進度條的改變事件注冊並添加監聽器
skbMusic.setOnSeekBarChangeListener(sChangeListener);
/**
* SeekBar進度改變事件
*/
=new OnSeekBarChangeListener() {
@Override
publicvoid onStopTrackingTouch(SeekBar seekBar) {
//TODO Auto-generated method stub
//當拖動停止後,控制mediaPlayer播放指定位置的音樂
MusicService.mediaPlayer.seekTo(seekBar.getProgress());
MusicService.isChanging=false;
}
@Override
publicvoid onStartTrackingTouch(SeekBar seekBar) {
//TODO Auto-generated method stub
MusicService.isChanging=true;
}
@Override
publicvoid onProgressChanged(SeekBar seekBar,int progress,
boolean fromUser) {
//TODO Auto-generated method stub
}
};
第三步:設置進度條的最大長度:
//getDuration()方法要在prepare()方法之後,否則會出現Attempt to call getDuration without a valid mediaplayer異常
MusicBox.skbMusic.setMax(mediaPlayer.getDuration());//設置SeekBar的長度
第四步:更新進度條
//----------定時器記錄播放進度---------//
mTimer =new Timer();
mTimerTask =new TimerTask() {
@Override
publicvoid run() {
isTimerRunning=true;
if(isChanging==true)//當用戶正在拖動進度進度條時不處理進度條的的進度
return;
MusicBox.skbMusic.setProgress(mediaPlayer.getCurrentPosition());
}
};
//每隔10毫秒檢測一下播放進度
mTimer.schele(mTimerTask, 0, 10);
2.裝載音頻文件:
為了讓MediaPlayer來裝載指定音頻文件,MediaPlayer提供了如下簡單的靜態方法。
static MediaPlayer create(Context context, Uri uri):從指定Uri來裝載音頻文件,並返回新創建的MediaPlayer對象。
static MediaPlayer create(Context context, int resid):從 resid資源 ID對應的資源文件中裝載音頻文件,並返回新創建的MediaPlayer對象。
提示:上而這兩個方法用起來非常方便,但這兩個方法每次都會返回新創建的MediaPlayer對象,如來程序需要使用MediaPlayer循環播放多個音頻文件,使用MediaPlayer的靜態create方法就不太合適了,此時可通過MediaPlayer的setDataSource()方法來裝載指定的音頻文件。MediaPlayer提供了如下方法來指定裝載相應的音頻文件。
setDataSource(String path):指定裝載path路徑所代表的文件。
setDataSource(FileDescriptor fd, long offset,long length):指定裝載fd所代表的文件中從offset開始長度為length的文件內容。
setDataSource(FileDescriptor fd):指定裝載fd所代表的文件。
setDataSource(Context context, Uri uri):指定裝載uri所代表的文件。
提示:執行上面所示的setDataSource()方法之後,MediaPlayer並未真正去裝載那些音頻文件,還需要調用MediaPlayer的prepare()方法去准備音頻,所謂「准備」,就是讓MediaPlayer真正去裝載音頻文件。
使用已有的MediaPlayer對象裝載「一首」歌曲的代碼模板為:
mPlayer.reset();
//裝戰下一竹歌曲
mPlayer.setDataSource(M/mnt/sdcard/next.mp3);
//准備聲音 mPlayer.prepare();
"播放
mPlayer.start();
}
catch (IOException e)
e.printStackTrace();
}
3.與MediaPlayer有關的事件監聽器:
MediaPlayer提供了一些綁定事件監聽器的方法,用於監聽MediaPlayer播放過程中所發生的特定事件,綁定事件監聽器的方法如下。
setOnCompletionListener(MediaPlayer.OnCompletionListener listener):為 Media Player的播放完成事件綁定事件監聽器。
setOnErrorListener(MediaPlayer.OnErrorListener listener):為MediaPlayer的播放錯誤事件綁定事件監聽器。
setOnPreparedListener(MediaPlayer.OnPreparedListener listener):當 MediaPlayer調用prepare()方法時觸發該監聽器。
setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener listener):當MediaPlayer調用seek()方法時觸發該監聽器。
因此可以在創建一個MediaPlayer對象之後,通過為該MediaPlayer綁定監聽器來監聽相應的事件,例如如下代碼:
//為MediaPlayer的播放完成事件綁定事件監聽器
mPlayer.setOnErrorListener(new OnErrorListener() {
@Override
publicboolean onError(MediaPlayer mp,int what,int extra) {
//TODO Auto-generated method stub
//針對錯誤進行相應的處理
// ... ...
}
});
//為MediaPlayer的播放完成講件綁定市件監聽器
mPlayer.setOnCompletionListener(new OnCompletionListener() {
@Override
publicvoid onCompletion(MediaPlayer mp) {
//TODO Auto-generated method stub
current++;
prepareAndPlay(current);
}
});
四、MediaPlayer播放不同來源的音頻文件:
1.播放應用的資源文件
播放應用的資源文件需要兩步即:
1) 調用MediaPlayer的create(Context context,int resid)方法加指定資源文件。
2) 調用 MediaPlayer的 start()、pause()、stop()等方法控制播放即可。
例如如下代碼:
MediaPlayer mPlayer=new MediaPlayer();
mPlayer.create(this, R.raw.music);
2. 播放應用的原始資源文件
播放應用的資源文件按如下步驟執行。
1) 調用 Context的 getAssets()方法獲取應用的 AssetManager。
2) 調用AssetManager對象的openFd(String name)方法打開指定的原生資源,該方法返回一個AssetFileDescriptor對象。
3) 調用 AssetFileDescriptor的 getFileDescriptor()、getStartOffset()和 getLength()方法來獲取音頻文件的FileDescriptor、開始位置、長度等。
4) 創建MediaPlayer對象(或利用已有的MediaPlayer對象),並調用MediaPlayer對象的setDataSource(FileDescriptor fd,long offset, long length)方法來裝載音頻資源。
5) 調用MediaPlayer對象的prepare()方法准備音頻。
6) 調用MediaPlayer的start()、pause()、stop()等方法控制播放即可。
例如如下代碼片段:
//獲取assets目錄下指定文件的AssetFileDescriptor對象
AssetFileDescriptor assetFileDescriptor=assetManager.openFd(musics[current]);
mediaPlayer.reset();//初始化mediaPlayer對象
mediaPlayer.setDataSource(assetFileDescriptor.getFileDescriptor(), assetFileDescriptor.getStartOffset(), assetFileDescriptor.getLength());
//准備播放音樂
mediaPlayer.prepare();
//播放音樂
mediaPlayer.start();
3. 播放外部存儲器上音頻文件
播放外部存儲器上音頻文件按如下步驟執行。
1) 創建MediaPlayer對象(或利用已有的MediaPlayer對象),並調用MediaPlayer對象的setDateSource(String path)方法裝載指定的音頻文件。
2) 調用MediaPlayer對象的prepare()方法准備音頻。
3) 調用MediaPlayer的start()、pause()、stop()等方法控制播放即可。
例如如下代碼:
//載入SD卡上的指定資源音頻文件
mPlayer.setDataSource("/mnt/You Are The One.mp3");
mPlayer.prepare();//准備因音頻
mPlayer.start();//播放音頻
4.播放來自網路的音頻文件
播放來自網路的音頻文件冇兩種方式:1.直接使用MediaPlayer的靜態create(Context context, Uri uri)方法;2.調用 MediaPlayer的setDataSource(Context context,Uri uri)裝載指定Uri對應的音頻文件。
以第二種方式播放來自網路的音頻文件的步驟如下。
1. 根據網路上的音頻文件所在的位置創建Uri對象。
2. 創建MediaPlayer對象(或利用己有的MediaPlayer對象),並調用MediaPlayer對象的 setDateSource(Context context,Uri uri)方法裝載Uri對應的音頻文件。
3. 調用MediaPlayer對象的prepare()方法准備音頻。
4. 調用MediaPlayer的start()、pause()、stop()等方法控制播放即可。
2. MKV格式的電影用什麼播放器放
可以用迅雷影音播放,具體的操作方法和步驟如下:
1、首先,找到要打開的mkv格式的電影文件,如下圖所示。
3. c++編寫了一個播放器 用的picture控制項,想雙擊它全屏顯示,再雙擊回到原來的狀態,
可以參考下面的技術
摘要:本文對在VC下單文檔程序的全屏顯示及其恢復的實現過程作了介紹。
關鍵字:窗體、全屏顯示、Visual C++
一、 引言
在編輯類軟體或程序代碼編輯程序中經常要遇到一些長度特別大的文本或代碼,尤其是對於程序源碼的編輯,如果編輯界面太小,則需要頻繁拉動滾動條,對於程序員而言是很不情願的,因為這樣會打斷程序的設計思路、影響編程的效果。因此不少軟體都具備了全屏放大的功能,將編輯界面放大到全屏幕,盡最大限度地減少對滾動條的依賴程度。相信不少程序員一定非常喜歡在VC的全屏編輯狀態下編程,本文就以Visual C++ 6.0為開發環境將普通的單文檔編輯視圖程序擴展為全屏編輯功能。
二、 程序的設計思路
普通常規程序之所以在最大化的情況下沒能實現全屏,是由於狀態條、工具條、系統菜單、標題欄等幾個窗口分別占據了一部分屏幕空間,所以實現視圖的全屏顯示首先要把以上幾個窗體隱藏起來,然後才可以考慮將視圖最大化的問題。
隱藏狀態欄、工具條,可以將其當作一個浮動的窗體,只需通過各自的句柄將ShowWindow()函數的參數設成SW_HIDE即可將這幾個窗體隱藏,同視圖非常類似,在需要顯示的時候可以用SW_SHOW標志將其顯示出來。在此需要說明的是在進行全屏操作之前需要將當前的視圖設置保存好,這在從全屏恢復為原始狀態時需要用到。該操作也比較簡單,只需簡單調用API函數GetWindowRect()即可。至於標題欄的隱藏就不是簡單的隱藏窗口了,這涉及到窗體風格的修改,要把WS_CAPTION風格從現有的窗體風格中剝離出來。這可以先用GetWindowLong()獲取到當前的窗體風格,然後通過邏輯運算將WS_CAPTION風格從中剝離開來,最後再用SetWindowLong()函數將修改後的窗體風格設置為當前的窗體風格。至於系統菜單的隱藏也可以很方便的加以實現:先保存當前菜單,然後將菜單設置為"空"就實現了菜單的隱藏。各個窗體都隱藏好後剩下的工作就是將編輯視圖放大到滿屏,可以用this來獲取當前的視圖指針,並把ShowWindow ()函數的參數設為SW_SHOWMAXIMIZED就最終完成了整個全屏放大的全過程。
至於從全屏恢復到初始狀態則完全是上述過程的逆操作:通過邏輯運算把WS_CAPTION風格加入到窗體風格中,恢復標題欄的顯示;通過將狀態條和工具條的ShowWindow()函數的標志參數設成WM_SHOW將其分別予以恢復;系統菜單也可以通過從保存好的原始菜單中讀取並重新設置來恢復其原始面貌。現在僅把隱藏的各個窗體顯示了出來,窗體還是處於滿屏狀態,所以還要通過MoveWindow()函數把窗體的位置恢復到全屏前的狀態,這也是我們為何在全屏時要保存窗體的一些原始參數的原因。
三、 程序的具體實現
前面部分在大體思路上對程序的設計實現進行了粗略的分析,但在實際編程中有不少的細節還未考慮進去,下面就根據前面的程序設計思路對其進行編碼,並結合其部分關鍵代碼進行講解說明,以便於更好的理解本程序的實現方法:
全屏顯示部分:
//通過設置SW_HIDE參數隱藏當前的工具條、任務欄
m_bToolBarWasVisible=(m_wndToolBar.IsWindowVisible()!=0);
m_wndToolBar.ShowWindow(SW_HIDE);
m_bStatusBarWasVisible=(m_wndStatusBar.IsWindowVisible()!=0);
m_wndStatusBar.ShowWindow(SW_HIDE);
……
//由於在全屏狀態下沒有系統菜單和工具條,所以需要顯示一個浮動的工具條按鈕用於//從全屏狀態下返回到正常狀態。
//首先創建一個工具條對象,並把一個工具條資源裝載進來,同時對工具條的風格進行//設置:
m_pwndFullScreenBar=new CToolBar;
m_pwndFullScreenBar->Create(this);
m_pwndFullScreenBar->LoadToolBar(IDR_FULLSCREEN);
m_pwndFullScreenBar->SetBarStyle(m_pwndFullScreenBar->GetBarStyle() |
CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
//浮動按鈕的效果
m_pwndFullScreenBar->ModifyStyle(0, TBSTYLE_FLAT);
m_pwndFullScreenBar->EnableDocking(0);
//設置返回到正常狀態下的按鈕的位置
CPoint pt(300,200);
FloatControlBar(m_pwndFullScreenBar,pt);
//在放大到滿屏前預先保存當前的窗口位置
GetWindowRect(&m_mainRect);
//通過改變窗口風格來隱藏標題欄
LONG style=::GetWindowLong(m_hWnd,GWL_STYLE);
style&=~WS_CAPTION;
::SetWindowLong(m_hWnd,GWL_STYLE,style);
int screenx=GetSystemMetrics(SM_CXSCREEN);
int screeny=GetSystemMetrics(SM_CYSCREEN);
//重新改變大小:
SetWindowPos(NULL,0,0,screenx,screeny,SWP_NOZORDER);
style=::GetWindowLong(m_hWnd,GWL_STYLE);
m_bChildMax=(style & WS_MAXIMIZE)?true:false;
//保存原有的系統菜單,並將當前菜單設置為空
CMenu* pOldMenu=GetMenu();
m_OrgMenu.Attach(pOldMenu->Detach());
SetMenu((CMenu*)NULL);
//在其他窗體隱藏好後,將編輯視圖放大到滿屏
this->ShowWindow (SW_SHOWMAXIMIZED);
……
至於從全屏恢復到初始狀態的這部分代碼則相對比較簡單,只需依次將隱藏的各個窗體和菜單恢復出來並將視圖移動到原來大小即可,該段代碼許多地方同放大到全屏時的代碼相似,只是參數有所差異而已。下面就是恢復部分的主要代碼:
……
//將保存的系統菜單恢復出來
SetMenu(&m_OrgMenu);
m_OrgMenu.Detach();
//釋放掉在全屏時創建的工具條指針對象,由於是用new創建的,在系統堆中為指針分//配地址空間,在程序退出時不能自動釋放,所以必須要用delete顯式地進行釋放
delete m_pwndFullScreenBar;
//把前面剝離出去的WS_CAPTION風格在加入到窗體風格中。
LONG style=::GetWindowLong(m_hWnd,GWL_STYLE);
style|=WS_CAPTION;
::SetWindowLong(m_hWnd,GWL_STYLE,style);
//顯示工具條、任務欄
if(m_bToolBarWasVisible)
m_wndToolBar.ShowWindow(SW_SHOW);
if(m_bStatusBarWasVisible)
m_wndStatusBar.ShowWindow(SW_SHOW);
MoveWindow(&m_mainRect);
RecalcLayout();
……
小結:
本文主要是針對單文檔框架的程序進行設計的,由於不涉及到子窗體,因此比較簡單。對於多文檔的全屏放大,實現方法在總體思路上是與之相一致的。只是在處理全屏顯示與恢復時需要將程序子框架也響應的進行放大與縮小,標題欄也要通過改變窗口風格的方式來隱藏與恢復顯示。本程序對於其他基於非編輯視圖的程序也是適用的。本文所述程序在Windows 2000 Professional下由Microsoft Visual C++ 6.0編譯通過。