twilio / twilio-video.js

Twilio’s Programmable Video JavaScript SDK
https://www.twilio.com/docs/video/javascript
Other
571 stars 217 forks source link

Headset problem on android #234

Closed EugeneSnihovsky closed 6 years ago

EugeneSnihovsky commented 6 years ago

Code to reproduce the issue:

export class WebrtcService {

    private _previewTracks: Array<Track>;
    private _activeRoom: Room;
    private _video: any = Video; // tslint:disable-line:no-any

    public constructor(
        private _callEvents: CallEventsService,
        private _platform: Platform
    ) {}

    public endCall(): void {
        if (this._activeRoom) {
            this._activeRoom.disconnect();
        }
    }

    public initWebRtc(connectOptions: ConnectOptions): Promise<void> {
        if (this._previewTracks) {
            connectOptions.tracks = this._previewTracks;
        }
        return this._video.connect(connectOptions.token, { name : connectOptions.roomName })
            .then((room: Room) => this._initRoom(room, {
                localMediaHtmlElement: connectOptions.localMediaHtmlElement,
                remoteMediaHtmlElement: connectOptions.remoteMediaHtmlElement
            }));
    }

    private _initRoom(room: Room, connectOptions: ConnectOptions): void {
        this._activeRoom = room;
        this._initLocalMediaView(room, connectOptions);
        this._initParticipantConnectedListener(room);
        this._initTrackAddedListener(room, connectOptions);
        this._initTrackRemovedListener(room);
        this._initParticipantDisconnectedListener(room);
        this._initDisconnectListener(room);
    }

    private _initLocalMediaView(room: Room, connectOptions: ConnectOptions): void {
        let previewLocalVideo: HTMLElement = connectOptions.localMediaHtmlElement.querySelector('video');

        // attach LocalParticipant's Tracks, if not already attached.
        if (!previewLocalVideo) {
            this._attachParticipantTracks(room.localParticipant, connectOptions.localMediaHtmlElement);
        }

        // attach the Tracks of the Room's Participants.
        room.participants.forEach((participant: Participant) => {
            this._attachParticipantTracks(participant, connectOptions.remoteMediaHtmlElement);
        });
    }

    /**
     * Attach Participant's Tracks to DOM
     */
    private _attachParticipantTracks(participant: Participant, container: Element): void {
        let tracks: Array<EventTrack> = Array.from(participant.tracks.values());
        this._attachTracks(tracks, container);
    }

    /**
     * Attach local Tracks to the DOM
     */
    private _attachTracks(tracks: Array<EventTrack>, container: Element): void {
        tracks.forEach((track: EventTrack) => container.appendChild(track.attach()));
    }

    /**
     * Detach the Participant's Tracks from the DOM
     */
    private _detachParticipantTracks(participant: Participant): void {
        let tracks: Array<EventTrack> = Array.from(participant.tracks.values());
        this._detachTracks(tracks);
    }

    /**
     * Detach local Tracks from the DOM
     */
    private _detachTracks(tracks: Array<EventTrack>): void {
        tracks.forEach((track: EventTrack) => track.detach()
            .forEach((detachedElement: Element) => detachedElement.remove()));
    }

    /**
     * Listener when Participant joins the Room, log event
     */
    private _initParticipantConnectedListener(room: Room): void {
        room.on('participantConnected', (participant: Participant) => {
            console.log('PARTICIPANT_CONNECTED');
        });
    }

    /**
     * Listener when participant adds Track, attach to the DOM
     */
    private _initTrackAddedListener(room: Room, connectOptions: ConnectOptions): void {
        let self: WebrtcService = this;
        room.on('trackAdded', (track: EventTrack, participant: Participant) => {
            self._attachTracks([track], connectOptions.remoteMediaHtmlElement);
            console.log('TRACK_ADDED');
        });
    }

    /**
     * Listener when participant removes Track, detach it from DOM.
     */
    private _initTrackRemovedListener(room: Room): void {
        let self: WebrtcService = this;
        room.on('trackRemoved', (track: EventTrack, participant: Participant) => {
            self._detachTracks([track]);
            console.log('TRACK_REMOVED');
        });
    }

    /**
     * Listener when a Participant leaves the Room, detach its Tracks.
     */
    private _initParticipantDisconnectedListener(room: Room): void {
        let self: WebrtcService = this;
        room.on('participantDisconnected', (participant: Participant) => {
            self._detachParticipantTracks(participant);
            console.log('PARTICIPANT_DISCONNECTED');
        });
    }

    /**
     * Listener once LocalParticipant leaves room, detach Tracks of all Participants, including that of LocalParticipant
     */
    private _initDisconnectListener(room: Room): void {
        let self: WebrtcService = this;
        room.on('disconnected', () => {
            if (self._previewTracks) {
                self._previewTracks.forEach((track: Track) => track.stop());
            }
            self._detachParticipantTracks(room.localParticipant);
            room.participants
                .forEach((participant: Participant) => self._detachParticipantTracks(participant));
            self._activeRoom = null;
        });
    }

}

Expected behavior:

I want to listen music in my headset after finish twilio call

Actual behavior:

My cordova app based on video-quickstart-js with latest twilio-video.js module (1.6.0)

  1. I am listening music on my android device in headset (standard music player)
  2. My cordova app detected incoming call
  3. I stop music in my music player app
  4. I begin twilio call in my app
  5. I end twilio call in my app
  6. I switch to music player and continue to listen music
  7. Music doesn't play in my headset it play in device speakerphone

To continue to listen music in headset I need to reload my music player.

This bug reproduced in three of my real android devices (different brands and android versions) with four different headsets.

Software versions:

markandrus commented 6 years ago

Hi @EugeneSnihovsky,

Your twilio-video.js code sample looks correct. I have a feeling this is going to be an issue in either

Do you know if Cordova or the Cordova/twilio-video.js integration you are using may be changing device defaults? Otherwise, we may have to look for open Android bugs re: music player and resuming playback through headset.

Mark