在清单中针对API级别18或更高级别调用AudioManager.startBluetoothSCO()时,文档指出已建立原始音频连接,并且如果使用针对API 17或更低版本的虚拟语音呼叫。
直到API级别20(Android L预览版),此功能正常,针对任何API。但是,当使用最新的Android Lollipop构建LPX13D并且目标API级别为18或更高时,我会遇到以下堆栈跟踪崩溃:
E / AndroidRuntime(31705):引起:java.lang.NullPointerException:尝试在空对象引用上调用虚方法'java.lang.String android.bluetooth.BluetoothDevice.getAddress()' E / AndroidRuntime(31705):在android.os.Parcel.readException(Parcel.java:1546) E / AndroidRuntime(31705):在android.os.Parcel.readException(Parcel.java:1493) E / AndroidRuntime(31705):在android.media.IAudioService $ Stub $ Proxy.startBluetoothSco(IAudioService.java:1587) E / AndroidRuntime(31705):在android.media.AudioManager.startBluetoothSco(AudioManager.java:1468)
如果我在Android Lollipop上定位API级别17或更低级别,一切都按预期工作。
我认为问题的根源在于改变Android的音频代码,该代码发生在文件AudioService.java第2392行的API级别21中:
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 :(得分:4)
正如@xsveda所写,如果没有连接耳机,你将在Lollipop上收到NPE。
您可以先尝试检查蓝牙耳机连接:
mAudioManager.isWiredHeadsetOn()
正如所描述的文档isWiredHeadsetOn()
(doc link)已被删除,仅用于检查耳机是否已连接。
在此之后,您可以使用startBluetoothSco()
连接。至于我,我使用了这段代码:
这一个开始:
if(mAudioManager.isWiredHeadsetOn())
mAudioManager.startBluetoothSco();
这个停止:
if(mAudioManager.isBluetoothScoOn())
mAudioManager.stopBluetoothSco();
希望它有所帮助。
答案 1 :(得分:0)
经过几天的绝望之后,我找到了一个简单的解决方法:
只有在没有连接蓝牙设备的情况下, startBluetoothSco()
才会抛出NPE,因此可以捕获并忽略它,因为没有人可以与#34;交谈。如果连接了BT耳机,则SCO成功启动并且播放正在运行!
答案 2 :(得分: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));
}
希望这有助于某人!