[セットトップ]androidマルチメディアとカメラの詳細3


オーディオフォーカスの処理
ある時点でactivityが1つしか実行できないにもかかわらず、Androidはマルチタスク環境である.これはオーディオを使用するアプリケーションに特別な挑戦をもたらした.1つのオーディオ出力しかないため、複数のメディアがそれを使用したい可能性がある.Android 2では.2以前は、この問題に対処するために組み込まれたメカニズムがなかったため、場合によっては悪いユーザ体験を招く可能性がある.例えば、あるユーザが音楽を聴いている場合、別のアプリケーションがユーザに重要なことを通知する必要がある場合、ユーザは音楽の音が大きいために聞けない可能性がある通知.Android 2から.2から、プラットフォームは、オーディオフォーカスと呼ばれるデバイスのオーディオ出力をどのように使用するかを協議する方法をアプリケーションに提供する.
アプリケーションが楽音や通知のようなオーディオを出力する必要がある場合は、常にオーディオフォーカスを要求する必要があります.フォーカスがあると、オーディオ出力を自由に使用することができます.しかし、フォーカスの変化を監視する必要があります.フォーカスが失われたと通知された場合は、直ちに音を殺すか、静音レベル(どちらを選択すべきかを示すフラグがある)に下げ、フォーカスを再取得した後にのみ大きな再生を再開すべきである.
将来のオーディオフォーカスは提携する.だから,アプリケーションはオーディオフォーカスの方针を守ることが望ましいが,システムに强制されたわけではない.もし一つのアプリケーションがオーディオフォーカスを失った后も大きな声で音楽を再生したいならば,システムはそれを阻止することはできない.しかし,ユーザーは体験が悪く,この鸟アプリケーションをアンインストールしたいと思っている.
オーディオフォーカスを要求するには、以下に示すように、AudioManagerからrequestAudioFocus()を呼び出す必要があります.
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
    AudioManager.AUDIOFOCUS_GAIN);

if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    //         
}

requestAudioFocus()の最初のパラメータはAudioManagerです.OnAudioFocusChangeListenerは、オーディオフォーカスの変更時にonAudioFocusChange()メソッドが呼び出されます.そのため、サービスとactivityでこのインタフェースを実現する必要があります.たとえば、次のようにします.
class MyService extends Service
                implements AudioManager.OnAudioFocusChangeListener {
    // ....
    public void onAudioFocusChange(int focusChange) {
        // Do something based on focus change...
    }
}

パラメータfocusChangeは、オーディオフォーカスがどのように変化したかを示します.これは、AudioManagerで定義されている定数です.
  • AUDIOFOCUS_GAIN:オーディオフォーカスを取得しました.
  • AUDIOFOCUS_LOSS:長い間オーディオフォーカスを失っています.すべてのオーディオの再生を停止しなければなりません.長い間オーディオフォーカスを取得できない可能性があると予想されているので、ここはリソースを整理するのに良い場所です.例えば、MediaPlayerを解放しなければなりません.
  • AUDIOFOCUS_LOSS_TRANSIENT:一時的にオーディオフォーカスを失うと、すぐに再取得されます.すべてのオーディオ再生を停止しなければなりませんが、すぐにフォーカスを再取得できる可能性があります.
  • AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:オーディオフォーカスを一時的に失ったが、完全に停止するのではなく、低音量で再生を継続することを許可された.
  • 次に例を示します.
    public void onAudioFocusChange(int focusChange) {
        switch (focusChange) {
            case AudioManager.AUDIOFOCUS_GAIN:
                // resume playback
                if (mMediaPlayer == null) initMediaPlayer();
                else if (!mMediaPlayer.isPlaying()) mMediaPlayer.start();
                mMediaPlayer.setVolume(1.0f, 1.0f);
                break;
    
            case AudioManager.AUDIOFOCUS_LOSS:
                // Lost focus for an unbounded amount of time: stop playback and release media player
                if (mMediaPlayer.isPlaying()) mMediaPlayer.stop();
                mMediaPlayer.release();
                mMediaPlayer = null;
                break;
    
            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                // Lost focus for a short time, but we have to stop
                // playback. We don't release the media player because playback
                // is likely to resume
                if (mMediaPlayer.isPlaying()) mMediaPlayer.pause();
                break;
    
            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                // Lost focus for a short time, but it's ok to keep playing
                // at an attenuated level
                if (mMediaPlayer.isPlaying()) mMediaPlayer.setVolume(0.1f, 0.1f);
                break;
        }
    }

    オーディオフォーカスAPIはAPIlevel 8(Android 2.2)以降でのみ可能であることを覚えておいてください.そのため、より早いAndroidバージョンをサポートしたい場合は、可能な場合に互換性のあるポリシーを使用して特性を使用する必要があります.不可能な場合は、should adopt a backward compatibility strategy that allows you touse this feature if available,and fall back seamlessly if not.
    オーディオフォーカスメソッドを反射的に呼び出すか、AudioFocusHelperという別のクラスですべてのオーディオフォーカス機能を実現して前方互換性を達成することができます.次のクラスは次のとおりです.
    public class AudioFocusHelper implements AudioManager.OnAudioFocusChangeListener {
        AudioManager mAudioManager;
    
        //         ,             ,    
        //       service          .
    
        public AudioFocusHelper(Context ctx, /*       */) {
            mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
            // ...
        }
    
        public boolean requestFocus() {
            return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
                mAudioManager.requestAudioFocus(mContext, AudioManager.STREAM_MUSIC,
                AudioManager.AUDIOFOCUS_GAIN);
        }
    
        public boolean abandonFocus() {
            return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
                mAudioManager.abandonAudioFocus(this);
        }
    
        @Override
        public void onAudioFocusChange(int focusChange) {
            //    service       
        }
    }
    
                    API level 8           AudioFocusHelper    .  :
    if (android.os.Build.VERSION.SDK_INT >= 8) {
        mAudioFocusHelper = new AudioFocusHelper(getApplicationContext(), this);
    } else {
        mAudioFocusHelper = null;
    }

    クリーンアップ
    前述したように、MediaPlayerオブジェクトは大量のシステムリソースを消費することができるので、必要に応じて保持し、使い終わったときにすぐに解放する必要があります.システムのゴミ収集メカニズムに頼るのではなく、クリーンアップ方法を明確に呼び出すことが重要です.なぜなら、収集される前にMediaPlayerが長い間存在する可能性があるためです.この場合、他のメディア関連のリソースに影響を与えることなくメモリを消費するだけです.そのため、サービスを使用する場合は、MediaPlayerの解放を保証するためにonDestroy()メソッドを4回書き換える必要があります.
    public class MyService extends Service {
       MediaPlayer mMediaPlayer;
       // ...
    
       @Override
       public void onDestroy() {
           if (mMediaPlayer != null) mMediaPlayer.release();
       }
    }

    他にもMediaPlayerを解放するタイミングを探さなければなりません.例えば、長い間メディアを再生できないと予想した場合(例えばオーディオフォーカスを失った後)、MediaPlayerを明確に解放し、後で再作成する必要があります.逆に、短時間で再生を停止すると予想した場合は、MediaPlayerを維持して過剰な作成を避ける必要があります.再準備ではなく