分类:C#、Android、VS2015;
创建日期:2016-03-11
一、简介
MediaPlayer:适合每次播放一个音频资源或者音频文件的场合。
SoundPool:适合同时播放多个音频资源或者音频文件的场合。
二、用MediaPlayer播放
在安卓系统中,播放音频最简单的方法是使用内置的媒体播放器(MediaPlayer类)。MediaPlayer既可以播放本地文件,也可以播放来自URL的网络数据流。
1、创建MediaPlayer实例
有两种创建MediaPlayer实例的办法,
办法1:
MediaPlayer player = MediaPlayer.Create(this, Resource.Raw.test);
用MediaPlayer.Create创建实例时可直接指定数据源。
办法2:
MediaPlayer player = new MediaPlayer();
2、数据源
有3种。
(1)播放raw文件夹下的资源文件
应用程序自带的音乐资源一般保存到raw文件夹下,下面的代码演示了如何播放Resource/raw下的媒体文件:
MediaPlayer mPlayer=MediaPlayer.Create(this, Resource.Raw.MyAudio);
mPlayer.Start();
注意:这种方式主要适用于播放应用程序自带的容量较小的资源文件,例如接听电话时播放的音乐、按键音、开机启动音、信息提示音等都可以随应用程序一块发布。
(2)播放来自文件系统的媒体文件
指播放Android默认的系统标准文件夹下、Assets文件夹下、SD卡中的媒体文件,这些文件都属于文件系统。
以下描述了使用MediaPlayer从文件系统中播放音频的步骤:
- 初始化MediaPlayer对象。
- 通过SetDataSource方法(同步方式)或者SetDataSourceAsync方法(异步方式)设置要播放的文件。
- 调用Prepare方法(同步方式)或者PrepareAsync方法(异步方式)初始化播放器。
- 调用Start方法开始音频播放。
- 注意采用这种方式时,播放顺序非常重要:先设置数据源、同步播放设备,最后再调用Start方法播放。
播放来自文件系统的媒体文件时,可通过MediaPlayer的SetDataSource()方法指定数据源,该方法的重载形式很多,常用有:
SetDataSource (string path)
SetDataSource (FileDescriptor fd)
SetDataSource (Context context, Uri uri)
SetDataSource (FileDescriptor fd, long offset, long length)
(3)播放来自网络的媒体流
对于用URL指定的媒体流,有两种播放形式。
方式1:与播放本地资源文件的处理办法相似。
方式2:与播放本地文件系统的处理办法相似。
3、播放控制
MediaPlayer只能从标准移动设备(扬声器、蓝牙耳机)中播放音频,不能从通话用的话筒中播放音频。
调用Pause方法可暂停播放:player.Pause();
调用Start方法恢复播放:player.Start();
调用Stop方法停止播放:player.Stop();
当不再需要播放器时,必须调用player.Release();将其从内存中释放。
三、用SoundPool播放
SoundPool适合同时播放多个音频资源或者音频文件的场合。比如游戏中同时出现的多个声音和背景音乐。
四、例20-1--AudioPlayDemo
下面通过例子说明播放音频文件最基本的用法。
1、运行截图
2、设计步骤
说明:SD卡Download文件夹下的音乐文件(ch2001dj2.mp3)是通过执行代码拷进去的(没有就复制,有了就不复制了)。其他铃声和音乐文件需要自己手工拖放到项目中对应的文件夹下。
(1)在raw和Assets下分别添加一些音频文件
由于是学习基本用法,所以文件自己随便找吧。
本示例放到raw文件夹下的文件有:
铃声:ch2001ringin1.wav
开枪:ch2001ZR35.wav
音乐:ch2001dj1.mp3
本示例放到Assets文件夹下文的件有:
音乐:ch2001dj2.mp3
(2)添加ch2001Main.axml文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:id="@+id/ch2001_btnRawRing" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="播放RAW下的铃声资源" /> <Button android:id="@+id/ch2001_btnRawMusic" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="播放RAW下的音乐资源" /> <Button android:id="@+id/ch2001_btnAssetsMusic" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="播放附件下的音乐文件" /> <Button android:id="@+id/ch2001_btnDownloadMusic" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="播放SD卡中的音乐文件" /> <Button android:id="@+id/ch2001_btnSoundPool" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="同时播放多个音乐" /> <Button android:id="@+id/ch2001_btnStop" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="停止播放" android:layout_marginTop="30dp" /> </LinearLayout>
(3)添加ch2001MainActivity.cs文件
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Android.App; using Android.Content; using Android.OS; using Android.Runtime; using Android.Views; using Android.Widget; using Android.Media; using System.Threading.Tasks; using System.IO; namespace MyDemos.SrcDemos { [Activity(Label = "例20-1 音频播放基本用法")] public class ch2001MainActivity : Activity { private MediaPlayer player = null; private SoundPool soundPool; private SortedList<int, int> sounds; protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.ch2001Main); soundPool = new SoundPool(maxStreams: 2, streamType: Android.Media.Stream.Music, srcQuality: 100); sounds = new SortedList<int, int>(); //0:不循环,-1:循环 sounds.Add(soundPool.Load(this, Resource.Raw.ch2001ringin1, 1), -1); sounds.Add(soundPool.Load(this, Resource.Raw.ch2001ZR35, 1), -1); var btnRawRing = FindViewById<Button>(Resource.Id.ch2001_btnRawRing); btnRawRing.Click += delegate { StopPlayer(); try { player = MediaPlayer.Create(this, Resource.Raw.ch2001ringin1); player.Start(); } catch (Exception ex) { Console.WriteLine(ex.StackTrace); } }; var btnRawMusic = FindViewById<Button>(Resource.Id.ch2001_btnRawMusic); btnRawMusic.Click += delegate { StopPlayer(); try { player = MediaPlayer.Create(this, Resource.Raw.ch2001dj1); player.Start(); } catch (Exception ex) { Console.WriteLine(ex.StackTrace); } }; var btnAssetsMusic = FindViewById<Button>(Resource.Id.ch2001_btnAssetsMusic); btnAssetsMusic.Click += delegate { StopPlayer(); try { var fd = Assets.OpenFd("ch2001dj2.mp3"); player = new MediaPlayer(); player.Reset(); player.SetDataSource(fd.FileDescriptor); player.Prepare(); player.Start(); } catch (Exception ex) { Console.WriteLine(ex.StackTrace); } }; var btnDownloadMusic = FindViewById<Button>(Resource.Id.ch2001_btnDownloadMusic); btnDownloadMusic.Click += delegate { StopPlayer(); try { string path = GetDownloadFile("ch2001dj2.mp3"); player = new MediaPlayer(); player.Reset(); player.SetDataSource(path); player.Prepare(); player.Start(); } catch (Exception ex) { Console.WriteLine(ex.StackTrace); } }; var btnSoundPool = FindViewById<Button>(Resource.Id.ch2001_btnSoundPool); btnSoundPool.Click += delegate { StopPlayer(); AudioManager mgr = (AudioManager)GetSystemService(Context.AudioService); float currentStreamVolume = mgr.GetStreamVolume(Android.Media.Stream.Music); float maxStreamVolume = mgr.GetStreamMaxVolume(Android.Media.Stream.Music); float volume = currentStreamVolume / maxStreamVolume; foreach (var v in sounds) { soundPool.Play(v.Key, volume, volume, 1, v.Value, 1.0f); } }; var btnStop = FindViewById<Button>(Resource.Id.ch2001_btnStop); btnStop.Click += delegate { StopPlayer(); }; } protected override void OnDestroy() { base.OnDestroy(); StopPlayer(); soundPool.Release(); } /// <summary> /// 同时播放多个音频 /// </summary> /// <param name="soundID">音频资源的id</param> /// <param name="loop">0:不循环,-1:循环</param> private void PlaySound(int soundID, int loop) { AudioManager mgr = (AudioManager)GetSystemService(Context.AudioService); float currentStreamVolume = mgr.GetStreamVolume(Android.Media.Stream.Music); float maxStreamVolume = mgr.GetStreamMaxVolume(Android.Media.Stream.Music); float volume = currentStreamVolume / maxStreamVolume; soundPool.Play(soundID, volume, volume, 1, loop, 1.0f); } private void StopPlayer() { if (player != null) { if (player.IsPlaying) { player.Stop(); } player.Release(); player = null; } if (soundPool != null) { foreach (var v in sounds) { soundPool.Stop(v.Key); } } } /// <summary> /// 该方法仅为了演示如何将Assets下的文件复制到SD卡上 /// 如果SD卡的Download文件夹下不存在指定的文件,就将其复制到该文件夹下。 /// 如果存在,直接返回路径 /// </summary> /// <param name="fileName">Assets文件夹下的文件名</param> /// <returns>SD卡的Download文件夹下的文件路径</returns> private string GetDownloadFile(string fileName) { //注意此操作需要 android.permission.WRITE_EXTERNAL_STORAGE 权限 //由于第3章已经添加过此权限,所以该例子不需要再添加了 //SD卡Download文件夹下的文件路径 string filePath = string.Format("{0}/{1}/{2}", Android.OS.Environment.ExternalStorageDirectory.Path, Android.OS.Environment.DirectoryDownloads, fileName); if (File.Exists(filePath) == false) { //如果不存在,就将Assets文件夹下的指定文件复制到SD卡的该文件夹下 var fromStream = Assets.Open(fileName); int size = 32 * 1024; using (FileStream toStream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite)) { int n = -1; byte[] buffer = new byte[size]; while ((n = fromStream.Read(buffer, 0, size)) > 0) { toStream.Write(buffer, 0, n); } } } return filePath; } } }