Updates
parent
3fb8876c31
commit
a60f66a069
@ -1,204 +1,204 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:diplomaticquarterapp/pages/conference/web_rtc/widgets/cam_view_widget.dart';
|
||||
import 'package:diplomaticquarterapp/pages/conference/widgets/noise_box.dart';
|
||||
import 'package:diplomaticquarterapp/pages/webRTC/signaling.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
|
||||
import '../conference_button_bar.dart';
|
||||
|
||||
class CallHomePage extends StatefulWidget {
|
||||
final String receiverId;
|
||||
final String callerId;
|
||||
|
||||
const CallHomePage({Key key, this.receiverId, this.callerId}) : super(key: key);
|
||||
|
||||
@override
|
||||
_CallHomePageState createState() => _CallHomePageState();
|
||||
}
|
||||
|
||||
class _CallHomePageState extends State<CallHomePage> {
|
||||
bool showNoise = true;
|
||||
RTCVideoRenderer _localRenderer = RTCVideoRenderer();
|
||||
RTCVideoRenderer _remoteRenderer = RTCVideoRenderer();
|
||||
|
||||
final StreamController<bool> _audioButton = StreamController<bool>.broadcast();
|
||||
final StreamController<bool> _videoButton = StreamController<bool>.broadcast();
|
||||
final StreamController<bool> _onButtonBarVisibleStreamController = StreamController<bool>.broadcast();
|
||||
final StreamController<double> _onButtonBarHeightStreamController = StreamController<double>.broadcast();
|
||||
|
||||
//Stream to enable video
|
||||
MediaStream localMediaStream;
|
||||
MediaStream remoteMediaStream;
|
||||
Signaling signaling = Signaling();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
startCall();
|
||||
}
|
||||
|
||||
startCall() async{
|
||||
await _localRenderer.initialize();
|
||||
await _remoteRenderer.initialize();
|
||||
await signaling.init();
|
||||
final connected = await receivedCall();
|
||||
}
|
||||
|
||||
|
||||
Future<bool> receivedCall() async {
|
||||
//Stream local media
|
||||
localMediaStream = await navigator.mediaDevices.getUserMedia({'video': true, 'audio': true});
|
||||
_localRenderer.srcObject = localMediaStream;
|
||||
|
||||
final connected = await signaling.acceptCall(widget.callerId, widget.receiverId, localMediaStream: localMediaStream,
|
||||
onRemoteMediaStream: (remoteMediaStream){
|
||||
|
||||
// print(remoteMediaStream.toString());
|
||||
// print(json.encode(remoteMediaStream.getTracks().asMap()));
|
||||
this.remoteMediaStream = remoteMediaStream;
|
||||
_remoteRenderer.srcObject = remoteMediaStream;
|
||||
_remoteRenderer.addListener(() {
|
||||
print('_remoteRenderer');
|
||||
print(_remoteRenderer);
|
||||
setState(() {});
|
||||
});
|
||||
},
|
||||
onRemoteTrack: (track){
|
||||
_remoteRenderer.srcObject.addTrack(track.track);
|
||||
// setState(() {
|
||||
// });
|
||||
|
||||
print(track.streams.first.getVideoTracks());
|
||||
print(track.streams.first.getAudioTracks());
|
||||
print(json.encode(track.streams.asMap()));
|
||||
}
|
||||
);
|
||||
|
||||
if(connected){
|
||||
signaling.signalR.listen(
|
||||
onAcceptCall: (arg0){
|
||||
print(arg0.toString());
|
||||
},
|
||||
onCandidate: (candidateJson){
|
||||
signaling.addCandidate(candidateJson);
|
||||
},
|
||||
onDeclineCall: (arg0,arg1){
|
||||
// _onHangup();
|
||||
},
|
||||
onHangupCall: (arg0){
|
||||
// _onHangup();
|
||||
},
|
||||
|
||||
onOffer: (offerSdp, callerUser) async{
|
||||
print('${offerSdp.toString()} | ${callerUser.toString()}');
|
||||
await signaling.answerOffer(offerSdp);
|
||||
}
|
||||
);
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
signaling.dispose();
|
||||
_localRenderer?.dispose();
|
||||
_remoteRenderer?.dispose();
|
||||
_audioButton?.close();
|
||||
_videoButton?.close();
|
||||
localMediaStream?.dispose();
|
||||
remoteMediaStream?.dispose();
|
||||
_disposeStreamsAndSubscriptions();
|
||||
}
|
||||
|
||||
Future<void> _disposeStreamsAndSubscriptions() async {
|
||||
if (_onButtonBarVisibleStreamController != null) await _onButtonBarVisibleStreamController.close();
|
||||
if (_onButtonBarHeightStreamController != null) await _onButtonBarHeightStreamController.close();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: buildLayout(),
|
||||
);
|
||||
}
|
||||
|
||||
LayoutBuilder buildLayout() {
|
||||
return LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
return Stack(
|
||||
children: [
|
||||
CamViewWidget(
|
||||
localRenderer: _localRenderer,
|
||||
remoteRenderer: _remoteRenderer,
|
||||
constraints: constraints,
|
||||
onButtonBarVisibleStreamController: _onButtonBarVisibleStreamController,
|
||||
onButtonBarHeightStreamController: _onButtonBarHeightStreamController,
|
||||
),
|
||||
ConferenceButtonBar(
|
||||
audioEnabled: _audioButton.stream,
|
||||
videoEnabled: _videoButton.stream,
|
||||
onAudioEnabled: _onAudioEnable,
|
||||
onVideoEnabled: _onVideoEnabled,
|
||||
onSwitchCamera: _onSwitchCamera,
|
||||
onHangup: _onHangup,
|
||||
onPersonAdd: () {},
|
||||
onPersonRemove: () {},
|
||||
onHeight: _onHeightBar,
|
||||
onShow: _onShowBar,
|
||||
onHide: _onHideBar,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Function _onAudioEnable() {
|
||||
final audioTrack = localMediaStream.getAudioTracks()[0];
|
||||
final mute = audioTrack.muted;
|
||||
Helper.setMicrophoneMute(!mute, audioTrack);
|
||||
_audioButton.add(mute);
|
||||
}
|
||||
|
||||
Function _onVideoEnabled() {
|
||||
final videoTrack = localMediaStream.getVideoTracks()[0];
|
||||
bool videoEnabled = videoTrack.enabled;
|
||||
localMediaStream.getVideoTracks()[0].enabled = !videoEnabled;
|
||||
_videoButton.add(!videoEnabled);
|
||||
}
|
||||
|
||||
Function _onSwitchCamera() {
|
||||
Helper.switchCamera(localMediaStream.getVideoTracks()[0]);
|
||||
}
|
||||
|
||||
void _onShowBar() {
|
||||
setState(() {
|
||||
});
|
||||
_onButtonBarVisibleStreamController.add(true);
|
||||
}
|
||||
|
||||
void _onHeightBar(double height) {
|
||||
_onButtonBarHeightStreamController.add(height);
|
||||
}
|
||||
|
||||
void _onHideBar() {
|
||||
setState(() {
|
||||
SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
|
||||
});
|
||||
_onButtonBarVisibleStreamController.add(false);
|
||||
}
|
||||
|
||||
Future<void> _onHangup() async {
|
||||
signaling.hangupCall(widget.callerId, widget.receiverId);
|
||||
print('onHangup');
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
}
|
||||
// import 'dart:async';
|
||||
// import 'dart:convert';
|
||||
//
|
||||
// import 'package:diplomaticquarterapp/pages/conference/web_rtc/widgets/cam_view_widget.dart';
|
||||
// import 'package:diplomaticquarterapp/pages/conference/widgets/noise_box.dart';
|
||||
// import 'package:diplomaticquarterapp/pages/webRTC/signaling.dart';
|
||||
// import 'package:flutter/material.dart';
|
||||
// import 'package:flutter/services.dart';
|
||||
// import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
//
|
||||
// import '../conference_button_bar.dart';
|
||||
//
|
||||
// class CallHomePage extends StatefulWidget {
|
||||
// final String receiverId;
|
||||
// final String callerId;
|
||||
//
|
||||
// const CallHomePage({Key key, this.receiverId, this.callerId}) : super(key: key);
|
||||
//
|
||||
// @override
|
||||
// _CallHomePageState createState() => _CallHomePageState();
|
||||
// }
|
||||
//
|
||||
// class _CallHomePageState extends State<CallHomePage> {
|
||||
// bool showNoise = true;
|
||||
// RTCVideoRenderer _localRenderer = RTCVideoRenderer();
|
||||
// RTCVideoRenderer _remoteRenderer = RTCVideoRenderer();
|
||||
//
|
||||
// final StreamController<bool> _audioButton = StreamController<bool>.broadcast();
|
||||
// final StreamController<bool> _videoButton = StreamController<bool>.broadcast();
|
||||
// final StreamController<bool> _onButtonBarVisibleStreamController = StreamController<bool>.broadcast();
|
||||
// final StreamController<double> _onButtonBarHeightStreamController = StreamController<double>.broadcast();
|
||||
//
|
||||
// //Stream to enable video
|
||||
// MediaStream localMediaStream;
|
||||
// MediaStream remoteMediaStream;
|
||||
// Signaling signaling = Signaling();
|
||||
//
|
||||
// @override
|
||||
// void initState() {
|
||||
// // TODO: implement initState
|
||||
// super.initState();
|
||||
// startCall();
|
||||
// }
|
||||
//
|
||||
// startCall() async{
|
||||
// await _localRenderer.initialize();
|
||||
// await _remoteRenderer.initialize();
|
||||
// await signaling.init();
|
||||
// final connected = await receivedCall();
|
||||
// }
|
||||
//
|
||||
//
|
||||
// Future<bool> receivedCall() async {
|
||||
// //Stream local media
|
||||
// localMediaStream = await navigator.mediaDevices.getUserMedia({'video': true, 'audio': true});
|
||||
// _localRenderer.srcObject = localMediaStream;
|
||||
//
|
||||
// final connected = await signaling.acceptCall(widget.callerId, widget.receiverId, localMediaStream: localMediaStream,
|
||||
// onRemoteMediaStream: (remoteMediaStream){
|
||||
//
|
||||
// // print(remoteMediaStream.toString());
|
||||
// // print(json.encode(remoteMediaStream.getTracks().asMap()));
|
||||
// this.remoteMediaStream = remoteMediaStream;
|
||||
// _remoteRenderer.srcObject = remoteMediaStream;
|
||||
// _remoteRenderer.addListener(() {
|
||||
// print('_remoteRenderer');
|
||||
// print(_remoteRenderer);
|
||||
// setState(() {});
|
||||
// });
|
||||
// },
|
||||
// onRemoteTrack: (track){
|
||||
// _remoteRenderer.srcObject.addTrack(track.track);
|
||||
// // setState(() {
|
||||
// // });
|
||||
//
|
||||
// print(track.streams.first.getVideoTracks());
|
||||
// print(track.streams.first.getAudioTracks());
|
||||
// print(json.encode(track.streams.asMap()));
|
||||
// }
|
||||
// );
|
||||
//
|
||||
// if(connected){
|
||||
// signaling.signalR.listen(
|
||||
// onAcceptCall: (arg0){
|
||||
// print(arg0.toString());
|
||||
// },
|
||||
// onCandidate: (candidateJson){
|
||||
// signaling.addCandidate(candidateJson);
|
||||
// },
|
||||
// onDeclineCall: (arg0,arg1){
|
||||
// // _onHangup();
|
||||
// },
|
||||
// onHangupCall: (arg0){
|
||||
// // _onHangup();
|
||||
// },
|
||||
//
|
||||
// onOffer: (offerSdp, callerUser) async{
|
||||
// print('${offerSdp.toString()} | ${callerUser.toString()}');
|
||||
// await signaling.answerOffer(offerSdp);
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
// return connected;
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// void dispose() {
|
||||
// // TODO: implement dispose
|
||||
// super.dispose();
|
||||
// signaling.dispose();
|
||||
// _localRenderer?.dispose();
|
||||
// _remoteRenderer?.dispose();
|
||||
// _audioButton?.close();
|
||||
// _videoButton?.close();
|
||||
// localMediaStream?.dispose();
|
||||
// remoteMediaStream?.dispose();
|
||||
// _disposeStreamsAndSubscriptions();
|
||||
// }
|
||||
//
|
||||
// Future<void> _disposeStreamsAndSubscriptions() async {
|
||||
// if (_onButtonBarVisibleStreamController != null) await _onButtonBarVisibleStreamController.close();
|
||||
// if (_onButtonBarHeightStreamController != null) await _onButtonBarHeightStreamController.close();
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Scaffold(
|
||||
// backgroundColor: Colors.white,
|
||||
// body: buildLayout(),
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// LayoutBuilder buildLayout() {
|
||||
// return LayoutBuilder(
|
||||
// builder: (BuildContext context, BoxConstraints constraints) {
|
||||
// return Stack(
|
||||
// children: [
|
||||
// CamViewWidget(
|
||||
// localRenderer: _localRenderer,
|
||||
// remoteRenderer: _remoteRenderer,
|
||||
// constraints: constraints,
|
||||
// onButtonBarVisibleStreamController: _onButtonBarVisibleStreamController,
|
||||
// onButtonBarHeightStreamController: _onButtonBarHeightStreamController,
|
||||
// ),
|
||||
// ConferenceButtonBar(
|
||||
// audioEnabled: _audioButton.stream,
|
||||
// videoEnabled: _videoButton.stream,
|
||||
// onAudioEnabled: _onAudioEnable,
|
||||
// onVideoEnabled: _onVideoEnabled,
|
||||
// onSwitchCamera: _onSwitchCamera,
|
||||
// onHangup: _onHangup,
|
||||
// onPersonAdd: () {},
|
||||
// onPersonRemove: () {},
|
||||
// onHeight: _onHeightBar,
|
||||
// onShow: _onShowBar,
|
||||
// onHide: _onHideBar,
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// Function _onAudioEnable() {
|
||||
// final audioTrack = localMediaStream.getAudioTracks()[0];
|
||||
// final mute = audioTrack.muted;
|
||||
// Helper.setMicrophoneMute(!mute, audioTrack);
|
||||
// _audioButton.add(mute);
|
||||
// }
|
||||
//
|
||||
// Function _onVideoEnabled() {
|
||||
// final videoTrack = localMediaStream.getVideoTracks()[0];
|
||||
// bool videoEnabled = videoTrack.enabled;
|
||||
// localMediaStream.getVideoTracks()[0].enabled = !videoEnabled;
|
||||
// _videoButton.add(!videoEnabled);
|
||||
// }
|
||||
//
|
||||
// Function _onSwitchCamera() {
|
||||
// Helper.switchCamera(localMediaStream.getVideoTracks()[0]);
|
||||
// }
|
||||
//
|
||||
// void _onShowBar() {
|
||||
// setState(() {
|
||||
// });
|
||||
// _onButtonBarVisibleStreamController.add(true);
|
||||
// }
|
||||
//
|
||||
// void _onHeightBar(double height) {
|
||||
// _onButtonBarHeightStreamController.add(height);
|
||||
// }
|
||||
//
|
||||
// void _onHideBar() {
|
||||
// setState(() {
|
||||
// SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
|
||||
// });
|
||||
// _onButtonBarVisibleStreamController.add(false);
|
||||
// }
|
||||
//
|
||||
// Future<void> _onHangup() async {
|
||||
// signaling.hangupCall(widget.callerId, widget.receiverId);
|
||||
// print('onHangup');
|
||||
// Navigator.of(context).pop();
|
||||
// }
|
||||
// }
|
||||
|
||||
@ -1,164 +1,164 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:diplomaticquarterapp/models/LiveCare/IncomingCallData.dart';
|
||||
import 'package:diplomaticquarterapp/pages/livecare/incoming_call.dart';
|
||||
import 'package:diplomaticquarterapp/pages/webRTC/signaling.dart';
|
||||
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
|
||||
class CallPage extends StatefulWidget {
|
||||
@override
|
||||
_CallPageState createState() => _CallPageState();
|
||||
}
|
||||
|
||||
class _CallPageState extends State<CallPage> {
|
||||
Signaling signaling = Signaling();
|
||||
RTCVideoRenderer _localRenderer = RTCVideoRenderer();
|
||||
RTCVideoRenderer _remoteRenderer = RTCVideoRenderer();
|
||||
String roomId;
|
||||
TextEditingController textEditingController = TextEditingController(text: '');
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_localRenderer.initialize();
|
||||
_remoteRenderer.initialize();
|
||||
|
||||
// signaling.onRemoteStream = ((stream) {
|
||||
// _remoteRenderer.srcObject = stream;
|
||||
// setState(() {});
|
||||
// });
|
||||
|
||||
fcmConfigure();
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_localRenderer.dispose();
|
||||
_remoteRenderer.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
FirebaseMessaging.instance.getToken().then((value) {
|
||||
print('FCM_TOKEN: $value');
|
||||
});
|
||||
|
||||
return AppScaffold(
|
||||
isShowAppBar: true,
|
||||
showNewAppBar: true,
|
||||
showNewAppBarTitle: true,
|
||||
isShowDecPage: false,
|
||||
appBarTitle: "WebRTC Calling",
|
||||
body: Column(
|
||||
children: [
|
||||
SizedBox(height: 8),
|
||||
Wrap(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 8,
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
dummyCall();
|
||||
},
|
||||
child: Text("Call"),
|
||||
),
|
||||
SizedBox(
|
||||
width: 8,
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
signaling.hangUp(_localRenderer);
|
||||
},
|
||||
child: Text("Hangup"),
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(0.0),
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(top: 0.0, right: 0.0, left: 0.0, bottom: 0.0, child: RTCVideoView(_remoteRenderer)),
|
||||
Positioned(
|
||||
top: 20.0,
|
||||
right: 100.0,
|
||||
left: 20.0,
|
||||
bottom: 300.0,
|
||||
child: RTCVideoView(_localRenderer, mirror: true),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text("Join the following Room: "),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: textEditingController,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
dummyCall() async {
|
||||
final json = {
|
||||
"callerID": "9920",
|
||||
"receiverID": "2001273",
|
||||
"msgID": "123",
|
||||
"notfID": "123",
|
||||
"notification_foreground": "true",
|
||||
"count": "1",
|
||||
"message": "Doctor is calling ",
|
||||
"AppointmentNo": "123",
|
||||
"title": "Rayyan Hospital",
|
||||
"ProjectID": "123",
|
||||
"NotificationType": "10",
|
||||
"background": "1",
|
||||
"doctorname": "Dr Sulaiman Al Habib",
|
||||
"clinicname": "ENT Clinic",
|
||||
"speciality": "Speciality",
|
||||
"appointmentdate": "Sun, 15th Dec, 2019",
|
||||
"appointmenttime": "09:00",
|
||||
"type": "video",
|
||||
"session_id":
|
||||
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImN0eSI6InR3aWxpby1mcGE7dj0xIn0.eyJqdGkiOiJTS2I2NjYyOWMzN2ZhOTM3YjFjNDI2Zjg1MTgyNWFmN2M0LTE1OTg3NzQ1MDYiLCJpc3MiOiJTS2I2NjYyOWMzN2ZhOTM3YjFjNDI2Zjg1MTgyNWFmN2M0Iiwic3ViIjoiQUNhYWQ1YTNmOGM2NGZhNjczNTY3NTYxNTc0N2YyNmMyYiIsImV4cCI6MTU5ODc3ODEwNiwiZ3JhbnRzIjp7ImlkZW50aXR5IjoiSGFyb29uMSIsInZpZGVvIjp7InJvb20iOiJTbWFsbERhaWx5U3RhbmR1cCJ9fX0.7XUS5uMQQJfkrBZu9EjQ6STL6R7iXkso6BtO1HmrQKk",
|
||||
"identity": "Haroon1",
|
||||
"name": "SmallDailyStandup",
|
||||
"videoUrl": "video",
|
||||
"picture": "video",
|
||||
"is_call": "true"
|
||||
};
|
||||
|
||||
IncomingCallData incomingCallData = IncomingCallData.fromJson(json);
|
||||
final result = await Navigator.push(context, MaterialPageRoute(builder: (context) => IncomingCall(incomingCallData: incomingCallData)));
|
||||
}
|
||||
|
||||
fcmConfigure() {
|
||||
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
|
||||
print(message.toString());
|
||||
|
||||
IncomingCallData incomingCallData;
|
||||
if (Platform.isAndroid)
|
||||
incomingCallData = IncomingCallData.fromJson(message.data['data']);
|
||||
else if (Platform.isIOS) incomingCallData = IncomingCallData.fromJson(message.data);
|
||||
if (incomingCallData != null) final result = await Navigator.push(context, MaterialPageRoute(builder: (context) => IncomingCall(incomingCallData: incomingCallData)));
|
||||
});
|
||||
}
|
||||
}
|
||||
// import 'dart:io';
|
||||
//
|
||||
// import 'package:diplomaticquarterapp/models/LiveCare/IncomingCallData.dart';
|
||||
// import 'package:diplomaticquarterapp/pages/livecare/incoming_call.dart';
|
||||
// import 'package:diplomaticquarterapp/pages/webRTC/signaling.dart';
|
||||
// import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
|
||||
// import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
// import 'package:flutter/material.dart';
|
||||
// import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
//
|
||||
// class CallPage extends StatefulWidget {
|
||||
// @override
|
||||
// _CallPageState createState() => _CallPageState();
|
||||
// }
|
||||
//
|
||||
// class _CallPageState extends State<CallPage> {
|
||||
// Signaling signaling = Signaling();
|
||||
// RTCVideoRenderer _localRenderer = RTCVideoRenderer();
|
||||
// RTCVideoRenderer _remoteRenderer = RTCVideoRenderer();
|
||||
// String roomId;
|
||||
// TextEditingController textEditingController = TextEditingController(text: '');
|
||||
//
|
||||
// @override
|
||||
// void initState() {
|
||||
// _localRenderer.initialize();
|
||||
// _remoteRenderer.initialize();
|
||||
//
|
||||
// // signaling.onRemoteStream = ((stream) {
|
||||
// // _remoteRenderer.srcObject = stream;
|
||||
// // setState(() {});
|
||||
// // });
|
||||
//
|
||||
// fcmConfigure();
|
||||
//
|
||||
// super.initState();
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// void dispose() {
|
||||
// _localRenderer.dispose();
|
||||
// _remoteRenderer.dispose();
|
||||
// super.dispose();
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// FirebaseMessaging.instance.getToken().then((value) {
|
||||
// print('FCM_TOKEN: $value');
|
||||
// });
|
||||
//
|
||||
// return AppScaffold(
|
||||
// isShowAppBar: true,
|
||||
// showNewAppBar: true,
|
||||
// showNewAppBarTitle: true,
|
||||
// isShowDecPage: false,
|
||||
// appBarTitle: "WebRTC Calling",
|
||||
// body: Column(
|
||||
// children: [
|
||||
// SizedBox(height: 8),
|
||||
// Wrap(
|
||||
// children: [
|
||||
// SizedBox(
|
||||
// width: 8,
|
||||
// ),
|
||||
// ElevatedButton(
|
||||
// onPressed: () {
|
||||
// dummyCall();
|
||||
// },
|
||||
// child: Text("Call"),
|
||||
// ),
|
||||
// SizedBox(
|
||||
// width: 8,
|
||||
// ),
|
||||
// ElevatedButton(
|
||||
// onPressed: () {
|
||||
// signaling.hangUp(_localRenderer);
|
||||
// },
|
||||
// child: Text("Hangup"),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// SizedBox(height: 8),
|
||||
// Expanded(
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(0.0),
|
||||
// child: Stack(
|
||||
// children: [
|
||||
// Positioned(top: 0.0, right: 0.0, left: 0.0, bottom: 0.0, child: RTCVideoView(_remoteRenderer)),
|
||||
// Positioned(
|
||||
// top: 20.0,
|
||||
// right: 100.0,
|
||||
// left: 20.0,
|
||||
// bottom: 300.0,
|
||||
// child: RTCVideoView(_localRenderer, mirror: true),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.all(8.0),
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// children: [
|
||||
// Text("Join the following Room: "),
|
||||
// Flexible(
|
||||
// child: TextFormField(
|
||||
// controller: textEditingController,
|
||||
// ),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(height: 8)
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// dummyCall() async {
|
||||
// final json = {
|
||||
// "callerID": "9920",
|
||||
// "receiverID": "2001273",
|
||||
// "msgID": "123",
|
||||
// "notfID": "123",
|
||||
// "notification_foreground": "true",
|
||||
// "count": "1",
|
||||
// "message": "Doctor is calling ",
|
||||
// "AppointmentNo": "123",
|
||||
// "title": "Rayyan Hospital",
|
||||
// "ProjectID": "123",
|
||||
// "NotificationType": "10",
|
||||
// "background": "1",
|
||||
// "doctorname": "Dr Sulaiman Al Habib",
|
||||
// "clinicname": "ENT Clinic",
|
||||
// "speciality": "Speciality",
|
||||
// "appointmentdate": "Sun, 15th Dec, 2019",
|
||||
// "appointmenttime": "09:00",
|
||||
// "type": "video",
|
||||
// "session_id":
|
||||
// "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImN0eSI6InR3aWxpby1mcGE7dj0xIn0.eyJqdGkiOiJTS2I2NjYyOWMzN2ZhOTM3YjFjNDI2Zjg1MTgyNWFmN2M0LTE1OTg3NzQ1MDYiLCJpc3MiOiJTS2I2NjYyOWMzN2ZhOTM3YjFjNDI2Zjg1MTgyNWFmN2M0Iiwic3ViIjoiQUNhYWQ1YTNmOGM2NGZhNjczNTY3NTYxNTc0N2YyNmMyYiIsImV4cCI6MTU5ODc3ODEwNiwiZ3JhbnRzIjp7ImlkZW50aXR5IjoiSGFyb29uMSIsInZpZGVvIjp7InJvb20iOiJTbWFsbERhaWx5U3RhbmR1cCJ9fX0.7XUS5uMQQJfkrBZu9EjQ6STL6R7iXkso6BtO1HmrQKk",
|
||||
// "identity": "Haroon1",
|
||||
// "name": "SmallDailyStandup",
|
||||
// "videoUrl": "video",
|
||||
// "picture": "video",
|
||||
// "is_call": "true"
|
||||
// };
|
||||
//
|
||||
// IncomingCallData incomingCallData = IncomingCallData.fromJson(json);
|
||||
// final result = await Navigator.push(context, MaterialPageRoute(builder: (context) => IncomingCall(incomingCallData: incomingCallData)));
|
||||
// }
|
||||
//
|
||||
// fcmConfigure() {
|
||||
// FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
|
||||
// print(message.toString());
|
||||
//
|
||||
// IncomingCallData incomingCallData;
|
||||
// if (Platform.isAndroid)
|
||||
// incomingCallData = IncomingCallData.fromJson(message.data['data']);
|
||||
// else if (Platform.isIOS) incomingCallData = IncomingCallData.fromJson(message.data);
|
||||
// if (incomingCallData != null) final result = await Navigator.push(context, MaterialPageRoute(builder: (context) => IncomingCall(incomingCallData: incomingCallData)));
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
@ -1,277 +1,277 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:diplomaticquarterapp/uitl/SignalRUtil.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
|
||||
typedef void StreamStateCallback(MediaStream stream);
|
||||
typedef void RTCIceGatheringStateCallback(RTCIceGatheringState state);
|
||||
typedef void RTCPeerConnectionStateCallback(RTCPeerConnectionState state);
|
||||
typedef void RTCSignalingStateCallback(RTCSignalingState state);
|
||||
|
||||
final Map<String, dynamic> constraints = {
|
||||
'mandatory': {},
|
||||
'optional': [
|
||||
{'DtlsSrtpKeyAgreement': true},
|
||||
]
|
||||
};
|
||||
|
||||
Map<String, dynamic> snapsis_ice_config = {
|
||||
'iceServers': [
|
||||
{ "urls": 'stun:15.185.116.59:3478' },
|
||||
{ "urls": "turn:15.185.116.59:3479", "username": "admin", "credential": "admin" },
|
||||
],
|
||||
// 'sdpSemantics': 'unified-plan'
|
||||
};
|
||||
Map<String, dynamic> twilio_ice_config = {
|
||||
"ice_servers": [
|
||||
{
|
||||
"url": "stun:global.stun.twilio.com:3478?transport=udp",
|
||||
"urls": "stun:global.stun.twilio.com:3478?transport=udp"
|
||||
},
|
||||
{
|
||||
"url": "turn:global.turn.twilio.com:3478?transport=udp",
|
||||
"username": "ce8042842b62c21bd20b176f80d6067fd3db81b1e9766312418ef5421d9ca2a2",
|
||||
"urls": "turn:global.turn.twilio.com:3478?transport=udp",
|
||||
"credential": "UzGOsiLwPZJ32cjafAebfDDpVrqeQjgpFHZEdau/8r4="
|
||||
},
|
||||
{
|
||||
"url": "turn:global.turn.twilio.com:3478?transport=tcp",
|
||||
"username": "ce8042842b62c21bd20b176f80d6067fd3db81b1e9766312418ef5421d9ca2a2",
|
||||
"urls": "turn:global.turn.twilio.com:3478?transport=tcp",
|
||||
"credential": "UzGOsiLwPZJ32cjafAebfDDpVrqeQjgpFHZEdau/8r4="
|
||||
},
|
||||
{
|
||||
"url": "turn:global.turn.twilio.com:443?transport=tcp",
|
||||
"username": "ce8042842b62c21bd20b176f80d6067fd3db81b1e9766312418ef5421d9ca2a2",
|
||||
"urls": "turn:global.turn.twilio.com:443?transport=tcp",
|
||||
"credential": "UzGOsiLwPZJ32cjafAebfDDpVrqeQjgpFHZEdau/8r4="
|
||||
}
|
||||
],
|
||||
// 'sdpSemantics': 'unified-plan'
|
||||
};
|
||||
Map<String, dynamic> google_ice_config = {
|
||||
'iceServers': [
|
||||
{
|
||||
'urls': [
|
||||
'stun:stun.l.google.com:19302',
|
||||
'stun:stun1.l.google.com:19302',
|
||||
'stun:stun2.l.google.com:19302',
|
||||
'stun:stun3.l.google.com:19302'
|
||||
]
|
||||
},
|
||||
],
|
||||
// 'sdpSemantics': 'unified-plan'
|
||||
};
|
||||
Map<String, dynamic> aws_ice_config = {
|
||||
'iceServers': [
|
||||
{'url': "stun:ec2-15-185-116-59.me-south-1.compute.amazonaws.com:3478"},
|
||||
{'url': "turn:ec2-15-185-116-59.me-south-1.compute.amazonaws.com:3479", 'credential': "admin", 'username': "admin"}
|
||||
],
|
||||
// 'sdpSemantics': 'unified-plan'
|
||||
};
|
||||
|
||||
class Signaling {
|
||||
dispose() {
|
||||
if (peerConnection != null) {
|
||||
peerConnection.dispose();
|
||||
peerConnection.getLocalStreams().forEach((e) => e.dispose());
|
||||
peerConnection.getRemoteStreams().forEach((e) => e.dispose());
|
||||
}
|
||||
signalR.closeConnection();
|
||||
}
|
||||
|
||||
init() async{
|
||||
// Create Peer Connection
|
||||
peerConnection = await createPeerConnection(google_ice_config, constraints);
|
||||
registerPeerConnectionListeners();
|
||||
}
|
||||
|
||||
initializeSignalR(String userName) async {
|
||||
if (signalR != null) await signalR.closeConnection();
|
||||
// https://vcallapi.hmg.com/webRTCHub?source=web&username=zohaib
|
||||
// signalR = SignalRUtil(hubName: "https://vcallapi.hmg.com/webRTCHub?source=mobile&username=$userName");
|
||||
signalR = SignalRUtil(hubName: "http://35.193.237.29/webRTCHub?source=mobile&username=$userName");
|
||||
final connected = await signalR.openConnection();
|
||||
if (!connected) throw 'Failed to connect SignalR';
|
||||
}
|
||||
|
||||
Map<String, dynamic> configuration = {
|
||||
// 'iceServers': [
|
||||
// {
|
||||
// 'urls': ['stun:stun1.l.google.com:19302', 'stun:stun2.l.google.com:19302']
|
||||
// }
|
||||
// ]
|
||||
|
||||
'iceServers': [
|
||||
// {'url': "stun:ec2-15-185-116-59.me-south-1.compute.amazonaws.com:3478"},
|
||||
// {'url': "turn:ec2-15-185-116-59.me-south-1.compute.amazonaws.com:3479", 'credential': "admin", 'username': "admin"}
|
||||
// {'url': "stun:15.185.116.59:3478"},
|
||||
// {
|
||||
// "url":"turn:15.185.116.59:3479",
|
||||
// "username": "admin",
|
||||
// "credential":"admin"
|
||||
// }
|
||||
{
|
||||
"url": "stun:global.stun.twilio.com:3478?transport=udp",
|
||||
"urls": "stun:global.stun.twilio.com:3478?transport=udp"
|
||||
},
|
||||
{
|
||||
"url": "turn:global.turn.twilio.com:3478?transport=udp",
|
||||
"username": "f18fc347ba4aeeaa1b00f5199b1e900834b464962d434a4a89b4cdba02510047",
|
||||
"urls": "turn:global.turn.twilio.com:3478?transport=udp",
|
||||
"credential": "WX16BB+9nKm0f+Whf5EwpM8S/Yv+T2tlvQWLfdV7oqo="
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
SignalRUtil signalR;
|
||||
|
||||
RTCPeerConnection peerConnection;
|
||||
MediaStream localStream;
|
||||
MediaStream remoteStream;
|
||||
RTCDataChannel dataChannel;
|
||||
|
||||
// Future<bool> call(String patientId, String mobile, {@required RTCVideoRenderer localVideo, @required RTCVideoRenderer remoteVideo}) async {
|
||||
// await initializeSignalR(patientId);
|
||||
//
|
||||
// // final isCallPlaced = await FCM.sendCallNotifcationTo(DOCTOR_TOKEN, patientId, mobile);
|
||||
// if(!isCallPlaced)
|
||||
// throw 'Failed to notify target for call';
|
||||
//
|
||||
// return isCallPlaced;
|
||||
// }
|
||||
|
||||
Future<bool> acceptCall(String caller, String receiver, {@required MediaStream localMediaStream, @required Function(MediaStream) onRemoteMediaStream, @required Function(RTCTrackEvent) onRemoteTrack}) async {
|
||||
await initializeSignalR(receiver);
|
||||
signalR.setContributors(caller: caller, receiver: receiver);
|
||||
await signalR.acceptCall(receiver, caller).catchError((e) => throw 'Failed to inform signalR that i accepted a call');
|
||||
|
||||
peerConnection.addStream(localMediaStream);
|
||||
|
||||
// peerConnection?.onTrack = (track){
|
||||
// onRemoteTrack(track);
|
||||
// };
|
||||
peerConnection?.onAddStream = (MediaStream stream) {
|
||||
remoteStream = stream;
|
||||
onRemoteMediaStream?.call(stream);
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Future<bool> declineCall(String caller, String receiver) async {
|
||||
await initializeSignalR(receiver);
|
||||
signalR.setContributors(caller: caller, receiver: receiver);
|
||||
await signalR.declineCall(receiver, caller).catchError((e) => throw 'Failed to inform signalR that i accepted a call');
|
||||
|
||||
// peerConnection.addStream(localMediaStream);
|
||||
//
|
||||
// peerConnection?.onAddStream = (MediaStream stream) {
|
||||
// remoteStream = stream;
|
||||
// onRemoteMediaStream?.call(stream);
|
||||
// };
|
||||
return true;
|
||||
}
|
||||
|
||||
Future hangupCall(String caller, String receiver) async {
|
||||
await signalR.hangupCall(caller, receiver);
|
||||
dispose();
|
||||
}
|
||||
|
||||
answerOffer(String sdp) async {
|
||||
final offer = jsonDecode(sdp);
|
||||
final caller = offer['caller'];
|
||||
final receiver = offer['target'];
|
||||
final offerSdp = offer['sdp'];
|
||||
peerConnection.setRemoteDescription(rtcSessionDescriptionFrom(offerSdp)).then((value) {
|
||||
return peerConnection.createAnswer().catchError((e){
|
||||
print(e);
|
||||
});
|
||||
}).then((anwser) {
|
||||
return peerConnection.setLocalDescription(anwser).catchError((e){
|
||||
print(e);
|
||||
});
|
||||
}).then((value) {
|
||||
return peerConnection.getLocalDescription().catchError((e){
|
||||
print(e);
|
||||
});
|
||||
}).then((answer) {
|
||||
return signalR.answerOffer(answer, caller, receiver).catchError((e){
|
||||
print(e);
|
||||
});
|
||||
}).catchError((e) {
|
||||
print(e);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> hangUp(RTCVideoRenderer localVideo) async {}
|
||||
|
||||
Future<String> createSdpAnswer(String toOfferSdp) async {
|
||||
final offerSdp = rtcSessionDescriptionFrom(jsonDecode(toOfferSdp));
|
||||
peerConnection.setRemoteDescription(offerSdp).catchError((e){
|
||||
print(e);
|
||||
});
|
||||
|
||||
final answer = await peerConnection.createAnswer().catchError((e){
|
||||
print(e);
|
||||
});
|
||||
var answerSdp = json.encode(answer); // Send SDP via Push or any channel
|
||||
return answerSdp;
|
||||
}
|
||||
|
||||
Future<String> createSdpOffer() async {
|
||||
final offer = await peerConnection.createOffer();
|
||||
await peerConnection.setLocalDescription(offer).catchError((e){
|
||||
print(e);
|
||||
});
|
||||
final map = offer.toMap();
|
||||
var offerSdp = json.encode(map); // Send SDP via Push or any channel
|
||||
return offerSdp;
|
||||
}
|
||||
|
||||
addCandidate(String candidateJson) {
|
||||
peerConnection.addCandidate(rtcIceCandidateFrom(candidateJson)).catchError((e){
|
||||
print(e);
|
||||
});
|
||||
}
|
||||
|
||||
void registerPeerConnectionListeners() {
|
||||
peerConnection.onRenegotiationNeeded = (){
|
||||
print('Renegotiation Needed...');
|
||||
};
|
||||
|
||||
peerConnection.onIceCandidate = (RTCIceCandidate candidate) {
|
||||
// print(json.encode(candidate.toMap()));
|
||||
signalR.addIceCandidate(json.encode(candidate.toMap())).catchError((e){
|
||||
print(e);
|
||||
});
|
||||
};
|
||||
|
||||
peerConnection?.onIceGatheringState = (RTCIceGatheringState state) {
|
||||
print('ICE gathering state changed: $state');
|
||||
};
|
||||
|
||||
peerConnection?.onConnectionState = (RTCPeerConnectionState state) {
|
||||
print('Connection state change: $state');
|
||||
};
|
||||
|
||||
peerConnection?.onSignalingState = (RTCSignalingState state) {
|
||||
print('Signaling state change: $state');
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
rtcSessionDescriptionFrom(Map sdp) {
|
||||
return RTCSessionDescription(
|
||||
sdp['sdp'],
|
||||
sdp['type'],
|
||||
);
|
||||
}
|
||||
|
||||
rtcIceCandidateFrom(String json) {
|
||||
final map = jsonDecode(json)['candidate'];
|
||||
return RTCIceCandidate(map['candidate'], map['sdpMid'], map['sdpMLineIndex']);
|
||||
}
|
||||
// import 'dart:convert';
|
||||
//
|
||||
// import 'package:diplomaticquarterapp/uitl/SignalRUtil.dart';
|
||||
// import 'package:flutter/cupertino.dart';
|
||||
// import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
//
|
||||
// typedef void StreamStateCallback(MediaStream stream);
|
||||
// typedef void RTCIceGatheringStateCallback(RTCIceGatheringState state);
|
||||
// typedef void RTCPeerConnectionStateCallback(RTCPeerConnectionState state);
|
||||
// typedef void RTCSignalingStateCallback(RTCSignalingState state);
|
||||
//
|
||||
// final Map<String, dynamic> constraints = {
|
||||
// 'mandatory': {},
|
||||
// 'optional': [
|
||||
// {'DtlsSrtpKeyAgreement': true},
|
||||
// ]
|
||||
// };
|
||||
//
|
||||
// Map<String, dynamic> snapsis_ice_config = {
|
||||
// 'iceServers': [
|
||||
// { "urls": 'stun:15.185.116.59:3478' },
|
||||
// { "urls": "turn:15.185.116.59:3479", "username": "admin", "credential": "admin" },
|
||||
// ],
|
||||
// // 'sdpSemantics': 'unified-plan'
|
||||
// };
|
||||
// Map<String, dynamic> twilio_ice_config = {
|
||||
// "ice_servers": [
|
||||
// {
|
||||
// "url": "stun:global.stun.twilio.com:3478?transport=udp",
|
||||
// "urls": "stun:global.stun.twilio.com:3478?transport=udp"
|
||||
// },
|
||||
// {
|
||||
// "url": "turn:global.turn.twilio.com:3478?transport=udp",
|
||||
// "username": "ce8042842b62c21bd20b176f80d6067fd3db81b1e9766312418ef5421d9ca2a2",
|
||||
// "urls": "turn:global.turn.twilio.com:3478?transport=udp",
|
||||
// "credential": "UzGOsiLwPZJ32cjafAebfDDpVrqeQjgpFHZEdau/8r4="
|
||||
// },
|
||||
// {
|
||||
// "url": "turn:global.turn.twilio.com:3478?transport=tcp",
|
||||
// "username": "ce8042842b62c21bd20b176f80d6067fd3db81b1e9766312418ef5421d9ca2a2",
|
||||
// "urls": "turn:global.turn.twilio.com:3478?transport=tcp",
|
||||
// "credential": "UzGOsiLwPZJ32cjafAebfDDpVrqeQjgpFHZEdau/8r4="
|
||||
// },
|
||||
// {
|
||||
// "url": "turn:global.turn.twilio.com:443?transport=tcp",
|
||||
// "username": "ce8042842b62c21bd20b176f80d6067fd3db81b1e9766312418ef5421d9ca2a2",
|
||||
// "urls": "turn:global.turn.twilio.com:443?transport=tcp",
|
||||
// "credential": "UzGOsiLwPZJ32cjafAebfDDpVrqeQjgpFHZEdau/8r4="
|
||||
// }
|
||||
// ],
|
||||
// // 'sdpSemantics': 'unified-plan'
|
||||
// };
|
||||
// Map<String, dynamic> google_ice_config = {
|
||||
// 'iceServers': [
|
||||
// {
|
||||
// 'urls': [
|
||||
// 'stun:stun.l.google.com:19302',
|
||||
// 'stun:stun1.l.google.com:19302',
|
||||
// 'stun:stun2.l.google.com:19302',
|
||||
// 'stun:stun3.l.google.com:19302'
|
||||
// ]
|
||||
// },
|
||||
// ],
|
||||
// // 'sdpSemantics': 'unified-plan'
|
||||
// };
|
||||
// Map<String, dynamic> aws_ice_config = {
|
||||
// 'iceServers': [
|
||||
// {'url': "stun:ec2-15-185-116-59.me-south-1.compute.amazonaws.com:3478"},
|
||||
// {'url': "turn:ec2-15-185-116-59.me-south-1.compute.amazonaws.com:3479", 'credential': "admin", 'username': "admin"}
|
||||
// ],
|
||||
// // 'sdpSemantics': 'unified-plan'
|
||||
// };
|
||||
//
|
||||
// class Signaling {
|
||||
// dispose() {
|
||||
// if (peerConnection != null) {
|
||||
// peerConnection.dispose();
|
||||
// peerConnection.getLocalStreams().forEach((e) => e.dispose());
|
||||
// peerConnection.getRemoteStreams().forEach((e) => e.dispose());
|
||||
// }
|
||||
// signalR.closeConnection();
|
||||
// }
|
||||
//
|
||||
// init() async{
|
||||
// // Create Peer Connection
|
||||
// peerConnection = await createPeerConnection(google_ice_config, constraints);
|
||||
// registerPeerConnectionListeners();
|
||||
// }
|
||||
//
|
||||
// initializeSignalR(String userName) async {
|
||||
// if (signalR != null) await signalR.closeConnection();
|
||||
// // https://vcallapi.hmg.com/webRTCHub?source=web&username=zohaib
|
||||
// // signalR = SignalRUtil(hubName: "https://vcallapi.hmg.com/webRTCHub?source=mobile&username=$userName");
|
||||
// signalR = SignalRUtil(hubName: "http://35.193.237.29/webRTCHub?source=mobile&username=$userName");
|
||||
// final connected = await signalR.openConnection();
|
||||
// if (!connected) throw 'Failed to connect SignalR';
|
||||
// }
|
||||
//
|
||||
// Map<String, dynamic> configuration = {
|
||||
// // 'iceServers': [
|
||||
// // {
|
||||
// // 'urls': ['stun:stun1.l.google.com:19302', 'stun:stun2.l.google.com:19302']
|
||||
// // }
|
||||
// // ]
|
||||
//
|
||||
// 'iceServers': [
|
||||
// // {'url': "stun:ec2-15-185-116-59.me-south-1.compute.amazonaws.com:3478"},
|
||||
// // {'url': "turn:ec2-15-185-116-59.me-south-1.compute.amazonaws.com:3479", 'credential': "admin", 'username': "admin"}
|
||||
// // {'url': "stun:15.185.116.59:3478"},
|
||||
// // {
|
||||
// // "url":"turn:15.185.116.59:3479",
|
||||
// // "username": "admin",
|
||||
// // "credential":"admin"
|
||||
// // }
|
||||
// {
|
||||
// "url": "stun:global.stun.twilio.com:3478?transport=udp",
|
||||
// "urls": "stun:global.stun.twilio.com:3478?transport=udp"
|
||||
// },
|
||||
// {
|
||||
// "url": "turn:global.turn.twilio.com:3478?transport=udp",
|
||||
// "username": "f18fc347ba4aeeaa1b00f5199b1e900834b464962d434a4a89b4cdba02510047",
|
||||
// "urls": "turn:global.turn.twilio.com:3478?transport=udp",
|
||||
// "credential": "WX16BB+9nKm0f+Whf5EwpM8S/Yv+T2tlvQWLfdV7oqo="
|
||||
// }
|
||||
// ]
|
||||
// };
|
||||
//
|
||||
// SignalRUtil signalR;
|
||||
//
|
||||
// RTCPeerConnection peerConnection;
|
||||
// MediaStream localStream;
|
||||
// MediaStream remoteStream;
|
||||
// RTCDataChannel dataChannel;
|
||||
//
|
||||
// // Future<bool> call(String patientId, String mobile, {@required RTCVideoRenderer localVideo, @required RTCVideoRenderer remoteVideo}) async {
|
||||
// // await initializeSignalR(patientId);
|
||||
// //
|
||||
// // // final isCallPlaced = await FCM.sendCallNotifcationTo(DOCTOR_TOKEN, patientId, mobile);
|
||||
// // if(!isCallPlaced)
|
||||
// // throw 'Failed to notify target for call';
|
||||
// //
|
||||
// // return isCallPlaced;
|
||||
// // }
|
||||
//
|
||||
// Future<bool> acceptCall(String caller, String receiver, {@required MediaStream localMediaStream, @required Function(MediaStream) onRemoteMediaStream, @required Function(RTCTrackEvent) onRemoteTrack}) async {
|
||||
// await initializeSignalR(receiver);
|
||||
// signalR.setContributors(caller: caller, receiver: receiver);
|
||||
// await signalR.acceptCall(receiver, caller).catchError((e) => throw 'Failed to inform signalR that i accepted a call');
|
||||
//
|
||||
// peerConnection.addStream(localMediaStream);
|
||||
//
|
||||
// // peerConnection?.onTrack = (track){
|
||||
// // onRemoteTrack(track);
|
||||
// // };
|
||||
// peerConnection?.onAddStream = (MediaStream stream) {
|
||||
// remoteStream = stream;
|
||||
// onRemoteMediaStream?.call(stream);
|
||||
// };
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// Future<bool> declineCall(String caller, String receiver) async {
|
||||
// await initializeSignalR(receiver);
|
||||
// signalR.setContributors(caller: caller, receiver: receiver);
|
||||
// await signalR.declineCall(receiver, caller).catchError((e) => throw 'Failed to inform signalR that i accepted a call');
|
||||
//
|
||||
// // peerConnection.addStream(localMediaStream);
|
||||
// //
|
||||
// // peerConnection?.onAddStream = (MediaStream stream) {
|
||||
// // remoteStream = stream;
|
||||
// // onRemoteMediaStream?.call(stream);
|
||||
// // };
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// Future hangupCall(String caller, String receiver) async {
|
||||
// await signalR.hangupCall(caller, receiver);
|
||||
// dispose();
|
||||
// }
|
||||
//
|
||||
// answerOffer(String sdp) async {
|
||||
// final offer = jsonDecode(sdp);
|
||||
// final caller = offer['caller'];
|
||||
// final receiver = offer['target'];
|
||||
// final offerSdp = offer['sdp'];
|
||||
// peerConnection.setRemoteDescription(rtcSessionDescriptionFrom(offerSdp)).then((value) {
|
||||
// return peerConnection.createAnswer().catchError((e){
|
||||
// print(e);
|
||||
// });
|
||||
// }).then((anwser) {
|
||||
// return peerConnection.setLocalDescription(anwser).catchError((e){
|
||||
// print(e);
|
||||
// });
|
||||
// }).then((value) {
|
||||
// return peerConnection.getLocalDescription().catchError((e){
|
||||
// print(e);
|
||||
// });
|
||||
// }).then((answer) {
|
||||
// return signalR.answerOffer(answer, caller, receiver).catchError((e){
|
||||
// print(e);
|
||||
// });
|
||||
// }).catchError((e) {
|
||||
// print(e);
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// Future<void> hangUp(RTCVideoRenderer localVideo) async {}
|
||||
//
|
||||
// Future<String> createSdpAnswer(String toOfferSdp) async {
|
||||
// final offerSdp = rtcSessionDescriptionFrom(jsonDecode(toOfferSdp));
|
||||
// peerConnection.setRemoteDescription(offerSdp).catchError((e){
|
||||
// print(e);
|
||||
// });
|
||||
//
|
||||
// final answer = await peerConnection.createAnswer().catchError((e){
|
||||
// print(e);
|
||||
// });
|
||||
// var answerSdp = json.encode(answer); // Send SDP via Push or any channel
|
||||
// return answerSdp;
|
||||
// }
|
||||
//
|
||||
// Future<String> createSdpOffer() async {
|
||||
// final offer = await peerConnection.createOffer();
|
||||
// await peerConnection.setLocalDescription(offer).catchError((e){
|
||||
// print(e);
|
||||
// });
|
||||
// final map = offer.toMap();
|
||||
// var offerSdp = json.encode(map); // Send SDP via Push or any channel
|
||||
// return offerSdp;
|
||||
// }
|
||||
//
|
||||
// addCandidate(String candidateJson) {
|
||||
// peerConnection.addCandidate(rtcIceCandidateFrom(candidateJson)).catchError((e){
|
||||
// print(e);
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// void registerPeerConnectionListeners() {
|
||||
// peerConnection.onRenegotiationNeeded = (){
|
||||
// print('Renegotiation Needed...');
|
||||
// };
|
||||
//
|
||||
// peerConnection.onIceCandidate = (RTCIceCandidate candidate) {
|
||||
// // print(json.encode(candidate.toMap()));
|
||||
// signalR.addIceCandidate(json.encode(candidate.toMap())).catchError((e){
|
||||
// print(e);
|
||||
// });
|
||||
// };
|
||||
//
|
||||
// peerConnection?.onIceGatheringState = (RTCIceGatheringState state) {
|
||||
// print('ICE gathering state changed: $state');
|
||||
// };
|
||||
//
|
||||
// peerConnection?.onConnectionState = (RTCPeerConnectionState state) {
|
||||
// print('Connection state change: $state');
|
||||
// };
|
||||
//
|
||||
// peerConnection?.onSignalingState = (RTCSignalingState state) {
|
||||
// print('Signaling state change: $state');
|
||||
// };
|
||||
//
|
||||
//
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// rtcSessionDescriptionFrom(Map sdp) {
|
||||
// return RTCSessionDescription(
|
||||
// sdp['sdp'],
|
||||
// sdp['type'],
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// rtcIceCandidateFrom(String json) {
|
||||
// final map = jsonDecode(json)['candidate'];
|
||||
// return RTCIceCandidate(map['candidate'], map['sdpMid'], map['sdpMLineIndex']);
|
||||
// }
|
||||
|
||||
@ -1,173 +1,173 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
import 'package:http/io_client.dart';
|
||||
import 'package:signalr_core/signalr_core.dart';
|
||||
|
||||
class SignalRUtil {
|
||||
String hubName;
|
||||
|
||||
String sourceUser;
|
||||
String destinationUser;
|
||||
setContributors({@required String caller, @required String receiver}){
|
||||
this.sourceUser = caller;
|
||||
this.destinationUser = receiver;
|
||||
}
|
||||
|
||||
Function(bool) onConnected;
|
||||
SignalRUtil({@required this.hubName});
|
||||
|
||||
|
||||
HubConnection connectionHub;
|
||||
|
||||
closeConnection() async{
|
||||
if(connectionHub != null) {
|
||||
connectionHub.off('OnIncomingCallAsync');
|
||||
connectionHub.off('OnCallDeclinedAsync');
|
||||
connectionHub.off('OnCallAcceptedAsync');
|
||||
connectionHub.off('nHangUpAsync');
|
||||
connectionHub.off('OnIceCandidateAsync');
|
||||
connectionHub.off('OnOfferAsync');
|
||||
await connectionHub.stop();
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> openConnection() async {
|
||||
connectionHub = HubConnectionBuilder()
|
||||
.withUrl(
|
||||
hubName,
|
||||
HttpConnectionOptions(
|
||||
logMessageContent: true,
|
||||
client: IOClient(HttpClient()..badCertificateCallback = (x, y, z) => true),
|
||||
logging: (level, message) => print(message),
|
||||
)).build();
|
||||
|
||||
await connectionHub.start();
|
||||
await Future.delayed(Duration(seconds: 1));
|
||||
|
||||
connectionHub.on('ReceiveMessage', (message) {
|
||||
handleIncomingMessage(message);
|
||||
});
|
||||
|
||||
return getConnectionState();
|
||||
}
|
||||
|
||||
void handleIncomingMessage(List<dynamic> message) {
|
||||
print(message.toString());
|
||||
}
|
||||
|
||||
void sendMessage(List<dynamic> args) async {
|
||||
await connectionHub.invoke('SendMessage', args: args); //['Bob', 'Says hi!']
|
||||
}
|
||||
|
||||
listen({Function(CallUser) onAcceptCall, Function(CallUser) onHangupCall, Function(String, CallUser) onDeclineCall, Function(String, CallUser) onOffer, Function(String) onCandidate}){
|
||||
|
||||
connectionHub.on('OnIncomingCallAsync', (arguments) {
|
||||
print('OnIncomingCallAsync: ${arguments.toString()}');
|
||||
});
|
||||
|
||||
connectionHub.on('OnCallDeclinedAsync', (arguments) {
|
||||
print('OnCallDeclinedAsync: ${arguments.toString()}');
|
||||
onDeclineCall(arguments.first, CallUser.from(arguments.last));
|
||||
});
|
||||
|
||||
connectionHub.on('OnCallAcceptedAsync', (arguments) {
|
||||
print('OnCallAcceptedAsync: ${arguments.toString()}');
|
||||
});
|
||||
|
||||
connectionHub.on('OnHangUpAsync', (arguments) {
|
||||
print('nHangUpAsync: ${arguments.toString()}');
|
||||
onHangupCall(CallUser.from(arguments.first));
|
||||
});
|
||||
|
||||
connectionHub.on('OnIceCandidateAsync', (arguments) {
|
||||
print('OnIceCandidateAsync: ${arguments.toString()}');
|
||||
onCandidate(arguments.first);
|
||||
});
|
||||
|
||||
connectionHub.on('OnOfferAsync', (arguments) {
|
||||
print('OnOfferAsync: ${arguments.toString()}');
|
||||
onOffer(arguments.first, CallUser.from(arguments.last));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// CallUserAsync(string currentUserId, string targerUserId)
|
||||
Future<dynamic> callUser(String from, to) async{
|
||||
return await connectionHub.invoke('CallUserAsync', args: [from, to]);
|
||||
}
|
||||
|
||||
// CallDeclinedAsync(string currentUserId, string targerUserId)
|
||||
Future<dynamic> declineCall(String from, to) async{
|
||||
return await connectionHub.invoke('CallDeclinedAsync', args: [from, to]);
|
||||
}
|
||||
|
||||
// AnswerCallAsync(string currentUserId, string targetUserId)
|
||||
Future<dynamic> answerCall(String from, to) async{
|
||||
return await connectionHub.invoke('AnswerCallAsync', args: [from, to]);
|
||||
}
|
||||
|
||||
// IceCandidateAsync(string targetUserId, string candidate)
|
||||
Future<dynamic> addIceCandidate(String candidate) async{
|
||||
final target = destinationUser;
|
||||
return await connectionHub.invoke('IceCandidateAsync', args: [target, candidate]);
|
||||
}
|
||||
|
||||
// OfferAsync(string targetUserId,string currentUserId, string targetOffer)
|
||||
Future<dynamic> offer(String from, to, offer) async{
|
||||
return await connectionHub.invoke('OfferAsync', args: [from, to, offer]);
|
||||
}
|
||||
|
||||
// AnswerOfferAsync(string targetUserId, string CallerOffer)
|
||||
Future<dynamic> answerOffer(RTCSessionDescription answerSdp, caller, receiver) async{
|
||||
final payload = {
|
||||
'target': receiver,
|
||||
'caller': caller,
|
||||
'sdp': answerSdp.toMap(),
|
||||
};
|
||||
return await connectionHub.invoke('AnswerOfferAsync', args: [caller, jsonEncode(payload)]);
|
||||
}
|
||||
|
||||
// HangUpAsync(string currentUserId, string targetUserId)
|
||||
Future<dynamic> hangupCall(String from, to) async{
|
||||
return await connectionHub.invoke('HangUpAsync', args: [from, to]);
|
||||
}
|
||||
|
||||
// CallAccepted(string currentUserId,string targetUserId)
|
||||
Future<dynamic> acceptCall(String from, to) async{
|
||||
// return await connectionHub.send(methodName: 'CallAccepted', args: [from, to]);
|
||||
return await connectionHub.invoke("CallAccepted", args: [ from, to]);
|
||||
}
|
||||
|
||||
|
||||
bool getConnectionState() {
|
||||
if (connectionHub.state == HubConnectionState.connected) return true;
|
||||
if (connectionHub.state == HubConnectionState.disconnected) return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class CallUser{
|
||||
String Id;
|
||||
String UserName;
|
||||
String Email;
|
||||
String Phone;
|
||||
String Title;
|
||||
dynamic UserStatus;
|
||||
String Image;
|
||||
int UnreadMessageCount = 0;
|
||||
|
||||
CallUser.from(Map map){
|
||||
Id = map['Id'];
|
||||
UserName = map['UserName'];
|
||||
Email = map['Email'];
|
||||
Phone = map['Phone'];
|
||||
Title = map['Title'];
|
||||
UserStatus = map['UserStatus'];
|
||||
Image = map['Image'];
|
||||
UnreadMessageCount = map['UnreadMessageCount'];
|
||||
}
|
||||
}
|
||||
// import 'dart:convert';
|
||||
// import 'dart:io';
|
||||
//
|
||||
// import 'package:flutter/cupertino.dart';
|
||||
// import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
// import 'package:http/io_client.dart';
|
||||
// import 'package:signalr_core/signalr_core.dart';
|
||||
//
|
||||
// class SignalRUtil {
|
||||
// String hubName;
|
||||
//
|
||||
// String sourceUser;
|
||||
// String destinationUser;
|
||||
// setContributors({@required String caller, @required String receiver}){
|
||||
// this.sourceUser = caller;
|
||||
// this.destinationUser = receiver;
|
||||
// }
|
||||
//
|
||||
// Function(bool) onConnected;
|
||||
// SignalRUtil({@required this.hubName});
|
||||
//
|
||||
//
|
||||
// HubConnection connectionHub;
|
||||
//
|
||||
// closeConnection() async{
|
||||
// if(connectionHub != null) {
|
||||
// connectionHub.off('OnIncomingCallAsync');
|
||||
// connectionHub.off('OnCallDeclinedAsync');
|
||||
// connectionHub.off('OnCallAcceptedAsync');
|
||||
// connectionHub.off('nHangUpAsync');
|
||||
// connectionHub.off('OnIceCandidateAsync');
|
||||
// connectionHub.off('OnOfferAsync');
|
||||
// await connectionHub.stop();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Future<bool> openConnection() async {
|
||||
// connectionHub = HubConnectionBuilder()
|
||||
// .withUrl(
|
||||
// hubName,
|
||||
// HttpConnectionOptions(
|
||||
// logMessageContent: true,
|
||||
// client: IOClient(HttpClient()..badCertificateCallback = (x, y, z) => true),
|
||||
// logging: (level, message) => print(message),
|
||||
// )).build();
|
||||
//
|
||||
// await connectionHub.start();
|
||||
// await Future.delayed(Duration(seconds: 1));
|
||||
//
|
||||
// connectionHub.on('ReceiveMessage', (message) {
|
||||
// handleIncomingMessage(message);
|
||||
// });
|
||||
//
|
||||
// return getConnectionState();
|
||||
// }
|
||||
//
|
||||
// void handleIncomingMessage(List<dynamic> message) {
|
||||
// print(message.toString());
|
||||
// }
|
||||
//
|
||||
// void sendMessage(List<dynamic> args) async {
|
||||
// await connectionHub.invoke('SendMessage', args: args); //['Bob', 'Says hi!']
|
||||
// }
|
||||
//
|
||||
// listen({Function(CallUser) onAcceptCall, Function(CallUser) onHangupCall, Function(String, CallUser) onDeclineCall, Function(String, CallUser) onOffer, Function(String) onCandidate}){
|
||||
//
|
||||
// connectionHub.on('OnIncomingCallAsync', (arguments) {
|
||||
// print('OnIncomingCallAsync: ${arguments.toString()}');
|
||||
// });
|
||||
//
|
||||
// connectionHub.on('OnCallDeclinedAsync', (arguments) {
|
||||
// print('OnCallDeclinedAsync: ${arguments.toString()}');
|
||||
// onDeclineCall(arguments.first, CallUser.from(arguments.last));
|
||||
// });
|
||||
//
|
||||
// connectionHub.on('OnCallAcceptedAsync', (arguments) {
|
||||
// print('OnCallAcceptedAsync: ${arguments.toString()}');
|
||||
// });
|
||||
//
|
||||
// connectionHub.on('OnHangUpAsync', (arguments) {
|
||||
// print('nHangUpAsync: ${arguments.toString()}');
|
||||
// onHangupCall(CallUser.from(arguments.first));
|
||||
// });
|
||||
//
|
||||
// connectionHub.on('OnIceCandidateAsync', (arguments) {
|
||||
// print('OnIceCandidateAsync: ${arguments.toString()}');
|
||||
// onCandidate(arguments.first);
|
||||
// });
|
||||
//
|
||||
// connectionHub.on('OnOfferAsync', (arguments) {
|
||||
// print('OnOfferAsync: ${arguments.toString()}');
|
||||
// onOffer(arguments.first, CallUser.from(arguments.last));
|
||||
// });
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // CallUserAsync(string currentUserId, string targerUserId)
|
||||
// Future<dynamic> callUser(String from, to) async{
|
||||
// return await connectionHub.invoke('CallUserAsync', args: [from, to]);
|
||||
// }
|
||||
//
|
||||
// // CallDeclinedAsync(string currentUserId, string targerUserId)
|
||||
// Future<dynamic> declineCall(String from, to) async{
|
||||
// return await connectionHub.invoke('CallDeclinedAsync', args: [from, to]);
|
||||
// }
|
||||
//
|
||||
// // AnswerCallAsync(string currentUserId, string targetUserId)
|
||||
// Future<dynamic> answerCall(String from, to) async{
|
||||
// return await connectionHub.invoke('AnswerCallAsync', args: [from, to]);
|
||||
// }
|
||||
//
|
||||
// // IceCandidateAsync(string targetUserId, string candidate)
|
||||
// Future<dynamic> addIceCandidate(String candidate) async{
|
||||
// final target = destinationUser;
|
||||
// return await connectionHub.invoke('IceCandidateAsync', args: [target, candidate]);
|
||||
// }
|
||||
//
|
||||
// // OfferAsync(string targetUserId,string currentUserId, string targetOffer)
|
||||
// Future<dynamic> offer(String from, to, offer) async{
|
||||
// return await connectionHub.invoke('OfferAsync', args: [from, to, offer]);
|
||||
// }
|
||||
//
|
||||
// // AnswerOfferAsync(string targetUserId, string CallerOffer)
|
||||
// Future<dynamic> answerOffer(RTCSessionDescription answerSdp, caller, receiver) async{
|
||||
// final payload = {
|
||||
// 'target': receiver,
|
||||
// 'caller': caller,
|
||||
// 'sdp': answerSdp.toMap(),
|
||||
// };
|
||||
// return await connectionHub.invoke('AnswerOfferAsync', args: [caller, jsonEncode(payload)]);
|
||||
// }
|
||||
//
|
||||
// // HangUpAsync(string currentUserId, string targetUserId)
|
||||
// Future<dynamic> hangupCall(String from, to) async{
|
||||
// return await connectionHub.invoke('HangUpAsync', args: [from, to]);
|
||||
// }
|
||||
//
|
||||
// // CallAccepted(string currentUserId,string targetUserId)
|
||||
// Future<dynamic> acceptCall(String from, to) async{
|
||||
// // return await connectionHub.send(methodName: 'CallAccepted', args: [from, to]);
|
||||
// return await connectionHub.invoke("CallAccepted", args: [ from, to]);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// bool getConnectionState() {
|
||||
// if (connectionHub.state == HubConnectionState.connected) return true;
|
||||
// if (connectionHub.state == HubConnectionState.disconnected) return false;
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// class CallUser{
|
||||
// String Id;
|
||||
// String UserName;
|
||||
// String Email;
|
||||
// String Phone;
|
||||
// String Title;
|
||||
// dynamic UserStatus;
|
||||
// String Image;
|
||||
// int UnreadMessageCount = 0;
|
||||
//
|
||||
// CallUser.from(Map map){
|
||||
// Id = map['Id'];
|
||||
// UserName = map['UserName'];
|
||||
// Email = map['Email'];
|
||||
// Phone = map['Phone'];
|
||||
// Title = map['Title'];
|
||||
// UserStatus = map['UserStatus'];
|
||||
// Image = map['Image'];
|
||||
// UnreadMessageCount = map['UnreadMessageCount'];
|
||||
// }
|
||||
// }
|
||||
Loading…
Reference in New Issue