2014-10-29 21 views
11

Khi thực hiện cuộc gọi đến AudioManager.startBluetoothSCO() trong khi nhắm mục tiêu API cấp 18 trở lên trong Tệp kê khai, tài liệu cho biết rằng kết nối âm thanh thô được thiết lập và nếu nhắm mục tiêu API 17 trở xuống bằng giọng nói ảo cuộc gọi được sử dụng.AudioManager.startBluetoothSco() treo trên Android Lollipop

Cho đến cấp API 20 (Xem trước Android L) điều này hoạt động tốt, nhắm mục tiêu bất kỳ API nào. Tuy nhiên, khi sử dụng LPX13D mới nhất của Android Lollipop và nhắm mục tiêu API cấp 18 trở lên, tôi gặp sự cố với dấu vết ngăn xếp sau:

E/AndroidRuntime (31705): Nguyên nhân: java.lang.NullPointerException: Cố gắng gọi phương thức ảo 'java.lang.String android.bluetooth.BluetoothDevice.getAddress()' trên tham chiếu đối tượng null E/AndroidRuntime (31705): tại android.os.Parcel.readException (Parcel.java:1546) E/AndroidRuntime (31705): tại android.os.Parcel.readException (Parcel.java:1493) E/AndroidRuntime (31705): tại android.media.IAudioService $ Stub $ Proxy.startBluetoothSco (IAudioService.java:1587) E/AndroidRuntime (31705): tại android.media.AudioManager.startBluetoothSco (AudioManager.java:1468)

Nếu tôi nhắm mục tiêu cấp API 17 trở xuống trên Android, mọi thứ hoạt động như mong đợi.

tôi tin rằng nguồn gốc của vấn đề nằm ở sự thay đổi mã âm thanh của Android đã xảy ra ở cấp độ API 21 trong file dòng 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); 
} 

Dường như SCO_MODE_UNDEFINED thay vì nên SCO_MODE_RAW. Nếu bạn xem qua tệp, bạn có thể thấy rằng SCO_MODE_RAW được chọn ở một vài nơi, nhưng không bao giờ thực sự được chuyển vào bất kỳ đâu.

Có ai khác đang gặp sự cố này không? Có ai biết sửa chữa tốt hơn là hạ cấp SDK mục tiêu xuống 17 không? Nếu không, bạn có thể vui lòng sao các bug report Tôi nộp với Google để nâng cao khả năng nó sẽ được xem xét :-)

+0

Ngay cả khi tôi không gặp sự cố, thiết bị dường như không định tuyến âm thanh từ micrô Bluetooth. –

+0

tôi có cùng một vấn đề, mic không định tuyến, bất kỳ giải pháp cho điều đó? –

Trả lời

0

Sau vài ngày tuyệt vọng tôi đã tìm thấy một workaround đơn giản:

startBluetoothSco() ném NPE chỉ khi không có thiết bị Bluetooth nào được kết nối để nó có thể bị phát hiện và bỏ qua vì có "không ai nói chuyện". Nếu tai nghe BT được kết nối, SCO được khởi động thành công và phát lại đang hoạt động!

+0

Điều đó có vẻ như giải pháp tốt hơn là đặt SDK mục tiêu thành 17, tuy nhiên khi điều tra thêm, tôi nhận thấy rằng với cả âm thanh cách giải quyết đều không được định tuyến qua micrô bluetooth mà thay vào đó là micrô của điện thoại. Thật dễ dàng để bỏ lỡ điều này nếu bạn có điện thoại và thiết bị bluetooth gần nhau. –

0

Đối với bây giờ những gì dường như làm việc đối với tôi là bỏ qua 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, này làm việc cho tôi và định tuyến thông qua mic Bluetooth, hãy chắc chắn rằng thiết bị Bluetooth được công nhận và kết nối:

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

Hy vọng điều này sẽ giúp ai đó!

4

Khi @xsveda viết nếu không có tai nghe nào được kết nối, bạn sẽ nhận được NPE trên Lollipop.

Bạn có thể thử để kiểm tra kết nối tai nghe bluetooth đầu tiên:

mAudioManager.isWiredHeadsetOn() 

Như doc mô tả isWiredHeadsetOn() (doc link) được depricated và chỉ sử dụng để kiểm tra là một tai nghe được kết nối hay không.

Và sau đó bạn có thể sử dụng kết nối startBluetoothSco(). Đối với tôi, tôi đã sử dụng mã này:

này một cho khởi đầu:

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

này một cho dừng:

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

Hy vọng nó giúp.

Các vấn đề liên quan