AudioManager.startBluetoothSco() се срива на Android Lollipop

Когато правите повикване към AudioManager.startBluetoothSCO(), докато насочен към API ниво 18 или по-високо в манифеста, в документацията се посочва, че се установява необработена аудио връзка и ако се насочва към API 17 или по-ниско, се използва виртуално гласово повикване.

До API ниво 20 (Android L Preview) това работи добре, насочено към всеки 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)

Ако насоча API ниво 17 или по-ниско на Android Lollipop, всичко работи според очакванията.

Вярвам, че източникът на проблема се крие в промяна в аудио кода на 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? Ако не, бихте ли могли да посочите доклада за грешка, който подадох с Google, за да увеличи шанса да бъде разгледан :-)


person Julian Claudino    schedule 29.10.2014    source източник
comment
Дори и да не получа срива, устройството изглежда не насочва аудиото от Bluetooth микрофона.   -  person Learn OpenGL ES    schedule 26.02.2015
comment
Имам същия проблем, микрофонът не се маршрутизира, има ли решение за това?   -  person Shofiqul Alam    schedule 18.04.2015


Отговори (3)


Както @xsveda написа, ако няма свързани слушалки, ще получите NPE на Lollipop.

Можете първо да опитате да проверите връзката на Bluetooth слушалките:

mAudioManager.isWiredHeadsetOn()

Както е описано в документа isWiredHeadsetOn() (връзка към документ) е оттеглен и използва само за проверка дали слушалките са свързани или не.

И след това можете да използвате startBluetoothSco() връзка. Що се отнася до мен, използвах този код:

Това за начало:

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

Това за стоп:

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

Дано помогне.

person busylee    schedule 12.12.2014

След няколко дни на отчаяние намерих просто решение:

startBluetoothSco() хвърля NPE само ако няма свързано Bluetooth устройство, за да може да бъде уловено и игнорирано, тъй като „няма с кого да се говори“. Ако например са свързани BT слушалки, SCO се стартира успешно и възпроизвеждането работи!

person xsveda    schedule 13.11.2014
comment
Това наистина изглежда като по-добро заобиколно решение от настройването на целевия SDK на 17, но при по-нататъшно проучване забелязах, че и при двете заобиколни решения звукът не се насочва през Bluetooth микрофона, а вместо това излиза през микрофона на телефона. Лесно е да пропуснете това, ако телефонът и bluetooth устройството ви са близо един до друг. - person Julian Claudino; 13.11.2014

Засега това, което изглежда работи за мен, беше игнорирането на 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, това работи за мен и маршрутизиране през Bluetooth микрофона, уверете се, че Bluetooth устройството е разпознато и свързано:

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

Надявам се това да помогне на някого!

person Danpe    schedule 14.11.2014