SaveRingtoneTaskを使って着メロを登録する

Windows Phone 7.5(Windows Phone OS 7.1)からSaveRingtoneTaskを使って着信音の登録が出来るようになりました。登録した着信音は、settings(設定アプリ)のringtones+soundsから設定が可能です。アプリケーションから登録した着信音をどのようにして設定するのかついても後述しています。

着信音として設定するには、以下の要項を守った楽曲ファイルである必要があります。

  • MP3もしくはWMAフォーマットであること
  • 40秒以下の長さであること
  • DRM保護されていないこと
  • サイズが1MB以下であること

Windows Phone SDK 7.1 Beta 2のWindows Phone Emulatorでは、実際に楽曲の長さが40秒を超えたファイルでも設定することが出来ましたが、アプリケーションとして正しい動きを保証しなければいけない場合、上記の要項を守っておくべきだと思われます。

今回は、アプリケーションのリソースとしてMP3ファイルを追加しておき、着信音として登録する方法についてご紹介させて頂きます。

プロジェクトにサンプルMP3ファイルを追加する

MP3ファイルをプロジェクトに追加します。ソリューションエクスプローラーで、プロジェクトを右クリックして[Add]->[Existing Item...]を選択します。

任意のファイルを追加してください。ここでは「sample.mp3」を追加しました。以降「sample.mp3」の部分は、任意のファイル名で読み替えてください。

リソースとしてビルド時にアプリケーション内に楽曲ファイルを含めてしまいたいので、ソリューションエクスプローラーから「sample.mp3」を選択し、プロパティウィンドウにあるBuild Actionの項目を「Content」に変更します。

Build Actionを「Content」に変更すると、Application.GetResourceStreamメソッドでファイル名を指定するだけで、リソースを取り出すことが出来るようになります。

リソースファイルを分離ストレージへ保存する

一般的なアプリケーションでSaveRingtoneTaskを使用するケースを考えた場合、アプリケーション内のリソースを着信音に登録するようなケースはほぼなく、インターネット上の楽曲ファイルをダウンロードしてきて、着信音に登録することが殆どだと思いますので、分離ストレージから着信音を設定出来るようにします。

まず、アプリケーションリソースとして持っているMP3ファイルを分離ストレージに保存します。

なんらかのストリームから分離ストレージへの保存処理自体は「Microsoft Translator APIを使用して翻訳をおこなう/テキストを読ませる」のものを流用しています。

Application.GetResourceStreamメソッドでURIを指定して、楽曲データのリソースを取り出します。取り出したリソースのストリームから、IsolatedStorageFileを使って分離ストレージへの書き出しを行っております。

// アプリケーションリソースファイルを分離ストレージへ保存する
private void SaveFileTo(string fileName)
{
    var resourceStream = Application.GetResourceStream(new Uri(fileName, UriKind.Relative));
 
    var store = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication();
    // 以前に作成したファイルが残っている場合は削除する
    if (store.FileExists(fileName))
    {
        store.DeleteFile(fileName);
    }
 
    // 読み込んだストリームを分離ストレージのファイルに書き出す
    using (var strm = store.CreateFile(fileName))
    using (var reader = new System.IO.BinaryReader(resourceStream.Stream))
    {
        var bytes = new byte[256 * 1024];
        while (true)
        {
            int read = reader.Read(bytes, 0, bytes.Length);
            if (read <= 0) break;
            strm.Write(bytes, 0, read);
        }
    }
 
    store.Dispose();
}
' アプリケーションリソースファイルを分離ストレージへ保存する
Private Sub SaveFileTo(fileName As String)
	Dim resourceStream = Application.GetResourceStream(New Uri(fileName, UriKind.Relative))
 
	Dim store = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication()
	' 以前に作成したファイルが残っている場合は削除する
	If store.FileExists(fileName) Then
		store.DeleteFile(fileName)
	End If
 
	' 読み込んだストリームを分離ストレージのファイルに書き出す
	Using strm = store.CreateFile(fileName)
		Using reader = New System.IO.BinaryReader(resourceStream.Stream)
			Dim bytes = New Byte(256 * 1024 - 1) {}
			While True
				Dim read As Integer = reader.Read(bytes, 0, bytes.Length)
				If read <= 0 Then
					Exit While
				End If
				strm.Write(bytes, 0, read)
			End While
		End Using
	End Using
 
	store.Dispose()
End Sub

SaveFileToメソッドにリソース名(例えばsample.mp3)を渡すと、アプリケーションそのものからリソースを取得して、分離ストレージへ同じリソース名で保存を行うことが出来るようになりました。

SaveRingtoneTaskを使って着信音を登録する

先ほどアプリケーションリソースを分離ストレージへ保存するメソッドを作りました。ボタンをタップされたのをトリガーにして着信音を登録してみましょう。MainPage.xamlに適当なボタンを配置して、Clickイベントにイベントハンドラを設定します。

<Button Content="SaveRingtone" Height="89" HorizontalAlignment="Left" Margin="6,322,0,0" x:Name="btnSaveRingtone" VerticalAlignment="Top" Width="444" Click="btnSaveRingtone_Click" />

ボタンがタップされると、btnSaveRingtone_Clickメソッドが呼び出され、SaveFileToメソッドを使ってリソースを分離ストレージへ保存します。

後は分離ストレージへ保存したMP3ファイルのパスを設定するだけなのですが、他のChooserと同じでShowメソッドを呼ぶ前にいくつかのプロパティを設定しておくことが出来ます。

DisplayNameプロパティを設定すると、Showメソッドで呼び出される登録画面の初期表示の着信音名を決めておくことが出来ます。

また他のアプリケーションから使わせなくするために、登録した着信音をDRM保護したい場合は、SaveRingtoneTaskのIsShareableプロパティにfalseを設定します。下記の例ではtrueを設定しています。

最後にSourceプロパティへ分離ストレージに保存したファイルパスを「isostore:/」というスキーマを使用して指定しています。http://のようにスラッシュを2つ付けないように気を付けてください。

今回使用するSaveRingtoneTaskを始め、登録や取得が完了した時点でCompletedイベントを発行するChooserは非同期で動作します。下記のサンプルコードでは、非同期処理を簡単に制御出来るようにReactive Extention(Rx)というフレームワークを使用します。

Reactive Extentionを使うには、Microsoft.Phone.ReactiveとSystem.Observableを参照しておく必要がありますので、ソリューションエクスプローラーから参照を追加を行っておいてください。

private void btnSaveRingtone_Click(object sender, RoutedEventArgs e)
{
    // アプリケーションリソースのMP3ファイルを分離ストレージに保存する
    SaveFileTo("sample.mp3"); 
 
    var saveRingToneTask = new SaveRingtoneTask();
    saveRingToneTask.DisplayName = "JUMP ON!";
    saveRingToneTask.IsShareable = true;
    saveRingToneTask.Source = new Uri("isostore:/sample.mp3");
 
    Observable.FromEvent<TaskEventArgs>(
        h => saveRingToneTask.Completed += h,
        h => saveRingToneTask.Completed -= h)
        .Subscribe(ex =>
        {
            // 着信音の保存に成功
            if (ex.EventArgs.TaskResult == TaskResult.OK)
                MessageBox.Show("Save Success!");
        });
    saveRingToneTask.Show();
}
Private Sub btnSaveRingtone_Click(sender As Object, e As RoutedEventArgs)
 
    ' アプリケーションリソースのMP3ファイルを分離ストレージに保存する
    SaveFileTo("sample.mp3")
 
    Dim saveRingToneTask = New SaveRingtoneTask()
    saveRingToneTask.DisplayName = "JUMP ON!"
    saveRingToneTask.IsShareable = True
    saveRingToneTask.Source = New Uri("isostore:/sample.mp3")
 
    Observable.FromEvent(Of TaskEventArgs)(
        Sub(h) AddHandler saveRingToneTask.Completed, h,
        Sub(h) RemoveHandler saveRingToneTask.Completed, h) _
    .Subscribe(Sub(ex)
                   ' 着信音の保存に成功
                   If ex.EventArgs.TaskResult = TaskResult.OK Then
                       MessageBox.Show("Save Success!")
                   End If
               End Sub)
    saveRingToneTask.Show()
End Sub

上記のコードが正しく実行されると、Save ringtone画面が表示されます。ここでシステムに登録する名前を設定して、アプリケーションバーのチェックボタンをタップすると、着信音が登録は完了です。

Windows Phone Emulatorでは、settings(設定アプリ)の「ringtones + sounds」の項目が表示されません。以降は、サンプルアプリケーションを実機にデプロイしたものを使用して確認したいと思います。画質が良くありませんがご了承ください。

一番上に表示されている項目「ringtones+sounds」を選択します。

いくつか設定項目がありますが「Ringtone」を選択します。写真上では画面中央の「Pure」が選択されている項目です。

Customの項目に、先ほど設定した名前で着信音が登録されているのを確認してください。「JUMP ON!」の左側にある再生ボタンをタップして、きちんと曲が再生されれば成功です。

登録した着信音を削除したい場合は、アイテムを長押しすると「delete」が表示されます。そのまま選択しましょう。

参考: