Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Ringtoneを再生する時にFileDescriptorを使いたい

1,328 views
Skip to first unread message

トムキャット

unread,
Jul 1, 2011, 2:05:44 AM7/1/11
to 日本Androidの会
トムキャットです。

着信音か通知音をRingtonePreferenceで選び、それをMediaPlayerで再生しています。簡略化していますが、次のようなコード
です。(実際にはurlは固定ではありません。)

String url;
url = Settings.System.DEFAULT_NOTIFICATION_URI.toString();
Uri ringtoneUri = Uri.parse(url);
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(context,ringtoneUri);
mp.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
mp.setLooping(false);
mp.prepare();
mp.start();

多くの場合はこれでいいのですが、これだとsetDataSourceに失敗する場合があることを、ACRAのクラッシュレポートから認知していまし
た。(自分の端末ではどうしても再現しませんが。)そして、IS03内蔵の長めの着信音を使っていたところ、これまで見たことのない、

“PVMFErrNotSupported”
“Prepare failed.: status=0×1″

というエラーが起きました。これは必ず起きるわけではなく、何度も再生しているとふいに起きます。理由がさっぱり分かりません。で、

http://blog.pocketjourney.com/2009/12/27/android-streaming-mediaplayer-tutorial-updated-to-v1-5-cupcake/

によると、setDataSourceにはパスではなくて、FileDescriptorを渡すのが良い、とあります。

ここから質問です。

①RingtonePreferenceから得た"content://settings/system/notification_sound"など
のurlから、
 FileDescriptorを手に入れるにはどうすればいいでしょうか。
②MediaPlayterでPVMFErrNotSupportedを避けるにはsetDataSourceにFileDescriptor渡すべ
き、
 というのは「よく知られていること」なのでしょうか。

トムキャット

unread,
Jul 2, 2011, 2:03:59 AM7/2/11
to 日本Androidの会
トムキャットです。

この、MediaPlayer.prepare()に失敗する問題を調べていて、IS03で問題を起こす、起こさないの「差」となるAPIコールを特定
できました。

RingtoneManager.getRingtone(context,ringtoneUri);

です。これで選んでいるRingtoneが正しいものであることを戻り値で判定しているのですが、これがあると、6~7回再生すると問題が再現します。
で、シャープの開発者用フォーラムで質問中です。

このこととは別で、setDataSourceにはパスではなくて、FileDescriptorを渡したいと思っていますので、まだこの質問は生きて
います。


On 7月1日, 午後3:05, トムキャット <dailyti...@gmail.com> wrote:
> トムキャットです。
>
> 着信音か通知音をRingtonePreferenceで選び、それをMediaPlayerで再生しています。簡略化していますが、次のようなコード
> です。(実際にはurlは固定ではありません。)
>
> String url;
> url = Settings.System.DEFAULT_NOTIFICATION_URI.toString();
> Uri ringtoneUri = Uri.parse(url);
> MediaPlayer mp = new MediaPlayer();
> mp.setDataSource(context,ringtoneUri);
> mp.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
> mp.setLooping(false);
> mp.prepare();
> mp.start();
>
> 多くの場合はこれでいいのですが、これだとsetDataSourceに失敗する場合があることを、ACRAのクラッシュレポートから認知していまし
> た。(自分の端末ではどうしても再現しませんが。)そして、IS03内蔵の長めの着信音を使っていたところ、これまで見たことのない、
>
> “PVMFErrNotSupported”
> “Prepare failed.: status=0×1″
>
> というエラーが起きました。これは必ず起きるわけではなく、何度も再生しているとふいに起きます。理由がさっぱり分かりません。で、
>
> http://blog.pocketjourney.com/2009/12/27/android-streaming-mediaplaye...

yoshiyuki kanno

unread,
Jul 2, 2011, 3:49:56 AM7/2/11
to android-g...@googlegroups.com
菅野です。

試してはおりませんが、
メディアプレイヤーのソースをみると、

715             ContentResolver resolver = context.getContentResolver();
716             fd = resolver.openAssetFileDescriptor(uri, "r");
717             if (fd == null) {
718                 return;
719             }
720             // Note: using getDeclaredLength so that our behavior is the same
721             // as previous versions when the content provider is returning
722             // a full file.
723             if (fd.getDeclaredLength() < 0) {
724                 setDataSource(fd.getFileDescriptor());
725             } else {
726                 setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getDeclaredLength());
727             }

こんな感じでContentResolverのopenAssetFileDescriptorをつかって内部的にuriをディスクリプタに変換しています。
なので、これを流用すればトムキャットさんの意図するFileDescriptorは取れると思いますが、
内部的に同じNativeメソッドの呼び出しになる場合があるので、問題の解決には至らないかもしれません。

※URIのschemeが「file」の場合はsetDataSource(String)のNativeメソッド呼び出し、上記の引用したロジック中に例外が発生した場合は
setDataSource(String, Map<String,String>)のNativeメソッドにいくので、これらのケースの場合は何らかの違いが見られるかもしれません。


※AudioEngine周りのNativeレイヤの部分も見てみたのですが
「PVMFErrNotSupported」になるケースがあまりにも多すぎるため、根本原因をつきとめるのは断念しました。。。
本気で原因特定するのであればNativeデバッグする必要がありそうです。

2011年7月2日15:03 トムキャット <daily...@gmail.com>:
--
このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。
このグループから退会するには、android-group-j...@googlegroups.com にメールを送信してください。
詳細については、http://groups.google.com/group/android-group-japan?hl=ja からこのグループにアクセスしてください。


トムキャット

unread,
Jul 3, 2011, 12:32:35 AM7/3/11
to 日本Androidの会
菅野さん

トムキャットです。ていねいな回答をありがとうございました。
教えて頂いた方法で、uriをファイルディスクリプタに変換し、setDataSourceできました。
僕が持っている端末ではsetDataSource(context,uri)が失敗するものはないのですが、ACRAのレポートには時々、
失敗した記録が上がります。で、これはsetDataSource(fd)だと回避できるかも?という期待があります。

現在βテスト中のアプリに適用して様子を見ます。

ありがとうございました。

On 7月2日, 午後4:49, yoshiyuki kanno <nekota...@gmail.com> wrote:
> 菅野です。
>
> 試してはおりませんが、http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;...
> メディアプレイヤーのソースをみると、
>
> 71<http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;...>5
> ContentResolver resolver = context.getContentResolver();
> 716<http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;...>
> fd = resolver.openAssetFileDescriptor(uri, "r");
> 717<http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;...>
> if (fd == null) {
> 718<http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;...>
> return;
> 719<http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;...>
> }
> 720<http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;...>
> // Note: using getDeclaredLength so that our behavior is
> the same
> 721<http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;...>
> // as previous versions when the content provider is
> returning
> 722<http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;...>
> // a full file.
> 723<http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;...>
> if (fd.getDeclaredLength() < 0) {
> 724<http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;...>
> setDataSource(fd.getFileDescriptor());
> 725<http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;...>
> } else {
> 726<http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;...>
> setDataSource(fd.getFileDescriptor(),
> fd.getStartOffset(), fd.getDeclaredLength());
> 727<http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;...>
> }
>
> こんな感じでContentResolverのopenAssetFileDescriptorをつかって内部的にuriをディスクリプタに変換しています。
> なので、これを流用すればトムキャットさんの意図するFileDescriptorは取れると思いますが、
> 内部的に同じNativeメソッドの呼び出しになる場合があるので、問題の解決には至らないかもしれません。
>
> ※URIのschemeが「file」の場合はsetDataSource(String)のNativeメソッド呼び出し、上記の引用したロジック中に例外が発生した場合は
> setDataSource(String,
> Map<String,String>)のNativeメソッドにいくので、これらのケースの場合は何らかの違いが見られるかもしれません。
>
> ※AudioEngine周りのNativeレイヤの部分も見てみたのですが
> 「PVMFErrNotSupported」になるケースがあまりにも多すぎるため、根本原因をつきとめるのは断念しました。。。
> 本気で原因特定するのであればNativeデバッグする必要がありそうです。
>
> 2011年7月2日15:03 トムキャット <dailyti...@gmail.com>:
Reply all
Reply to author
Forward
0 new messages