2014-10-29 126 views
11

在清單中針對API級別18或更高級別調用AudioManager.startBluetoothSCO()時,文檔指出建立了原始音頻連接,並且如果針對API 17或更低級別的虛擬語音呼叫被使用。AudioManager.startBluetoothSco()在Android Lollipop上崩潰

直到API級別20(Android L預覽版)爲止,這個工作正常,目標是任何API。但是,如果使用最新的Android Lollipop版本LPX13D並且API等級爲18或更高,我會遇到以下堆棧跟蹤崩潰:

E/AndroidRuntime(31705):引起:java.lang.NullPointerException:嘗試調用虛擬方法java.lang.String android.bluetooth.BluetoothDevice.getAddress()'null對象引用 E/AndroidRuntime(31705):at android.os.Parcel.readException(Parcel.java:1546) E/AndroidRuntime (31705):at android.os.Parcel.readException(Parcel.java:1493) E/AndroidRuntime(31705):at android.media.IAudioService $存根$ Proxy.startBluetoothSco(IAudioService.java:1587) E/AndroidRuntime (31705):at android.media.AudioManager.startBluetoothSco(AudioManager.java:1468)

如果我在Android Lollipop上定位API級別17或更低版​​本,則按預期工作。

我認爲,問題的根源在於,改變Android的音頻代碼,API等級21發生在文件AudioService.java行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); 
} 

看起來SCO_MODE_UNDEFINED應改爲SCO_MODE_RAW。如果你仔細查看文件,你會發現SCO_MODE_RAW在幾個地方被檢查過,但實際上從來沒有在任何地方傳過。

是否有其他人遇到這種崩潰?有誰知道比將目標SDK降級到17更好的解決方案嗎?如果沒有,你能不能請明星bug report我與谷歌申請增加的機會,這將在:-)

+0

即使我沒有得到崩潰,設備似乎也沒有從藍牙麥克風路由音頻。 – 2015-02-25 23:39:16

+0

我有同樣的問題,麥克風不是路由,任何解決方案? – 2015-04-18 06:40:25

回答

0

被看作絕望後的幾天,我發現一個簡單的解決方法:

startBluetoothSco()拋出NPE只有在沒有連接藍牙設備的情況下,才能被捕捉並忽略,因爲「沒有人可以交談」。如果連接了BT頭戴式耳機,則SCO成功啓動並且播放正在進行!

+0

這看起來好像比將目標SDK設置爲17更好的解決方法,但經過進一步調查後,我注意到,在兩種解決方法中,音頻不是通過藍牙麥克風路由,而是通過手機的麥克風發出。如果您的手機和藍牙設備彼此靠近,很容易錯過。 – 2014-11-13 18:26:54

0

現在似乎什麼對我來說是無視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,這對我的作品,並通過藍牙麥克風路由,確保藍牙設備被識別並連接:

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)); 
} 

希望這可以幫助別人!

4

如@xsveda寫道,如果沒有連接耳機,您將收到棒棒糖上的NPE。

你可以嘗試先檢查藍牙耳機的連接:

mAudioManager.isWiredHeadsetOn() 

由於文檔描述isWiredHeadsetOn()doc link)被depricated,只用來檢查被連接耳機或沒有。

此後,您可以使用startBluetoothSco()連接。至於我,我用這個代碼:

這一個開始:

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

這一個站:

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

希望它能幫助。