twilio / audioswitch

An Android audio management library for real-time communication apps.
Apache License 2.0
163 stars 50 forks source link

ConcurrentModificationException #114

Closed velevtzvetlin closed 1 year ago

velevtzvetlin commented 2 years ago
    java.util.ConcurrentModificationException: null
    at java.util.ArrayList$Itr.next(ArrayList.java:860)
    at java.util.AbstractCollection.toString(AbstractCollection.java:461)
    at java.lang.String.valueOf(String.java:2924)
    at java.lang.StringBuilder.append(StringBuilder.java:132)
    at com.twilio.audioswitch.AudioSwitch.addAvailableAudioDevices(AudioSwitch.kt:339)
    at com.twilio.audioswitch.AudioSwitch.enumerateDevices(AudioSwitch.kt:265)
    at com.twilio.audioswitch.AudioSwitch.enumerateDevices$default(AudioSwitch.kt:264)
    at com.twilio.audioswitch.AudioSwitch.start(AudioSwitch.kt:161)
    at com.happytheapp.react.RNTwilioVoiceSDK.TwilioVoiceSDKModule.connect(TwilioVoiceSDKModule.java:259)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:372)
    at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:151)
    at com.facebook.react.bridge.queue.NativeRunnable.run(NativeRunnable.java)
    at android.os.Handler.handleCallback(Handler.java:938)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:27)
    at android.os.Looper.loop(Looper.java:246)
    at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:226)
    at java.lang.Thread.run(Thread.java:923)
  1. make call (with headphones plugged in) => audioSwitch.start(...)
  2. hang up => audioSwitch.stop
  3. unplug headphones
  4. make call right after pulling headphones. => audioSwitch.start(...)

    seems like enumerateDevices is called twice possibly? once by audioSwitch.start() and a also by wiredDeviceConnectionListener

velevtzvetlin commented 2 years ago

would it make sense to call enumerateDevices before setting up the listeners? https://github.com/twilio/audioswitch/blob/ac4900b2a507828c1b67fa3717b82b9aed23fb4f/audioswitch/src/main/java/com/twilio/audioswitch/AudioSwitch.kt#L162

Feroz-Istar commented 2 years ago

I am also getting the same exception


 Fatal Exception: java.util.ConcurrentModificationException 
TwilioCallService$$ExternalSyntheticLambda1.invoke (Unknown Source:6)
com.twilio.audioswitch.AudioSwitch.enumerateDevices (AudioSwitch.kt:307)
com.twilio.audioswitch.AudioSwitch.enumerateDevices$default (AudioSwitch.kt:270)
com.twilio.audioswitch.AudioSwitch$bluetoothDeviceConnectionListener$1.onBluetoothHeadsetActivationError(AudioSwitch.kt:60)
com.twilio.audioswitch.bluetooth.BluetoothHeadsetManager$EnableBluetoothScoJob.scoTimeOutAction (BluetoothHeadsetManager.kt:332)
com.twilio.audioswitch.bluetooth.BluetoothScoJob$BluetoothScoRunnable.run (BluetoothScoJob.kt:57)

I am using Android Service, iterating audio devices as bluetooth is not get connected automatically so manually setting it, code is below:


List<AudioDevice> availableAudioDevices;
private AudioSwitch audioSwitch;

@Override
    public void onCreate() {
        super.onCreate();
 audioSwitch = new AudioSwitch(getApplicationContext(), false, focusChange -> {
        }, preferredDevices);

        audioSwitch.start((audioDevices, audioDevice) -> {
            String selectedDeviceName = audioDevice.getName();

            for (AudioDevice device : audioDevices) {
                if ( selectedDeviceName == device.getName() ) {
                    switch (selectedDeviceName) {
                        case "Speakerphone":
                            FirebaseCrashlytics.getInstance().log("audioDevices "+ audioDevices);
                            try{
                                if ( audioDevices.size() > 2 ) {
                                    audioSwitch.selectDevice(audioDevices.get(audioDevices.size() - 1));
                                } else {
                                    audioSwitch.selectDevice(audioDevices.get(1));
                                }
                            }catch (Exception e){
                                FirebaseCrashlytics.getInstance().log(e.getMessage());
                                audioSwitch.selectDevice(audioDevices.get(0));
                            }
                            break;
                        default:
                            audioSwitch.selectDevice(audioDevices.get(0));
                            break;
                    }
                }
            }

            return Unit.INSTANCE;
        });
        availableAudioDevices = audioSwitch.getAvailableAudioDevices();
        //  Log.d(TAG,"ff- >>" + gson.toJson(availableAudioDevices));
        audioSwitch.selectDevice(availableAudioDevices.get(0));

}

getting runtime exception at while iterating  for audioDevices 

`for(AudioDevice device : audioDevices) 
`
ocarevs commented 1 year ago

This issue has been resolved as part of https://github.com/twilio/audioswitch/pull/142