ここではアプリ内での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