10000 Firebase · Issue #18 · flutter-webrtc/flutter-webrtc · GitHub
[go: up one dir, main page]

Skip to content
8000

Firebase #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
rlee1990 opened this issue Oct 23, 2018 · 6 comments
Closed

Firebase #18

rlee1990 opened this issue Oct 23, 2018 · 6 comments

Comments

@rlee1990
Copy link

Can this be used with firebase?

@rostopira
Copy link
Collaborator
rostopira commented Oct 23, 2018

@rlee1990 yes, I use firebase database as signaling server with this plugin

@rlee1990
Copy link
Author

Any docs on setting this up just really lost on how to set this up with firebase.
@rostopira

@rostopira
Copy link
Collaborator
rostopira commented Oct 23, 2018

@rlee1990 you can use my basic sample, but keep in mind, that this example is incomplete, it doesn't include TURN config and ICE-connection/ICE-gathering state listeners

import 'package:firebase_database/firebase_database.dart';
typedef void StreamStateCallback(MediaStream stream);

class FirebaseRtcClient {
  FirebaseRtcClient(this.target, this.roomId) {
    isInitiator = roomId == null;
    if (roomId != null) {
      _dbRef = FirebaseDatabase.instance.reference().child("t/$roomId");
    } else {
      _dbRef = FirebaseDatabase.instance.reference().child("t").push();
      roomId = _dbRef.key;
    }
  }

  //Public vars
  bool isInitiator;
  User target;
  String roomId;
  var useTurn = false;
  StreamStateCallback onAddStream;
  StreamStateCallback onRemoveStream;

  //Public getters
  get state => _state;

  //Abstract vars
  final Map<String, dynamic> _constraints = {
    'mandatory': {
      'OfferToReceiveAudio': true,
      'OfferToReceiveVideo': true,
    },
    'optional': [{'DtlsSrtpKeyAgreement': true}]
  };

  //Private vars
  var isFrontFacing = false;
  RTCDataChannel _myDataChannel;
  DatabaseReference _dbRef;
  MediaStream _localStream;
  RTCPeerConnection _peerCon;
  var _state = SignalingState.CallStateNew;
  StreamSubscription<Event> _listener;
  Map<String, dynamic> _iceServers = {
    'iceServers': [
      {'url': 'stun:stun.l.google.com:19302'},
    ]
  };

  connect() async {
    await _createStream();
    if (useTurn)
      await _loadTurn();
    _peerCon = await createPeerConnection(_iceServers, _constraints);
    if (_localStream != null)
      _peerCon.addStream(_localStream);
    _peerCon.onIceCandidate = (candidate) {
      this._send({
        't': 'ice',
        'smi': candidate.sdpMlineIndex,
        'sm': candidate.sdpMid,
        'c': candidate.candidate,
        'id': S.userId
      });
    };
    _peerCon.onAddStream = onAddStream;
    _peerCon.onRemoveStream = onRemoveStream;
    if (isInitiator) {
      var dci = RTCDataChannelInit();
      dci.id = 1;
      _myDataChannel = await _peerCon.createDataChannel("commands", dci);
    } else {
      _peerCon.onDataChannel = (dataChannel) {
        print("On new data channel");
        dataChannel.onMessage = _onDataChannelMessage;
      };
    }
    if (isInitiator) {
      await _createOffer();
    }
    _listener = _dbRef.onChildAdded.listen((event) {
      final val = event.snapshot.value;
      if (event.snapshot.key == '0' //Zero reserved for future use
          || val["id"] == S.userId)
        return;
      if (val["t"] == "ice") {
        _peerCon.addCandidate(
            RTCIceCandidate(val['c'], val['sm'], val['smi']));
        return;
      }
      if (val['t'] == "ans") {
        assert(isInitiator);
        _peerCon.setRemoteDescription(
            RTCSessionDescription(val['sdp'], val['tp']));
        return;
      }
      if (val['t'] == "off") {
        assert(!isInitiator);
        _peerCon.setRemoteDescription(
            RTCSessionDescription(val['sdp'], val['tp']));
        _createAnswer();
        return;
      }
    });
    if (isInitiator)
      _sendPush();
  }

  void _onDataChannelMessage(String msg) async {
    //TODO
  }

  void close() {
    _listener?.cancel();
    _dbRef.remove();
    _localStream?.dispose();
    _localStream = null;
    _peerCon?.close();
  }

  _loadTurn() async {
    //TODO
  }

  Future<void> _send(data) async =>
    await _dbRef.push().set(data);

  _createStream() async {
    final Map<String, dynamic> mediaConstraints = {
      'audio': true,
      'video': {
        'mandatory': {
          'minWidth': '1280',
          'minHeight': '720',
          'minFrameRate': '30'
        },
        'facingMode': 'environment'
      },
      'facingMode': 'environment',
      'optional': []
    };
    _localStream = await navigator.getUserMedia(mediaConstraints);
  }

  _createOffer() async {
    final off = await _peerCon.createOffer(_constraints);
    await _peerCon.setLocalDescription(off);
    await _send({
      't': 'off',
      'sdp': off.sdp,
      'tp': off.type,
      'id': S.userId
    });
  }

  void _createAnswer() async {
    final ans = await _peerCon.createAnswer(_constraints);
    await _peerCon.setLocalDescription(ans);
    await _send({
      't': 'ans',
      'sdp': ans.sdp,
      'tp': ans.type,
      'id': S.userId
    });
  }

  void _sendPush() {
    const url = "https://onesignal.com/api/v1/notifications";
    http.post(url, headers: {
      "Content-Type": "application/json"
    }, body: json.encode({
      "app_id": appId,
      "data": {
        "id": S.userId,
        "v": roomId,
        "t": 1
      },
      "content_available": true,
      "ttl": 120,
      "priority": 10,
      "include_player_ids": [target.pushId]
    })).then((response) {
      print("OneSignal result: ${response.body}");
    }, onError: (err) {
      print("OneSignal error: $err");
    });
  }

}

@rlee1990
Copy link
Author

thanks

@rostopira
Copy link
Collaborator

@rlee1990 please, close issue now, firebase isn't related to this plugin, and it's not a stackoverflow

@rostopira
Copy link
Collaborator
rostopira commented Dec 3, 2018

@harshapulikollu yeah, sure, just give me a single reason to do that for you
That's not 10 minutes task
If you don't understand code I've shared above, then just go RTFM, I've spent more than year to learn and understand how WebRTC works without anyones help, so why do you think somebody is going to do that for you?
Actually, I'm going to make working sample app on both Firebase RTDB and Firestore using code I have already, but I have some real job to be done
So only god knows when I'll get some free time
And only god knows, if you will understand how my demo works, if you don't understand a difference between STUN and TURN (just google it, really)

evdokimovs pushed a commit to evdokimovs/flutter-webrtc that referenced this issue Jun 6, 2024
…brtc#18)

Additionally:
- do not download `libwebrtc` library if it's already present

Co-authored-by: logist322 <hytornoy-99@mail.ru>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants
0