Android Audio Play Out Channel

1: 7嘴8舌

 

揚聲器, 耳機, 和聽筒html

就是經過: audiomanager.setmode(AudioManager.MODE_IN_COMMUNICATION)
audiomanager.setSpeakerhponeOn(boolean value).這兩個來設置.不過有的好像不支持的.java

米手機上切換 揚聲器和聽筒不能切換android

 

Android AudioTrack音頻播放分析  
音頻資源在播放時,會常常出現衝突的狀況,如在進行音樂播放時有電話呼入、
有新消息的提示音須要播放等,此類的併發處理就須要有一個統一的處理策略。在 Android系統開發中,經過爲不一樣的場景配置不一樣的播放接口,在底層執行統一的併發策略,使得開發者能夠將精力更集中在應用自己。
A udioTrack、MediaPlayer、SoundPool、Ringtone、JetPlayer等都是Android音頻處理中經常使用接口,本文將針對AudioTrack接口進行詳細說明。
AudioTrack AudioTrack用於管理單個的音頻資源。 在構造AudioTrack實例時,會涉及到流類型、採樣率、通道配置、音頻格式、緩衝大小、播放模式等因素。
AudioTrack支持STREAM_VOICE_CALL、STREAM_SYSTEM、STREAM_RING、STREAM_MUSIC和STREAM_ALARM等流類型。
AudioTrack支持44100Hz、22050Hz、11025Hz等採樣率。 AudioTrack支持單聲道(CHANNEL_OUT_MONO)、立體聲(CHANNEL_OUT_STEREO)等兩種通道。
AudioTrack支持ENCODING_PCM_16BIT、ENCODING_PCM_8BIT等兩種編碼格式。
AudioTrack支持兩種播放模式:靜態模式(
static mode)和流模式(Streaming mode)。
其中靜態模式因爲沒有從Java層向原生層傳遞數據形成的延遲,時延很小,固然受限於音頻緩衝的大小,一般在遊戲場景中用於播放時長很短的音頻資源。
當音頻流較大不足以在音頻緩衝中一次寫入時,可採用流模式。
AudioTrack的播放狀態包括PLAYSTATE_STOPPED、PLAYSTATE_PAUSED、PLAYSTATE_PLAYING等。
AudioTrack實例的狀態包括STATE_INITIALIZED、STATE_NO_STATIC_DATA、STATE_UNINITIALIZED等。
向音頻緩衝中添加數據的方法爲write()。
在設置音頻緩衝時,其大小與採樣率、通道和音頻格式有關。
其計算公式爲: 緩衝大小=最小幀數×(通道==CHANNEL_OUT_STEREO?2:1)×(音頻格式== PCM16?2:1) 而最小幀數則受制於採樣率和音頻設備的延遲等因素。
另外,在Android 2.3中,還引入了會話的概念,便於對單曲的音效進行處理。相應的方法包括:attachAuxEffect()、getAudioSessionId()、setAuxEffectSendLevel()等。
經過AudioTrack.OnPlaybackPositionUpdateListener監聽器能夠監聽播放進度。
下面是一個背景音頻的播放過程:
代碼10-3 AudioTrack播放音頻文件


public class BackgroundAudio extends Thread { public static final int SAMPLE_RATE = 16000public static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT; public static final int BYTES_PER_SAMPLE = 2public static final int PLAYBACK_STREAM = AudioManager.STREAM_MUSIC; …… 
public BackgroundAudio(byte[] data) { 
 //計算緩衝大小  final int minBufferSize = (BUFFER_TIME *SAMPLE_RATE*BYTES_PER_SAMPLE) / 1000; 
  //計算硬件的最小緩衝 
      final int minHardwareBufferSize = AudioTrack.getMinBufferSize(SAMPLE_RATE,AudioFormat.CHANNEL_OUT_MONO,AUDIO_FORMAT); 
        mBufferSize = Math.max(minHardwareBufferSize, minBufferSize);        
     mAudioTrack = new AudioTrack(PLAYBACK_STREAM, SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO,  AUDIO_FORMAT, mBufferSize, AudioTrack.MODE_STREAM);         

     if (mAudioTrack.getState() == AudioTrack.STATE_INITIALIZED) {             
     writeAudio();          start(); 
// 啓動背景線程去推送音頻數據             mAudioTrack.play();         } else {          Log.e(TAG, "Error initializing audio track.");         
  } } …… 
private void writeAudio() {    
  int len = mData.length;    
  int count;    int maxBytes = Math.min(mBufferSize, len - mPos);     count = mAudioTrack.write(mData, mPos, maxBytes);    
  if (count < 0) {         Log.e(TAG, "Error writing looped audio data");        
  halt();        

  return;     
  }     mPos 
+= count;    

if (mPos == len) {         mPos = 0; // Wraparound    
 }  } }

Media playback  
Supported Media Formats  
Audio Capture  
JetPlayer  
Camera  

        此次我先分享下Media Playback的中一些內容以及我學習中的感悟。  




        首先須要咱們接觸到的最主要的兩個類分別是MediaPlayer、MediaManager。MediaPlayer是用來控制音頻/視頻流或者文件的播放的,須要咱們注意的是MediaPlayer對象加上其支持的一些播放操做會造成一個狀態機,在不合適的狀態執行不合適的操做就會拋出異常,若是開發者不清楚本身建立的MediaPlayer對象當前處於哪一個狀態,就頗有可能調用錯誤的方法形成程序的異常,並且這些錯誤很難被察覺,因此錯誤處理在這個部分就顯得尤其重要。  




        下面要說的就是Audio Focus,舉個例子,當你在聽歌的時候,忽然來了一條短信,若是不加處理,短信的聲音極可能被音樂的聲音湮沒,你就會察覺不到。咱們但願發生什麼事情呢?咱們但願這個時候音樂的聲音較以前稍微下降些使得咱們可以聽到短信提示音,在短信提示音結束後音樂的聲音再次回到正常。這個過程就是獲取和釋放audio focus的過程。  

        在寫代碼的時候,我忽略了一點:Audio Focus is cooperative in nature.  

申請audio focus  


[java] view plaincopyprint?AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);   
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,    
    AudioManager.AUDIOFOCUS_GAIN);    

AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);  
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,  
    AudioManager.AUDIOFOCUS_GAIN);  
處理focus change事件  


[java] view plaincopyprint?class MyService extends Service    
                implements AudioManager.OnAudioFocusChangeListener {    
    // ....     
    public void onAudioFocusChange(int focusChange) {    
        // Do something based on focus change...     
    }    
}    

class MyService extends Service  
                implements AudioManager.OnAudioFocusChangeListener {  
    // ....  
    public void onAudioFocusChange(int focusChange) {  
        // Do something based on focus change...  
    }  
}  

        申請audio focus和處理focus change必定是互相配合實現的,我一開始寫了個service用來播放音樂,在start函數調用前並無申請audio focus,可是我實現了onAudioFocusChange函數。我期待這個service在focus change時中止播放,可是我發現,當另一個service申請到audio focus時,以前的service不會出現音樂中止播放的狀況。 
android培訓,就選成都達內,最好的成都軟件培訓機構,若是你有「達內培訓須要多少錢」、「達內培訓怎麼樣」等問題,詳情請諮詢達內客服(http://www.sctarena.com),咱們會給你詳細的講解。

 

 

android 聽筒播放音樂


AudioManager.setMode(AudioManager.MODE_IN_CALL) //設定爲通話中便可 仍是這一句代碼的事,不過記得要加上權限 android.permission.MODIFY_AUDIO_SETTINGS 還有一點須要注意的事,在播放完畢後須要 AudioManager.setMode(AudioManager.MODE_NORMAL); 否則其餘軟件播放都聽筒發聲了

實際操做中,僅僅上述代碼並不能是實現需求:

榮耀:4..2.2併發

內核3.4.5app


audiomanager.setMode(AudioManager.MODE_IN_CALL);less

Nexus 5   5.0.1ide

內核2.4.0函數

audiomanager.setMode(AudioManager.MODE_IN_CALL);不能生效,即使添加該行仍然從揚聲器播出oop

 

 

   
   
   
 
設備 audio path media paly new  
       
       
       
       

 

Actually you don't need audioManager.setSpeakerphoneOn(false); . And also, you need to create MediaPlayer not with static method MediaPlayer.create(), but you need to create it with new MediaPlayer()... –  Andranik Jun 12 '14 at 18:40 



up vote
16
down vote
accepted
Audio handling on Android is going to be pretty horrible for a while. The APIs are pretty weird, poorly documented, and keep changing/deprecating/breaking between versions. Even the AudioManager code has FIXMEs in it.

Anyway, there are several stream types in Android (music, notifications, phone calls, etc.) and applications are meant to choose the appropriate one for playback. I imagine the majority of Android apps should use the music/media type (STREAM_TYPE_MUSIC). You set this on your MediaPlayer using the setAudioStreamType method.

The SDK does allow you to set a single stream type as solo — causing all other streams to be muted — but I don't believe you can identify the audio being played back by particular applications and somehow pause/unpause it. Music applications in general will use the PhoneStateListener to pause themselves when a call comes in.

So in your case, you could "borrow" the phone call stream for your MediaPlayer and use the method call AudioManager.setStreamSolo(AudioManager.STREAM_VOICE_CALL, true) when playback begins, then un-solo the stream with false when playback or your Activity is done.

I can tell you that this works, but I can't remember offhand whether you need to also set the audio mode to MODE_IN_CALL when using the voice call stream (like this: AudioManager.setMode(AudioManager.MODE_IN_CALL)). If you find that is required, then you need to make sure you return the mode to MODE_NORMAL once playback completes, otherwise whenever you press the volume hard keys, it'll say "In-call volume"! However, if and when you do want to change back to MODE_NORMAL, you must check that a genuine phone call isn't happening at that time...

Maybe you could use another stream type rather than the voice call one, but I'm just speaking from experience working on an app that could use either the speakerphone or the earpiece for audio playback, which requires the use of the voice call stream.

Like I said, audio handling isn't particularly fun... ;)

 

2:應用場景

 

Audio 輸出通道有不少,Speaker、headset、bluetooth A2DP等。學習

通話或播放音樂等使用Audio輸出過程當中,可能發生Audio輸出通道的切換。好比,插入有線耳機播放音樂時,聲音是從耳機發出的;而此時拔出耳機,Audio輸出通道會發生切換。若是音樂播放器不作處理,Audio輸出是被切換到揚聲器的,聲音直接從Speaker發出。

Android中能夠經過android.media.AudioManager查詢當前Audio輸出的狀況,而且在Audio輸出發生變化時,捕獲並處理這種變化。

AudioNoisy AudioManager

1、Audio輸出狀態查詢與控制

android.media.AudioManager提供的下列方法能夠用來查詢當前Audio輸出的狀態:

 

  •  isBluetoothA2dpOn():檢查A2DPAudio是否經過藍牙耳機;
  •  isSpeakerphoneOn():檢查揚聲器是否打開;
  •  isWiredHeadsetOn():檢查線控耳機是否連着;注意這個方法只是用來判斷耳機是不是插入狀態,並不能用它的結果來斷定當前的Audio是經過耳機輸出的,這還依賴於其餘條件。

 

另外還有一些設置這些Audio輸出的setXYZ()方法,這些方法在通常使用Audio輸出的應用程序不要直接調用,他們由系統來管理,實現Audio輸出通道的自動切換。除非,界面提供給用戶切換的菜單或按鈕,而用戶選擇了卻換,好比要直接選擇揚聲器發聲,可直接調用setSpeakerphoneOn()。

 

2、Audio輸出通道切換的事件的捕獲與處理

由於耳機插拔、藍牙耳機的斷開,Audio輸出通路會自動切換。此時正在播放Audio的程序要得到通知,知道這一事件的發生。Android中是經過廣播ACTION_AUDIO_BECOMING_NOISY這個Intent通知的。

處理廣播的較好的方式,是動態註冊/註銷本身所關心的廣播。下面代碼演示了,開始播放時註冊廣播的Receiver;中止播放時註銷廣播的Receiver。對Audio輸出通道切換的處理是暫停當前的播放,不直接重新的通道里發出聲來。

private class NoisyAudioStreamReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
            // Pause the playback
        }
    }
}

private IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);

private void startPlayback() {
    registerReceiver(myNoisyAudioStreamReceiver(), intentFilter);
}

private void stopPlayback() {
    unregisterReceiver(myNoisyAudioStreamReceiver);
}

3、Audio輸出通道切換的典型場景—— 用耳機聽音樂時,拔出耳機

聽耳機聽音樂時,耳機別拔出的時序圖以下:

AudioNoisy_Sequence.jpg

圖中:

 

  •  AudioNoisy Client註冊了偵聽廣播AudioManager.ACTION_AUDIO_BECOMING_NOISY[Step#1 ~ #2];
  •  用耳機一直在聽音樂;
  •  HeadsetObserver一直在監視耳機狀態的變化。檢測到耳機被拔出以後,發出廣播AudioManager.ACTION_AUDIO_BECOMING_NOISY[Step#3~4];
  •  AudioNoisy Client收到了廣播,發送暫停命令給MediaPaybackService去暫停當前的播放 [Step#5~6]。

 

 3:Android 文檔

Building Apps with Multimedia

These classes teach you how to create rich multimedia apps that behave the way users expect.

  1. Managing Audio Playback

    If your app plays audio, it’s important that your users can control the audio in a predictable manner. To ensure a great user experience, it’s also important that your app manages the audio focus to ensure multiple apps aren’t playing audio at the same time.
    
    After this class, you will be able to build apps that respond to hardware audio key presses, which request audio focus when playing audio, and which respond appropriately to changes in audio focus caused by the system or other applications.
    爲用戶提供便捷的音頻狀態控制對良好的用戶體驗是很是重要的。
    
    你能夠構建響應物理音頻按鍵,獲取音頻播放焦點,以及適時的響應因爲系統or其餘應用引發的音頻焦點變化。

     

  2.  


    How to respond to hardware audio key presses, request audio focus when playing audio, and respond appropriately to changes in audio focus.

    1. Controlling Your App's Volume and Playback
    2. Managing Audio Focus
    3. Dealing with Audio Output Hardware

 

引用:

http://blog.csdn.net/thl789/article/details/7423523

相關文章
相關標籤/搜索