2010-01-22 3 views
32

Attualmente ho un codice che legge una registrazione dal microfono del dispositivo utilizzando la classe AudioRecord e quindi riproducilo utilizzando la classe AudioTrack.Android - Riprodurre l'audio tramite l'auricolare

Il mio problema è che quando lo suono viene riprodotto tramite il vivavoce.

Voglio che venga riprodotto tramite l'auricolare sul dispositivo.

Ecco il mio codice:

public class LoopProg extends Activity { 

boolean isRecording; //currently not used 
AudioManager am; 
int count = 0; 

/** Called when the activity is first created. */ 
@Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 
     am.setMicrophoneMute(true); 
     while(count <= 1000000){ 
     Record record = new Record(); 
     record.run(); 
     count ++; 
     Log.d("COUNT", "Count is : " + count); 
     } 
    } 

    public class Record extends Thread{ 
     static final int bufferSize = 200000; 
     final short[] buffer = new short[bufferSize]; 
     short[] readBuffer = new short[bufferSize]; 

     public void run() { 
     isRecording = true; 
     android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); 

     int buffersize = AudioRecord.getMinBufferSize(11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT); 
     AudioRecord arec = new AudioRecord(MediaRecorder.AudioSource.MIC, 11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, buffersize); 
     AudioTrack atrack = new AudioTrack(AudioManager.STREAM_MUSIC, 11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, buffersize, AudioTrack.MODE_STREAM); 
     am.setRouting(AudioManager.MODE_NORMAL,1, AudioManager.STREAM_MUSIC); 
     int ok = am.getRouting(AudioManager.ROUTE_EARPIECE); 
     Log.d("ROUTING", "getRouting = " + ok); 
     setVolumeControlStream(AudioManager.STREAM_VOICE_CALL); 
     //am.setSpeakerphoneOn(true); 
     Log.d("SPEAKERPHONE", "Is speakerphone on? : " + am.isSpeakerphoneOn()); 
     am.setSpeakerphoneOn(false); 
     Log.d("SPEAKERPHONE", "Is speakerphone on? : " + am.isSpeakerphoneOn()); 
     atrack.setPlaybackRate(11025); 

     byte[] buffer = new byte[buffersize]; 
     arec.startRecording(); 
     atrack.play(); 

     while(isRecording) { 
         arec.read(buffer, 0, buffersize); 
         atrack.write(buffer, 0, buffer.length); 
         } 
     arec.stop(); 
     atrack.stop(); 
     isRecording = false; 
     } 
    } 
} 

Come si può vedere se il codice che ho provato ad utilizzare la classe AudioManager ei suoi metodi tra cui il metodo setRouting deprecato e non funziona nulla, il metodo setSpeakerphoneOn sembra avere alcun effetto del tutto, nemmeno il metodo di routing.

Qualcuno ha qualche idea su come farlo funzionare tramite l'auricolare invece del telefono Spaker?

risposta

27

1,6 Ho appena finito per funzionare su 2.2. Avevo ancora bisogno del setup di In_Call che non mi piace, ma per ora mi occuperò di questo. Sono stato in grado di abbandonare il routing delle chiamate che ora è deprecato. Ho trovato che hai sicuramente bisogno dell'autorizzazione Modify_Audio_Settings, nessun errore senza di esso ma il metodo setSpeakerPhone non fa nulla. Ecco il mock up del codice che ho usato.

private AudioManager m_amAudioManager; 
m_amAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); 
m_amAudioManager.setMode(AudioManager.MODE_IN_CALL); 
m_amAudioManager.setSpeakerphoneOn(false); 
+0

Hai bisogno di riportare l'audio allo stato originale prima di impostarlo su IN_CALL? qualcosa del genere: int currAudioMode = audioManager.getMode(); \t \t \t \t \t \t audioManager.setMode (AudioManager.MODE_IN_CALL); \t \t \t audioManager.setSpeakerphoneOn (actionData.speakerOn); \t \t \t \t \t \t audioManager.setMode (currAudioMode); – Muzikant

+0

L'ho impostato su MODE_NORMAL per riaccendere il vivavoce. Pertanto, il codice sopra riportato spegne l'altoparlante e si dirige verso l'auricolare, e il percorso del codice sottostante torna al valore predefinito dell'altoparlante. 'm_amAudioManager.setMode (AudioManager.MODE_NORMAL);' – Piwaf

+0

disturba le impostazioni globali del telefono ?? –

3

Si è discusso correlate in questo recente domanda:
Android - can I mute currently playing audio applications?

Basato sul codice sorgente AudioManager, sembra che si deve essere in "modalità chiamata" prima che il metodo setSpeakerphoneOn ha alcun effetto.

Tuttavia, di recente ho visto un'applicazione che poteva passare senza interruzioni tra l'altoparlante e il vivavoce mentre mostrava lo stream corrente come flusso "multimediale", quindi sarei interessato a qualsiasi altra risposta.

+1

Ahh, quindi penso che il dispositivo Ho visto questo lavoro è stato in esecuzione 1.5. Sfortunatamente le API AudioManager sembrano cambiare spesso tra le versioni. Il routing e la roba del vivavoce era decisamente un'area cambiata tra 1.5 e 1.6. Che fa schifo :( –

+0

Ciao Christopher, attualmente uso questo codice per farlo e funziona in 1.5 audio_service.setSpeakerphoneOn (false); audio_service.setMode (AudioManager.MODE_IN_CALL); audio_service.setRouting (AudioManager.MODE_NORMAL, AudioManager.ROUTE_EARPIECE, AudioManager.ROUTE_ALL Tuttavia è rotto da 1.6 in poi e non riesco a trovare la nuova soluzione.Ho provato a impostare il metodo SpeakerPhoneOn su falso ma si mette ancora fuori l'altoparlante, ho provato a cambiare tutti i flussi in giro e ancora senza fortuna –

+0

Sì, sembra essere abbastanza rotto da 1.6 su cui è abbastanza fastidioso al minuto, la maggior parte dei nuovi dispositivi utilizza una versione superiore a 1.5! –

0

Se l'auricolare è collegato al telefono con Bluetooth (che presumo sia), hai provato a chiamare AudioManager.setBluetoothScoOn(true)?

Ho avuto il riferimento Android e questa è l'unica cosa che ho potuto trovare che non hai menzionato provare.

+1

Non sembra che stia usando un auricolare Bluetooth. avere un orecchio contro durante le telefonate –

+0

Sì come dice christopher Sto cercando di fare rotta l'audio attraverso l'auricolare che si trova sul dispositivo stesso, dove le persone ascoltano per le normali telefonate. Posso usare il metodo setRouting e funziona in 1.5, tuttavia non riesco a trovare una soluzione per instradare l'audio all'orecchio da 1,6 su –

1

Mi sembra che abbia funzionato su 1.6.

Quindi ho detto che avrei postato qui come l'ho fatto.

per farlo funzionare in 1.6 I:

Usato classe AudioManager per impostare setSpeakerphoneOn(false), ho poi usato il Voice_Call_Stream e aggiungere il controllo del volume al Voice_Call_Stream.

Il metodo setSpeakerphoneOn(false) viene utilizzato in onCreate() dell'attività e questo sembra rotta verso l 'auricolare, Ho quindi utilizzato un pulsante e utilizzare il metodo setSpeakerphoneOn(true) e l'audio viene instradato verso l'altoparlante.

Il metodo sembra funzionare solo quando viene utilizzato in onCreate() per me e non hanno testato ampiamente ma per il momento mi permette di commutare tra cuffia e altoparlante su un dispositivo

+0

puoi fornire del codice? – pengwang

1
public MediaPlayer m_mpSpeakerPlayer; 

private AudioManager m_amAudioManager; 

m_amAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); 

// 從Receiver Earpiece發音 

m_amAudioManager.setSpeakerphoneOn(false); 

m_amAudioManager.setRouting(AudioManager.MODE_NORMAL, AudioManager.ROUTE_EARPIECE, AudioManager.ROUTE_ALL); 

Log.i(TAG, String.valueOf(m_amAudioManager.getRouting(AudioManager.ROUTE_EARPIECE))); 

setVolumeControlStream(AudioManager.STREAM_VOICE_CALL); 

// 把聲音設定成從Earpiece出來 
// 重點在這行,要把它設定為正在通話中 
m_amAudioManager.setMode(AudioManager.MODE_IN_CALL); 

// 開始放音樂 
m_mpSpeakerPlayer.reset(); 

m_mpSpeakerPlayer.setDataSource("sdcard/receiver.mp3"); 

m_mpSpeakerPlayer.prepare(); 

m_mpSpeakerPlayer.start(); 

//最後再把它設定從Speaker放音,達成! 

m_amAudioManager.setMode(AudioManager.MODE_NORMAL); 
+0

Il codice dato da Achigo ha funzionato perfettamente. Il tuo codice deve avere l'autorizzazione ** android.permission.MODIFY_AUDIO_SETTINGS ** impostata nel file manifest perché * setSpeakerPhoneOn() * richiede tale autorizzazione. – MegaMind

+0

@MegaMind Cosa fornisce esattamente questa autorizzazione? Ho notato che la modifica del volume è ok e non necessita di autorizzazione. È vero? –

3

Ingannato da alcune risposte qui per un bel po 'di tempo. Sto usando Android 2.2. "AudioManager.setSpeakerphoneOn (false);" sta lavorando.

audioManager.setSpeakerphoneOn(false); 
... 
mediaPlayer.setDataSource(..); 
mediaPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL); 
mediaPlayer.prepare(); 
+0

Non si utilizza MediaPlayer –

+1

In realtà non è necessario 'audioManager.setSpeakerphoneOn (false);'. Inoltre, è necessario creare MediaPlayer non con il metodo statico 'MediaPlayer.create()', ma è necessario crearlo con 'new MediaPlayer() ...' – Andranik

3

Si prega di utilizzare questo codice, funziona bene:

//PLAY ON EARPIECE 
    mPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL); 
    audioManager.setMode(AudioManager.MODE_IN_CALL); 
    audioManager.setSpeakerphoneOn(false); 

    //PLAY ON SPEAKER 
    mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 
    audioManager.setMode(AudioManager.MODE_IN_CALL); 
    audioManager.setSpeakerphoneOn(true);