AndroidのメディアAPI

Androidプラットフォームには、今時の組み込み用OSに求められるようなマルチメディア機能が含まれています。マルチメディア機能を使うのは、Androidの他部分と全く同じようにIntentとアクティビティのメカニズムを利用するだけなので、単純明快です。

マルチメディア機能

Androidプラットフォームは音声と映像の両方を再生する機能を持っています。またこのとき、アプリケーション内リソースからの再生や、ファイルシステム上の単独ファイル再生、データコネクションからのストリーミングといった様々な方法をとることが可能です。メディア再生にはandroid.media.MediaPlayerクラスを利用します。

Androidプラットフォームはまた、音声や映像の記録にも対応しています。メディア記録にはandroid.media.MediaRecorderクラスを利用します。お気付きのようにエミュレータには音声や映像をキャプチャし、記録するためのハードウェアがありませんが、これらのAPIを用いることで将来の出荷用デバイスに向けての開発を行うことが出来ます。

メディアリソースの再生

Rawリソースからの再生

最もよく利用されるのは、アプリケーション内でメディア、特に音声を再生することでしょう。これは以下のように、簡単に行うことが出来ます。

  1. サウンド(あるいは他のメディアリソース)をプロジェクト内のres/rawフォルダに配置し、Eclipseプラグイン(あるいはaapt)がそれを見つけてRクラスからリソースとして参照出来る形に出来るようにします。
  2. MediaPlayer.createメソッドを用いて、(1)で埋め込んだリソースと関連付いたMediaPlayerのインスタンスを作成し、まずインスタンス内のprepare()を呼び、次にstart()メソッドを呼び出します。
    MediaPlayer mp = MediaPlayer.create(context, R.raw.sound_file_1);
    mp.prepare();
    mp.start();

ファイルからの再生

以下のようにしてファイルシステムから直接ファイル再生を行うことも出来ます。

  1. newを利用して、MediaPlayerのインスタンス作成を行います
  2. setDataSource()に再生したいファイルのパス文字列を渡します
  3. prepare()を呼んだ上でstart()メソッドを呼び出します
    MediaPlayer mp = new MediaPlayer();
    mp.setDataSource(PATH_TO_FILE);
    mp.prepare();
    mp.start();

注意: mpがnullであることも考えられるので、newを行った後でnullチェックを行うようにして下さい。また、setDataSource()メソッドを呼び出した時点で、指定したファイルが見つからない場合にIllegalArgumentExceptionやIOExceptionが発生することも考えられるので、こちらの対応も必要です。

URLからの再生

メディア再生の最も楽な方法は、Intentメカニズムを利用して、再生したいメディアのURLを渡すというものです。これは、Media Playerからオンラインのメディアにアクセスする際に有効でしょう。

  1. 再生したいメディアを指すandroid.net.ContentURIを作成します。
  2. Intent.VIEW_ACTIONと、(1)で作成したURIを用いてIntentを作成します。
  3. (必須)再生対象コンテンツのMIMEタイプを設定します。これを忘れるとVIEW_ACTIONIntent側では渡されたURLに対して何をすれば良いのかが分かりません。
  4. startActivity()またはstartSubActivity()を呼び出します。

最もシンプルな方法はVIEW_ACTIONと再生対象ファイルのContentURIをつけてIntentを作成し、setType()によりMIMEタイプを設定し、Intentを開始するというもので、この場合後の処理はMedia Playerアクティビティが全てやってくれます。

    ContentURI myURL = new ContentURI("http://myserver.com/link/to/my.mp3");
    Intent intent = new Intent(Intent.VIEW_ACTION, myURL);
    intent.setType("audio/*");
    startActivity(intent);

注意: 音声ファイルは標準的な出力デバイスにしか出すことが出来ません。現時点ではデバイスのスピーカかBluetoothヘッドセットのみの対応となります。また通話録音ファイル[※1]を再生することは出来ません。

メディアを記録する

ご想像の通り、メディアの記録は再生に比べると若干複雑ですが、必要な設定が増えるだけでさほど難しくはありません。

  1. newを用いてandroid.media.MediaRecorderの新規インスタンスを作成します。
  2. android.content.ContentValuesの新規インスタンスを作成し、標準的なプロパティ(TITLEやTIMESTAMP)と重要なMIME_TYPEの設定を行います。
  3. データの保存先を指定します(ここでは、android.content.ContentResolverを用いてContentデータベース内にエントリ作成を行い、保存先パスとして自動割当を行うことが出来ます)
  4. 推奨事項ながらも、映像については任意でMediaRecorder.setPreviewDisplay()を用い、アクティビティ上のビューサーフェス上に現在録画されている映像のプレビュー表示を行うことが出来ます。
  5. 映像についてはMediaRecorder.setVideoSource()により映像ソース設定を行います。MediaRecorder.VideoSource.CAMERAを使うこともあるでしょう。
  6. 同様にして音声についてはMediaRecorder.setAudioSource()によりソース設定を行います。こちらではMediaRecorder.AudioSource.MICを使うこともあるでしょう。
  7. 出力フォーマット、映像サイズ、フレームレートの設定を行います。
  8. 音声(任意で映像も)エンコーダを設定します。
  9. ここでようやく設定が終わり、prepare()の呼出し後にstart()を呼んで記録を開始出来ます。停止時にはstop()の呼出し後にrelease()を呼び出します。
  10. 以下に、全容をスッキリと理解するためのサンプルコードを示します。

    記録開始部分

        recorder = new MediaRecorder();
        ContentValues values = new ContentValues(3);
    
        values.put(Video.MediaColumns.TITLE, SOME_NAME_HERE);
        values.put(Video.MediaColumns.TIMESTAMP, System.currentTimeMillis());
        values.put(Video.MediaColumns.MIME_TYPE, recorder.getMimeContentType());
        
        contentResolver = new ContentResolver();
        
        ContentURI base = Video.Media.INTERNAL_CONTENT_URI;
        ContentURI newUri = contentResolver.insert(base, values);
        
        if (newUri == null) {
            // 新規のコンテンツエントリを作成出来なかった場合。
            // 例外処理を行う必要あり。
        }
        
        String path = contentResolver.getDataFilePath(newUri);
    
        // ここでsetPreviewDisplay()を使ってView上にプレビュー表示が可能。
        
        recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        recorder.setVideoSize(176, 144); // QCIF
        recorder.setVideoFrameRate(15);
        recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        recorder.setOutputFile(path);
        
        recorder.prepare();
        recorder.start();
    

    記録終了部分

        recorder.stop();
        recorder.release();