meet_hour 5.0.17 meet_hour: ^5.0.17 copied to clipboard
Meet Hour Flutter Plugin - Meet Hour is 100% free video conference solution with End to End Encrypted and many other features such as lobby mode, Donor box & Click&Pledge Connect for fundraising, Vide [...]
Meet Hour Flutter SDK (https://meethour.io) #
Meet Hour Plugin for Flutter. Supports Android and iOS platforms.
"Meet Hour is 100% free video conference solution with End to End Encrypted and many other features such as lobby mode, Donor box & Click&Pledge Connect for fundraising, Video call recording, Youtube Live Stream etc."
Example Project is here - https://github.com/v-empower/MeetHour-Web-MobileSDKs/tree/master/Mobile/Flutter/MeetHourSDKTest
Pub dev - https://pub.dev/packages/meet_hour
meet_hour: '>=5.0.17'
MeetHour SDK Implementation - Steps #
- SDK Examples Link - https://github.com/v-empower/MeetHour-Web-MobileSDKs
- API Documentation Link - https://docs.v-empower.com/docs/MeetHour-API/
Steps to Use Meet Hour React Flutter SDK Example #
- Go to meethour.io and signup for Developer or Higher plan. Currently we offer 28 days free trial.
- Go to the dashboard and then click on developers menu.
- Copy your Client ID, Client Secret and Api Key. After copying, paste each copied text to the respective constant in the source code lib/constants/index.dart
- On Home page Click on Get Access Token
- Then Try Schedule a Meeting & Join Meeting.
Table of Contents #
- API End Points Supported
- Configuration
- Join A Meeting
- Listening to Meeting Events
- Closing a Meeting Programmatically
API End Points Supported #
-
To Get Access Token Endpoint : => https://docs.v-empower.com/docs/MeetHour-API/a44a7d7669f91-user-login-get-access-token
LoginType LoginObject = LoginType( client_id: '', client_secret: '', grant_type: 'password', password: '', username: '' ); Map<String, dynamic> response - await ApiServices.login(LoginObject);
=> You have to pass respective values in the argument section. Hence, to get desired response.
-
To schedule a meeting: => https://docs.v-empower.com/docs/MeetHour-API/2de4b757a6312-meeting-schedule-meeting
ScheduleMeetingType ScheduleObject = ScheduleMeetingType( meetingName : 'Test', agenda: '', passcode: '', meetingDate: '', meetingTime: '', meetingMeridiem: '', durationhr: '', durationmin: '', timezone: '', isrecurring: '', recurringtype: '', repeat_interval: '', endBy: '', enddatetime: '', instructions: '', is_show_portal: '', enablepreregistration: '', meetingtopic: '', meetingagenda: '', options: '', attend: '', groups: '', hostusers: '' ); Map<String, dynamic> response = await ApiServices.scheduleMeeting(token, ScheduleObject);
-
To Generate JWT Token Endpoint => https://docs.v-empower.com/docs/MeetHour-API/b7e3d0ab3906f-generate-jwt
GenerateJwtType JWTObject = GenerateJwtType( config: '', contactid, meetingid, uiconfig Map<String, dynamic> response = await ApiServices.generateJwt(token, JWTObject); );
-
To fetch User Details: => https://docs.v-empower.com/docs/MeetHour-API/ff9d0e37d9191-user-details
Map<String, dynamic> response = await ApiServices.userDetails(token);
-
To fetch access Token using Refresh Token: => https://docs.v-empower.com/docs/MeetHour-API/d851be1af9804-get-access-token-using-refresh-token
RefreshTokenType RefreshTokenObject = RefreshTokenType( client_id: ''; client_secret: ''; grant_type: ''; refresh_token: ''; ) Map<String, dynamic> response = await ApiServices.getRefreshToken(token, RefreshTokenObject);
-
To add a contact in Meet Hour database: => https://docs.v-empower.com/docs/MeetHour-API/bd1e416413e8c-add-contact
AddContactType AddContactObject = AddContactType( countrycode: '', email: '', firstname: '', image: '', is_show_portal: '', lastname: '', phone: '' ); Map<String, dynamic> response = await ApiServices.addContact(token AddContactObject);
-
To get Timezones of various countries: => https://docs.v-empower.com/docs/MeetHour-API/c688c29bce9b9-timezone-list
Map<String, dynamic> response = await ApiServices.timezone(token)
-
To get list of all the contacts in your Meet Hour account: => https://api.meethour.io/api/{version}/customer/contacts
ContactsType AddContactObject = ContactsType( exclude_hosts: 1100, limit: 10, page: 1 ); Map<String, dynamic> response = await ApiServices.contactsList(token, AddContactObject);
-
To make changes in the existing contact details: => https://docs.v-empower.com/docs/MeetHour-API/28cae9187d215-edit-contact
EditContactType EditContactObject = EditContactType( contactid: 1150; countrycode: '', email: '', firstname: '', image: '', is_show_portal: '', lastname: '', phone: '' );
Map<String, dynamic> response = ApiServices.editContact(token, EditContactObject);
10. To get Upcoming Meetings: => https://docs.v-empower.com/docs/MeetHour-API/31df88388416d-upcoming-meetings
UpcomingMeetingType UpcomingMeetingObject = UpcomingMeetingType(
page: 10,
limit: 10,
show_all: 1
);
Map<String, dynamic> response = ApiServices.upcomingMeetings(token, UpcomingMeetingObject
11. To archive a meeting: => https://docs.v-empower.com/docs/MeetHour-API/1dd64523cc6bf-archive-meeting
```
ArchiveMeetingType ArchiveMeetingObject = ArchiveMeetingType(
id: 10
);
Map<String, dynamic> response = ApiServices.archiveMeeting(token, ArchiveMeetingObject);
```
12. To get the details of a missed meeting: => https://docs.v-empower.com/docs/MeetHour-API/92998e2dda102-missed-meetings
```
MissedMeetingType MissedMeetingObject = MissedMeetingType(
limit: 10,
page: number,
show_all: 1
);
Map<String, dynamic> response = ApiServices.missedMeetings(token, MissedMeetingObject);
```
13. To get completed meetings: => https://docs.v-empower.com/docs/MeetHour-API/aa9ef6a678250-completed-meetings
```
CompletedMeetingType CompletedMeetingObject = CompletedMeetingType(
limit: 10,
page: number,
show_all: 1
);
Map<String, dynamic> response = ApiServices.completedMeetings(token, CompletedMeetingObject);
```
14. To edit an existing meeting: => https://docs.v-empower.com/docs/MeetHour-API/5dedde36380b4-meeting-edit-meeting
```
EditMeetingType EdiMeetingObject = EditMeetingType(
meeting_id: ''
meetingName : 'Test',
agenda: '',
passcode: '',
meetingDate: '',
meetingTime: '',
meetingMeridiem: '',
durationhr: '',
durationmin: '',
timezone: '',
isrecurring: '',
recurringtype: '',
repeat_interval: '',
endBy: '',
enddatetime: '',
instructions: '',
is_show_portal: '',
enablepreregistration: '',
meetingtopic: '',
meetingagenda: '',
old_attend: []
options: '',
attend: '',
groups: '',
hostusers: ''
);
Map<String, dynamic> response = await ApiServices.editMeeting(token, EdiMeetingObject);
```
15. To view a meeting: => https://docs.v-empower.com/docs/MeetHour-API/7e9a0a1e0da7f-meeting-view-meeting
```
ViewMeetingType ViewMeetingObject = ViewMeetingType(
meeting_id: ''
);
Map<String, dynamic> response = ApiServices.viewMeeting(token, ViewMeetingObject);
```
16. To get all the recordings list: => https://docs.v-empower.com/docs/MeetHour-API/ce7c4fd8cae7e-recording-list
```
RecordingsListType RecordingMeetingObject = RecordingsListType(
filter_by: '';
limit: '';
page: '';
);
Map<String, dynamic> response = ApiServices.recordingsList(token, RecordingMeetingObject);
Configuration #
IOS #
- Note: Example compilable with XCode 12.2 & Flutter 1.22.4.
Podfile
Ensure in your Podfile you have an entry like below declaring platform of 11.0 or above and disable BITCODE.
platform :ios, '12.1'
...
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
end
end
end
Info.plist
Add NSCameraUsageDescription and NSMicrophoneUsageDescription to your Info.plist.
<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) MyApp needs access to your camera for meetings.</string>
<key>NSMicrophoneUsageDescription</key>
<string>$(PRODUCT_NAME) MyApp needs access to your microphone for meetings.</string>
Android #
Gradle
Set dependencies of build tools gradle to minimum 3.6.3:
dependencies {
classpath 'com.android.tools.build:gradle:7.1.0' <!-- Upgrade this -->
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
Set distribution gradle wrapper to minimum 5.6.4.
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip <!-- Upgrade this -->
AndroidManifest.xml
Meet Hour's SDK AndroidManifest.xml will conflict with your project, namely
the application:label field. To counter that, go into
android/app/src/main/AndroidManifest.xml
and add the tools library
and tools:replace="android:label"
to the application tag.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="yourpackage.com"
xmlns:tools="http://schemas.android.com/tools"> <!-- Add this -->
<application
tools:replace="android:label"
android:name="your.application.name"
android:label="My Application"
android:icon="@mipmap/ic_launcher">
...
</application>
...
</manifest>
Minimum SDK Version 23
Update your minimum sdk version to 23 in android/app/build.gradle
defaultConfig {
applicationId "go.meethour.io.flutter.sdk_example"
minSdkVersion 23 //Required for MeetHour
targetSdkVersion 33
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
Proguard
MeetHour's SDK enables proguard, but without a proguard-rules.pro file, your release apk build will be missing the Flutter Wrapper as well as react-native code. In your Flutter project's android/app/build.gradle file, add proguard support
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
// Add below 3 lines for proguard
minifyEnabled false
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
Then add a file in the same directory called proguard-rules.pro. See the example app's proguard-rules.pro file to know what to paste in.
Note
If you do not create the proguard-rules.pro file, then your app will
crash when you try to join a meeting or the meeting screen tries to open
but closes immediately. You will see one of the below errors in logcat.
Join A Meeting #
_joinMeeting() async {
try {
FeatureFlag featureFlag = FeatureFlag();
featureFlag.welcomePageEnabled = false;
featureFlag.resolution = FeatureFlagVideoResolution.MD_RESOLUTION; // Limit video resolution to 360p
var options = MeetHourMeetingOptions()
..room = "TestRoom" // Required, spaces will be trimmed
..serverURL = "https://meethour.io"
..subject = "Meeting with John"
..userDisplayName = "John Delise"
..token = "" // JWT Token for User authentication as Moderator.
..pcode = "" // To Pass meeting password dynamically.
..userEmail = "john@gmail.com"
..userAvatarURL = "https://someimageurl.com/image.jpg" // or .png
..audioOnly = true
..audioMuted = true
..videoMuted = true
..prejoinPageEnabled = true // Make it false to Skip PrejoinPage
..disableInviteFunctions = true // To disable invite functions in Mobile SDK.
..featureFlag = featureFlag;
await MeetHour.joinMeeting(options);
} catch (error) {
debugPrint("error: $error");
}
}
MeetHourMeetingOptions #
Field | Required | Default | Description |
---|---|---|---|
room | Yes | N/A | Unique room name that will be appended to serverURL. Valid characters: alphanumeric, dashes, and underscores. |
subject | No | $room | Meeting name displayed at the top of the meeting. If null, defaults to room name where dashes and underscores are replaced with spaces and first characters are capitalized. |
userDisplayName | No | "Guest" | User's display name. |
userEmail | No | none | User's email address. |
audioOnly | No | false | Start meeting without video. Can be turned on in meeting. |
audioMuted | No | false | Start meeting with audio muted. Can be turned on in meeting. |
videoMuted | No | false | Start meeting with video muted. Can be turned on in meeting. |
serverURL | No | meethour.io | Specify your own hosted server. Must be a valid absolute URL of the format <scheme>://<host>[/path] , i.e. https://someHost.com. Defaults to Meet Hour's servers. |
userAvatarURL | N/A | none | User's avatar URL. |
token | N/A | none | JWT token used for authentication. |
pcode | N/A | none | pcode used for passing meeting password dynamically. |
prejoinPageEnabled | N/A | false | Make it false to Skip PrejoinPage. |
disableInviteFunctions | N/A | false | To disable invite functions in Mobile SDK. |
featureFlag | No | see below | Object of FeatureFlag class used to enable/disable features and set video resolution of Meet Hour SDK. |
FeatureFlag #
Feature flag allows you to limit video resolution and enable/disable few features of Meet Hour SDK mentioned in the list below.
If you don't provide any flag to MeetHourMeetingOptions, default values will be used.
Flag | Default (Android) | Default (iOS) | Description |
---|---|---|---|
addPeopleEnabled |
true | true | Enable the blue button "Add people", show up when you are alone in a call. Required for flag inviteEnabled to work. |
calendarEnabled |
true | auto | Enable calendar integration. |
callIntegrationEnabled |
true | true | Enable call integration (CallKit on iOS, ConnectionService on Android). SEE REMARK BELOW |
closeCaptionsEnabled |
true | true | Enable close captions (subtitles) option in menu. |
conferenceTimerEnabled |
true | true | Enable conference timer. |
chatEnabled |
true | true | Enable chat (button and feature). |
inviteEnabled |
true | true | Enable invite option in menu. |
iOSRecordingEnabled |
N/A | false | Enable recording in iOS. |
kickOutEnabled |
true | true | Enable kick-out option in video thumb of participants. |
liveStreamingEnabled |
auto | auto | Enable live-streaming option in menu. |
meetingNameEnabled |
true | true | Display meeting name. |
meetingPasswordEnabled |
true | true | Display meeting password option in menu (if a meeting has a password set, the dialog will still show up). |
pipEnabled |
auto | auto | Enable Picture-in-Picture mode. |
raiseHandEnabled |
true | true | Enable raise hand option in menu. |
recordingEnabled |
auto | N/A | Enable recording option in menu. |
resoulution |
N/A | N/A | Set local and (maximum) remote video resolution. Overrides server configuration. Accepted values are: LD_RESOLUTION for 180p, MD_RESOLUTION for 360p, SD_RESOLUTION for 480p(SD), HD_RESOLUTION for 720p(HD) . |
serverURLChangeEnabled |
true | true | Enable server URL change. |
tileViewEnabled |
true | true | Enable tile view option in menu. |
toolboxAlwaysVisible |
true | true | Toolbox (buttons and menus) always visible during call (if not, a single tap displays it). |
videoShareButtonEnabled |
true | true | Enable video share button. |
welcomePageEnabled |
false | false | Enable welcome page. "The welcome page lists recent meetings and calendar appointments and it's meant to be used by standalone applications." |
MeetHourMeetingResponse #
Field | Type | Description |
---|---|---|
isSuccess | bool | Success indicator. |
message | String | Success message or error as a String. |
error | dynamic | Optional, only exists if isSuccess is false. The error object. |
Listening to Meeting Events #
Events supported
Name | Description |
---|---|
onConferenceWillJoin | Meeting is loading. |
onConferenceJoined | User has joined meeting. |
onConferenceTerminated | User has exited the conference. |
onPictureInPictureWillEnter | User entered PIP mode. |
onPictureInPictureTerminated | User exited PIP mode. |
onError | Error has occurred with listening to meeting events. |
Per Meeting Events #
To listen to meeting events per meeting, pass in a MeetHourMeetingListener
in joinMeeting. The listener will automatically be removed when an
onConferenceTerminated event is fired.
await MeetHour.joinMeeting(options,
listener: MeetHourMeetingListener(onConferenceWillJoin: ({message}) {
debugPrint("${options.room} will join with message: $message");
}, onConferenceJoined: ({message}) {
debugPrint("${options.room} joined with message: $message");
}, onConferenceTerminated: ({message}) {
debugPrint("${options.room} terminated with message: $message");
}, onPictureInPictureWillEnter: ({message}) {
debugPrint("${options.room} entered PIP mode with message: $message");
}, onPictureInPictureTerminated: ({message}) {
debugPrint("${options.room} exited PIP mode with message: $message");
}));
Global Meeting Events #
To listen to global meeting events, simply add a MeetHourListener with
MeetHour.addListener(myListener)
. You can remove listeners using
MeetHour.removeListener(listener)
or MeetHour.removeAllListeners()
.
@override
void initState() {
super.initState();
MeetHour.addListener(MeetHourMeetingListener(
onConferenceWillJoin: _onConferenceWillJoin,
onConferenceJoined: _onConferenceJoined,
onConferenceTerminated: _onConferenceTerminated,
onPictureInPictureWillEnter: _onPictureInPictureWillEnter,
onPictureInPictureTerminated: _onPictureInPictureTerminated,
onError: _onError));
}
@override
void dispose() {
super.dispose();
MeetHour.removeAllListeners();
}
_onConferenceWillJoin({message}) {
debugPrint("_onConferenceWillJoin broadcasted");
}
_onConferenceJoined({message}) {
debugPrint("_onConferenceJoined broadcasted");
}
_onConferenceTerminated({message}) {
debugPrint("_onConferenceTerminated broadcasted");
}
_onPictureInPictureWillEnter({message}) {
debugPrint("_onPictureInPictureWillEnter broadcasted with message: $message");
}
_onPictureInPictureTerminated({message}) {
debugPrint("_onPictureInPictureTerminated broadcasted with message: $message");
}
_onError(error) {
debugPrint("_onError broadcasted");
}
Closing a Meeting Programmatically #
MeetHour.closeMeeting();
Contributing #
Send a pull request with as much information as possible clearly describing the issue or feature. Keep changes small and for one issue at a time.