2014-10-29 18 views
11

Quando si effettua una chiamata a AudioManager.startBluetoothSCO() mentre si seleziona il livello API 18 o successivo nel manifesto, la documentazione indica che viene stabilita una connessione audio non elaborata e se l'API di destinazione 17 o inferiore è una voce virtuale la chiamata è usataAudioManager.startBluetoothSco() si arresta su Android Lollipop

Fino al livello API 20 (Android L Preview), questo ha funzionato correttamente, indirizzando qualsiasi API. Tuttavia, quando si utilizza l'ultima versione di Android Lollipop LPX13D e il livello di API 18 o successivo, si verifica un arresto anomalo con il seguente stack:

E/AndroidRuntime (31705): Causato da: java.lang.NullPointerException: tentativo di richiamare metodo virtuale 'java.lang.String android.bluetooth.BluetoothDevice.getAddress()' su un oggetto nullo di riferimento E/AndroidRuntime (31705): su android.os.Parcel.readException (Parcel.java:1546) E/AndroidRuntime (31705): su android.os.Parcel.readException (Parcel.java:1493) E/AndroidRuntime (31705): su android.media.IAudioService $ Stub $ Proxy.startBluetoothSco (IAudioService.java:1587) E/AndroidRuntime (31705): su android.media.AudioManager.startBluetoothSco (AudioManager.java:1468)

Se utilizzo il livello API 17 o inferiore su Android Lollipop, tutto funziona come previsto.

credo che l'origine del problema risiede in una modifica al codice di audio di Android che è accaduto nel livello di API 21 nel file AudioService.java linea 2392:

public void startBluetoothSco(IBinder cb, int targetSdkVersion) { 
    int scoAudioMode = 
      (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ? 
        SCO_MODE_VIRTUAL_CALL : SCO_MODE_UNDEFINED; 
    startBluetoothScoInt(cb, scoAudioMode); 
} 

Sembra SCO_MODE_UNDEFINED dovrebbero invece essere SCO_MODE_RAW. Se si guarda attraverso il file, è possibile vedere che SCO_MODE_RAW viene controllato in alcuni punti, ma non viene mai effettivamente trasferito da nessuna parte.

Qualcun altro sta vivendo questo incidente? Qualcuno sa di una soluzione migliore rispetto al downgrade dell'SDK di destinazione a 17? In caso contrario, potrebbe per favore protagonista il bug report ho presentato con Google per aumentare la probabilità che sarà esaminato :-)

+0

Anche se non si verifica l'arresto anomalo, il dispositivo non sembra instradare l'audio dal microfono Bluetooth. –

+0

ho lo stesso problema, il microfono non è routing, nessuna soluzione per questo? –

risposta

0

Dopo alcuni giorni di disperazione, ho trovato una semplice soluzione:

startBluetoothSco() tiri NPE solo se non è collegato alcun dispositivo Bluetooth in modo che possa essere catturato e ignorato poiché non c'è "nessuno con cui parlare". Se ad esempio è collegato un auricolare BT, SCO viene avviato correttamente e la riproduzione funziona!

+0

Sembra una soluzione migliore rispetto all'impostazione dell'SDK di destinazione su 17, tuttavia dopo ulteriori indagini ho notato che con entrambi i workaround l'audio non viene instradato attraverso il microfono Bluetooth ma invece esce attraverso il microfono del telefono. È facile perdere questo se hai il telefono e il dispositivo bluetooth vicini l'uno all'altro. –

0

Per ora quello che sembra funzionare per me è stato ignorando la NullPointerException:

private void tryConnectAudio() { 
    verifyBluetoothSupport(); 
    try { 
     mAudioManager.startBluetoothSco(); 
    } catch (NullPointerException e) { 
     // TODO This is a temp workaround for Lollipop 
     Log.d(TAG, "startBluetoothSco() failed. no bluetooth device connected."); 
    } 
} 

@Julian Claudino, Questo funziona per me e il routing attraverso il microfono Bluetooth, assicurarsi che il dispositivo Bluetooth viene riconosciuto e collegato:

private void verifyBluetoothSupport() { 
    getActivity().registerReceiver(new BroadcastReceiver() { 
     @Override 
     public void onReceive(Context context, Intent intent) { 
      int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1); 
      Log.d(TAG, "Audio SCO state: " + state); 
      if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) { 
       Toast.makeText(getActivity(), "Bluetooth Connected", Toast.LENGTH_SHORT).show(); 
       getActivity().unregisterReceiver(this); 
      } 
     } 
    }, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)); 
} 

Spero che questo aiuti qualcuno!

4

Come @xsveda ha scritto se non ci sono cuffie collegate, si riceverà NPE su Lollipop.

Si può cercare di controllare il collegamento auricolare Bluetooth prima:

mAudioManager.isWiredHeadsetOn() 

DOC descritto isWiredHeadsetOn() (doc link) è depricated e utilizza solo per controllare è un auricolare è collegato o meno.

E dopo questo è possibile utilizzare la connessione startBluetoothSco(). Per quanto mi riguarda ho usato questo codice:

Questo per l'avvio:

if(mAudioManager.isWiredHeadsetOn()) 
    mAudioManager.startBluetoothSco(); 

Questo per l'arresto:

if(mAudioManager.isBluetoothScoOn()) 
      mAudioManager.stopBluetoothSco(); 

Speranza che aiuta.

Problemi correlati