一 前言
android提供了簡單的播放音頻和視訊的類MediaPlayer,它可以播放raw、assets、sdk、網絡上的音視訊資源,在前面已經介紹過MediaPlayer(點選檢視)。
二 音頻播放
播放音頻步驟:
(1)建立MediaPlayer對象執行個體;可以通過new建立該執行個體,也可以通過靜态方法create建立。 (2)裝載音頻資源,如果在(1)中你使用create建立的MediaPlayer,此時該步驟可省略,否則你将調用setDataSource添加音頻資源。 (3)調用prepare()或prepareAsync()方法來做播放前的準備工作,如果(2)省略的話,該步驟也要省略(即如果你掉用setDataSource方法添加音頻資源了,就要調用prepare()或prepareAsync()方法做播放前的準備工作,否則就不需要了)。 (4)調用MediaPlayer的start、stop、pause等方法控制播放過程。
1 播放raw中的音頻資源檔案
首先在res目錄建立目錄raw ,在raw添加你要播放的音頻資源檔案,然後就可以按照上述步驟就行了,建立MediaPlayer對象執行個體代碼如下:
private MediaPlayer player;
@AfterViews
void initData(){
player = new MediaPlayer();
// loadRaw();
}
播放音頻代碼如下:
void loadRaw(){
/*
* 判斷音頻是否在正在播放,如果是正在播放,
* 就要調用reset方法進行重置,此時player會處于空閑狀态,
* 如果不進行重置的話,再調用setDataSource設定資源時,會抛出異常 IllegalStateException
*/
if (player.isPlaying()){
// player.release();
player.stop();
}
player.reset();
// player = MediaPlayer.create(this, R.raw.hongyanjiu);
AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.hongyanjiu);
try {
player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
player.prepare();
player.start();
//設定播放監聽
setListener();
} catch (IOException e) {
e.printStackTrace();
}
}
說明,需要注意的是在裝載資源之前,先要判斷是否有資源正在播放,如果有的話就要調用stop停止播放,然後調用reset方法使MediaPlayer處于空閑狀态,否則的将會出現非法狀态異常。接下來看看是如何設定監聽的,這裡直接繼承了監聽類,如下:
public class MainActivity extends AppCompatActivity
implements MediaPlayer.OnCompletionListener,MediaPlayer.OnErrorListener ,
MediaPlayer.OnPreparedListener,MediaPlayer.OnSeekCompleteListener {
......
}
然後
void setListener(){
player.setOnCompletionListener(this);
player.setOnErrorListener(this);
player.setOnPreparedListener(this);
player.setOnSeekCompleteListener(this);
}
需要實作的方法,如下:
/**
* 音頻播放完成調用該方法
* @param mp
*/
@Override
public void onCompletion(MediaPlayer mp) {
Toast.makeText(this, "音頻播放完畢", Toast.LENGTH_SHORT).show();
}
/**
* 音頻播放錯誤調用該方法
* @param mp
* @param what 錯誤類型
* @param extra
* @return
*/
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Toast.makeText(this, "音頻播放發生錯誤", Toast.LENGTH_SHORT).show();
return false;
}
/**
* 當方法prepare被調用觸發該方法
* @param mp
*/
@Override
public void onPrepared(MediaPlayer mp) {
Toast.makeText(this, "音頻播放已就緒", Toast.LENGTH_SHORT).show();
}
/**
* 當調用seek方法時觸發該方法
* @param mp
*/
@Override
public void onSeekComplete(MediaPlayer mp) {
Toast.makeText(this, "音頻播放已seek", Toast.LENGTH_SHORT).show();
}
2 播放assets中的音頻資源檔案
首先在src/main目錄建立目錄assets ,在assets添加你要播放的音頻資源檔案,然後就可以按照上述步驟就行了,實作fang發如下:
void loadAsset(){
/*
* 判斷音頻是否在正在播放,如果是正在播放,
* 就要調用reset方法進行重置,此時player會處于空閑狀态,
* 如果不進行重置的話,再調用setDataSource設定資源時,會抛出異常 IllegalStateException
*/
// player.isLooping()
if (player.isPlaying()){
// player.release();
player.stop();
}
player.reset();
//AssetManage對象
AssetManager am = getAssets();
//打開指定音頻檔案
try {
AssetFileDescriptor afd = am.openFd("hongyanjiu.mp3");
//給MediaPlayer添加資源檔案
player.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(),afd.getLength());
//做準備工作:裝載音頻 使用setDataSource()方法添加資源 必須再調用prepare()裝載音頻, 而後才能調用start方法開始播放
afd.close();
player.prepare();
player.start();
setListener();
} catch (IOException e) {
e.printStackTrace();
}
}
說明擷取assets資源檔案需要用到AssetManage,而AssetManage可以通過Context.getAssets()擷取,然後調用AssetManage的openFd方法擷取音頻資源。
3 播放手機記憶體中的音頻資源檔案
在這裡我的示例是先把assets中的音頻資源copy到手機的sdk裡,再來播放資源檔案,copy實作代碼如下:
public void copyFileFromAssetToSDK(){
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) ){
path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + getPackageName();
}else {
path = Environment.getDataDirectory().getAbsolutePath() + File.separator + getPackageName();
}
File file = new File(path);
if (!file.exists()){
file.mkdirs();
}
//AssetManage對象
AssetManager am = getAssets();
try {
AssetFileDescriptor afd = am.openFd("hongyanjiu.mp3");
InputStream is = afd.createInputStream();
// InputStreamReader reader = new InputStreamReader(afd.createInputStream());
// OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(new File(path,"hongyanjiu.mp3")));
File needFile = new File(path,"hongyanjiu.mp3");
// if (!needFile.exists()){
// needFile.mkdirs();
// }
path = needFile.getAbsolutePath();
Log.e("音頻檔案路徑====>", path);
OutputStream os = new FileOutputStream(needFile);
int hasRead = 0;
byte[] buffer = new byte [1024];
while ((hasRead = is.read(buffer)) != -1){
os.write(buffer,0,hasRead);
}
os.flush();
os.close();
is.close();
afd.close();
} catch (IOException e) {
e.printStackTrace();
}
}
然後播放該音頻資源代碼如下:
void loadSDK(){
/*
* 判斷音頻是否在正在播放,如果是正在播放,
* 就要調用reset方法進行重置,此時player會處于空閑狀态,
* 如果不進行重置的話,再調用setDataSource設定資源時,會抛出異常 IllegalStateException
*/
if (player.isPlaying()){
// player.release();
player.stop();
}
player.reset();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
//動态判斷手機儲存空間的權限
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == -1 ||
ActivityCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE ) == -1){
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE},0x123);
}else {
try {
copyFileFromAssetToSDK();
if (TextUtils.isEmpty(path)){
return;
}
player.setDataSource(path);
player.prepare();
player.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}else {
try {
copyFileFromAssetToSDK();
if (TextUtils.isEmpty(path)){
return;
}
player.setDataSource(path);
player.prepare();
player.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4 播放網絡音頻資源
void loadNet(){
/*
* 判斷音頻是否在正在播放,如果是正在播放,
* 就要調用reset方法進行重置,此時player會處于空閑狀态,
* 如果不進行重置的話,再調用setDataSource設定資源時,會抛出異常 IllegalStateException
*/
if (player.isPlaying()){
player.stop();
}
player.reset();
Uri url = Uri.parse(urlPath);
try {
player.setDataSource(this,url);
player.prepare();
player.start();
} catch (IOException e) {
e.printStackTrace();
}
}
說明,urlPath為網絡音頻資源位址。最後不要忘記在onDestroy方法釋放資源:
@Override
protected void onDestroy() {
super.onDestroy();
if (player.isPlaying()){
player.stop();
player.release();
}
}
完整示例代碼點選檢視