Before using Stringee Video Conference API for the first time, you must have a Stringee account If you do not have a Stringee account, sign up for free here: https://developer.stringee.com/account/register
Create a Project on Stringee Dashboard
pubspec.yaml
file
dependencies:
stringee_flutter_plugin:
git:
url: https://github.com/stringeecom/stringee_flutter_plugin.git
$ flutter pub get
android/app/src/main/AndroidManifest.xml
// for internet access
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
// for audio access
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
// for camera access
<uses-permission android:name="android.permission.CAMERA" />
// for bluetooth access
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
proguard-rules.pro
in your app/
dir and insert inside:
#Flutter Wrapper
-dontwarn org.webrtc.**
-keep class org.webrtc.** { *; }
-keep class com.stringee.** { *; }
/app/buidl.gradle
:
android {
...
buildTypes {
...
release {
...
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
From the command line run following command:
pod install --repo-update
After run cocoapods command, open project file .xcworkspace
In the "Build Settings" tab -> "Other linker flags" add "$(inherited)" flag
In the "Build Settings" tab -> "Enable bitcode" select "NO"
Right-click the information property list file (Info.plist) and select Open As -> Source Code. Then insert the following XML snippet into the body of your file just before the final element:
<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) uses Camera</string>
<key>NSMicrophoneUsageDescription</key>
<string>$(PRODUCT_NAME) uses Microphone</string>
In the "Build Settings" tab -> "Allow Non-modular includes in Framework Modules" select "YES"
In order to connect to Stringee Server, 3-parties authentication is required as described here: Client authentication
For testing purpose, go to Dashboard -> Tools -> Generate Access token and generates an access_token. In production, the access_token should be generated by your server, here is a sample code generates access token here: https://github.com/stringeecom/server-samples/tree/master/access_token
import 'package:stringee_flutter_plugin/stringee_flutter_plugin.dart';
...
StringeeClient _client = StringeeClient();
Register the client's events in your State
class _MyHomePageState extends State<MyHomePage> {
...
@override
Future<void> initState() {
super.initState();
...
/// Listen for the StringeeClient event
_client.eventStreamController.stream.listen((event) {
Map<dynamic, dynamic> map = event;
switch (map['eventType']) {
case StringeeClientEvents.didConnect:
handleDidConnectEvent();
break;
case StringeeClientEvents.didDisconnect:
handleDiddisconnectEvent();
break;
case StringeeClientEvents.didFailWithError:
int code = map['body']['code'];
String msg = map['body']['message'];
handleDidFailWithErrorEvent(code,msg);
break;
case StringeeClientEvents.requestAccessToken:
handleRequestAccessTokenEvent();
break;
case StringeeClientEvents.didReceiveCustomMessage:
handleDidReceiveCustomMessageEvent(map['body']);
break;
default:
break;
}
});
...
}
...
/// Invoked when the StringeeClient is connected
void handleDidConnectEvent() {}
/// Invoked when the StringeeClient is disconnected
void handleDiddisconnectEvent() {}
/// Invoked when StringeeClient connect false
void handleDidFailWithErrorEvent(int code, String message) {}
/// Invoked when your token is expired
void handleRequestAccessTokenEvent() {}
/// Invoked when get Custom message
void handleDidReceiveCustomMessageEvent(Map<dynamic, dynamic> map) {}
...
}
@override
Future<void> initState() {
super.initState();
...
String token = 'PUT YOUR TOKEN HERE'
_client.connect(token);
...
}
After the client connects to Stirngee server, follows these steps to connect to a room:
import 'package:stringee_flutter_plugin/stringee_flutter_plugin.dart';
...
late StringeeVideo _video;
...
_video = StringeeVideo(client);
When creating StringeeVideo, you must pass StringeeClient which you used to connect in step 4.
In order to create room, you will need to use rest api, described here: https://developer.stringee.com/docs/rest-api-reference/room-management.
In order to join room, you will need token to the room credential : room_token. In production application, the room_token should be generated by your server sample code generates room token here: https://developer.stringee.com/docs/room-token
```
late StringeeRoom? _room;
...
_video.joinRoom('YOUR_ROOM_TOKEN').then((value) {
if (value['status']) {
_room = value['body']['room'];
List<StringeeVideoTrackInfo> trackInfos = value['body']['videoTrackInfos'];
List<StringeeRoomUser> users = value['body']['users'];
}
});
```
In which:
Register the room's events
/// Listen for the StringeeRoom event
_room!.eventStreamController.stream.listen((event) {
Map<dynamic, dynamic> map = event;
switch (map['eventType']) {
case StringeeRoomEvents.didJoinRoom:
handleJoinRoomEvent(map['body']);
break;
case StringeeRoomEvents.didLeaveRoom:
handleLeaveRoomEvent(map['body']);
break;
case StringeeRoomEvents.didAddVideoTrack:
handleAddVideoTrackEvent(map['body']);
break;
case StringeeRoomEvents.didRemoveVideoTrack:
handleRemoveVideoTrackEvent(map['body']);
break;
case StringeeRoomEvents.didReceiveRoomMessage:
handleReceiveRoomMessageEvent(map['body']);
break;
case StringeeRoomEvents.trackReadyToPlay:
handleTrackReadyToPlayEvent(map['body']);
break;
default:
break;
}
}
...
/// Invoked when the another user join room
void handleJoinRoomEvent(StringeeRoomUser joinUser) {}
/// Invoked when the another user leave room
void handleLeaveRoomEvent(StringeeRoomUser leaveUser) {}
/// Invoked when the add track to room
void handleAddVideoTrackEvent(StringeeVideoTrack addTrack) {}
/// Invoked when the remove track from room
void handleRemoveVideoTrackEvent(StringeeVideoTrack removeTrack) {}
/// Invoked when receive message in room
void handleReceiveRoomMessageEvent(Map<dynamic, dynamic> bodyMap) {}
/// Invoked when track is ready to display video
void handleTrackReadyToPlayEvent(StringeeVideoTrack track) {}
/// Create video track options
StringeeVideoTrackOptions options = StringeeVideoTrackOptions(
audio: true,
video: true,
screen: false,
);
/// Create local video track
_video.createLocalVideoTrack(options).then((value) {
if (value['status']) {
/// After create Track success, you can publish track to room
_room!.publish(value['body']).then((value) {
if (value['status']) {
// Success
}
});
}
});
After receiving another video track information, you need to subscribe the track to display the video
StringeeVideoTrackOptions options = StringeeVideoTrackOptions(
audio: track.audioEnable,
video: track.videoEnable,
screen: track.isScreenCapture,
);
_room!.subscribe(trackInfo, options).then((value) {
if (value['status']) {
// Success
}
});
fter subscribing another video track successfully or publishing your track successfully, you can display the video
StringeeVideoView videoView = track.attach(
isOverlay: true,
height: 200.0,
width: 150.0,
scalingType: ScalingType.fit,
);
...
return new Scaffold(
backgroundColor: Colors.black,
body: new Stack(
children: <Widget>[
...
videoView,
],
),
);
If you don't want to stop showing your track in the room, you can remove your track from the room by unpublishing it:
_room!.unPublish(_localTrack).then((result) {
if (result['status']) {
// Success
}
});
If you don't want to receive another track's audio or video in the room, you can unsubscribe this track:
_room!.unsubscribe(removeTrackInfo).then((value) {
if (value['status']) {
// Success
}
});
In order to leave room, you can call the following method:
_room!.leave(allClient: false).then((result) {
if (result['status']) {
// Success
}
});
Mute the local sound:
bool mute = true; // true: mute, false: unmute
your_track.mute(mute).then((result) {
if (result['status']) {
///success
}
});
Switch the local camera:
your_track.switchCamera().then((result) {
if (result['status']) {
///success
}
});
Turn on/off video:
bool enableVideo = true; // true: turn on, false: turn off
your_track.enableVideo(enableVideo).then((result) {
if (result['status']) {
///success
}
});
After leaving the room, you need to release all resources in the StringeeRoom. Call this function to release all resources:
_room!.destroy();
You can view a completed version of this sample app on GitHub: https://github.com/stringeecom/stringee_flutter_plugin/tree/master/example