2014-10-29 99 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(); 

希望它能帮助。

相关问题