ここではアプリ内でのBGMの再生を想定して説明します。
現時点でiOSとAndroidを共通で使えるXamarin.Formsのコンポーネントは提供されていませんので、プレーヤーは以下のものを利用しています。(※2016/8/22時点では動画コンポーネントのみ)
・iOS側:AVAudioPlayer
・Android側:MediaPlayer
事前準備
空のXamarin.Formプロジェクト(Portable Class Library)を作成します。
※ここでは、プロジェクト名を「AudioPlaySample」として作成してますが、好きに読み替えてください。
新規プロジェクトを作成すると、「AudioPlaySample」と「Droid」、「iOS」の3つのプロジェクトが作成されていると思います。
次に、そこに再生するための音楽(MP3形式)を登録します。
※ここでは、フリーBGMサイト「DOVA-SYNDROME」から、「Shall we meet?」を利用しています。
Androidアプリ側は「Droid」内の「Resources」フォルダを利用します。
「Resources」フォルダ内に「raw」フォルダを作成し、その中に音楽ファイルを入れます。
(Droid>Resources>raw>shall_we_meet.mp3])
iOSアプリ側は「iOS」内の「Resources」フォルダを利用します。
「Resources」フォルダ内にそのまま、音楽ファイルを入れます。
(iOS>Resources>shall_we_meet.mp3])
画面の作成
「AudioPlaySample.cs」のAppの部分に以下の形で、Content画面をコードで作成します。
※もし、XAMLで対応したい方は、イベント記述をうまく拾ってください。
まずはコマンド用に「class App」内に以下のIMediaPlayerインターフェイスを作成します。
・Play(非同期)
・Stop
共通処理[AudioPlaySample>AudioPlaySample.cs]
public interface IMediaPlayer
{
Task PlayAsync(string title);
void Stop();
}
次に、以下のコードでサクッと画面を作成します。(XAMLで対応しても構いません。)
public App()
{
Button btnPlay = new Button {
Text = "Play/Pause",
Command = new Command((obj) => {
DependencyService.Get<IMediaPlayer>().PlayAsync("shall_we_meet");
})
};
Button btnStop = new Button {
Text = "Stop",
Command = new Command((obj) => {
DependencyService.Get<IMediaPlayer>().Stop();
})
};
// The root page of your application
var content = new ContentPage {
Title = "AudioPlaySample",
Content = new StackLayout {
VerticalOptions = LayoutOptions.Center,
Children = {
btnPlay,
btnStop
}
},
Padding = new Thickness(10)
};
MainPage = new NavigationPage(content);
}
DependencyServiceを使ったオーディオサービスの作成
各プラットフォームごとにオーディオサービスの作成をします。
各プラットフォームに空のクラスで「MediaPlayer_Droid.cs」「MediaPlayer_iOS.cs」を作成して、以下のように修正します。
Android側[Droid>MediaPlayer_Droid.cs]
using System;
using System.Threading.Tasks;
using Xamarin.Forms;
using Android.Media;
[assembly: Dependency(typeof(AudioPlaySample.Droid.MediaPlayer_Droid))]
namespace AudioPlaySample.Droid
{
public class MediaPlayer_Droid : App.IMediaPlayer
{
MediaPlayer player = null;
private async Task StartPlayerAsync(string title)
{
var resourceId = (int)typeof(Resource.Raw).GetField(title).GetValue(null);
await Task.Run(() => {
if (player == null) {
player = new MediaPlayer();
player.SetAudioStreamType(Stream.Music);
player = MediaPlayer.Create(
global::Android.App.Application.Context,
resourceId
);
player.Looping = true;
player.Start();
} else {
if (player.IsPlaying == true) {
player.Pause();
} else {
player.Start();
}
}
});
}
private void StopPlayer()
{
if ((player != null)) {
if (player.IsPlaying) {
player.Stop();
}
player.Release();
player = null;
}
}
public async Task PlayAsync(string title)
{
await StartPlayerAsync(title);
}
public void Stop()
{
StopPlayer();
}
}
}
iOS側[iOS>MediaPlayer_iOS.cs]
using System;
using System.Threading.Tasks;
using Xamarin.Forms;
using AVFoundation;
using Foundation;
[assembly: Dependency(typeof(AudioPlaySample.iOS.MediaPlayer_iOS))]
namespace AudioPlaySample.iOS
{
public class MediaPlayer_iOS : App.IMediaPlayer
{
AVAudioPlayer player = null;
private async Task StartPlayerAsync(string title)
{
await Task.Run(() => {
if (player == null)
{
var url = NSUrl.FromFilename(title + ".mp3");
NSError _err = null;
player = new AVAudioPlayer(
url,
AVFileType.MpegLayer3,
out _err
);
player.NumberOfLoops = -1;//player.Looping = true;
player.PrepareToPlay();
player.Play();
} else {
if (player.Playing == true) {
player.Stop();
} else {
player.Play();
}
}
});
}
private void StopPlayer()
{
if (player != null) {
if (player.Playing) {
player.Stop();
}
player.Dispose();
player = null;
}
}
public async Task PlayAsync(string title)
{
await StartPlayerAsync(title);
}
public void Stop()
{
StopPlayer();
}
}
}
動作確認
サンプル画面では固定をしていますが、BGMファイル名を引数で指定すればリソース内にある音楽を選んで再生することが出来ます。
また、再生ボタンをもう一度押すことで、一時停止が可能になっています。
サンプルコードはこちら(GitHub)
(※サンプルでは経過時間の取得にも対応しています。)
備考
Xamarin.Formsとして比較的同じような機能を使って、シンプルに共用化を行いましたが、Androidでは音楽用のコンポーネントはほとんどなく、iOS側では逆に様々なメディアコンポーネントがあります。
今回はリソースからの呼び出しで対応しましたが、呼び出し先もファイルやAssets、メディアサービスなど多岐にわたりますし、メディアフォーマットでも対応、非対応があります。
そのため、利用状況によっては各プラットフォームでのコンポーネント選択が必要となってきますので、注意してください。
(音楽プレーヤーアプリを作成する場合なら、Xamarin.Formsを利用して共通化せずにXamarin.Nativeを使った方が効率はいいでしょう。)
Search index:
[Xamarin.Forms] Background Audio play
[Xamarin.Forms] background music player

