Change Role
Role
is a powerful concept that takes a lot of complexity away in handling permissions and supporting features like breakout rooms.
Each HMSPeer
instance has a role
property which returns an HMSRole
instance. You can use this property to do the following:
-
Check what this Role is allowed to publish, that is, can it publish a video (and at what resolution)? Can it publish audio? Can it share a screen? Who can this role subscribe to?
For example, a Student Role can only see the Teacher's video. This is can be discovered by checking
publishSettings
andsubscribeSettings
properties. -
Check what actions this Role can perform. i.e can it change someone else's current Role, End the Meeting, or remove someone from the room? This is can be discovered by checking the
permissions
property.
In certain scenarios, you may want to change someone's role.
Imagine an audio room with 2 roles speaker
and listener
. Only someone with a speaker
role can publish audio to the room while a listener
can only subscribe.
Now at some point, the speaker
may decide to nominate some listener
to become a speaker
.
This is where Change Role capabilities come into play.
You may choose to do either:
-
Single Peer Role Change: Change the role of a single peer to a specified one using the
changeRoleOfPeer
API -
Bulk Role Change: Change the role of all peers with a certain role, to a specified one using the
changeRoleOfPeersWithRoles
API
Single Peer Role Change
Note: 🔑 changeRoleOfPeer
is the same as changeRole
but we have deprecated changeRole
and it will be removed in future releases. So, Please
use changeRoleOfPeer
.
class Meeting implements HMSUpdateListener, HMSActionResultListener{ ... void changeRoleOfPeer({required HMSPeer peer,required HMSRole roleName,bool forceChange}) { ///[peer]: peer whose role needs to be changed ///[toRole]: the role which we want the peer to be in(destination role). ///[forceChange]: it indicates whether to change the role of a peer forcefully ///If set to `true` then the role will be changed without asking permission from the [peer] ///In case of `false` permissions will be asked and the role will be changed only after the request is accepted. ///[hmsActionResultListener]: an instance of a class which implements HMSActionResultListener //Here this is an instance of a class that implements HMSActionResultListener that is Meeting hmsSDK.changeRoleOfPeer( forPeer: peer, toRole: roleName, force: forceChange, hmsActionResultListener: this); } void onSuccess( {HMSActionResultListenerMethod methodType = HMSActionResultListenerMethod.unknown, Map<String, dynamic>? arguments}) { switch (methodType) { ... case HMSActionResultListenerMethod.changeRoleOfPeer: //Here we will receive the success callback break; ... } } void onException( {HMSActionResultListenerMethod methodType = HMSActionResultListenerMethod.unknown, Map<String, dynamic>? arguments, required HMSException hmsException}) { switch (methodType) { ... case HMSActionResultListenerMethod.changeRoleOfPeer: // Check the HMSException object for details about the error break; ... } } }
To invoke this method we will need 4 parameters.
-
forPeer
: An instance ofHMSPeer
of the peer whose role you want to change. -
toRole
: TheHMSRole
instance for the target role. -
force
: Whether you want to change their role without asking them or give them a chance to accept/reject. -
hmsActionResultListener
: TheHMSActionResultListener
will get a success or failure callback depending on the result of the request.
How to handle it at receiver side if force
is false.Check it out here
Note: success doesn't mean that the role was changed, just that the server accepted the request as valid.
If the changeRole was succeeded you will get an update in the onPeerUpdate
with roleUpdated
as update type,
With the same peer, you passed as forPeer
and an HMSPeerUpdate.roleUpdated
update type.
class Meeting implements HMSUpdateListener, HMSActionResultListener{ ... void onPeerUpdate({required HMSPeer peer, required HMSPeerUpdate update}) async { switch (update) { ... case HMSPeerUpdate.roleUpdated: //Here we will get the update with peer being the same as the `forPeer` we sent in changeRole break; ... } } }
Bulk Role Change
Bulk Role Change is used when we want to change the role of peers with a specific role to another role.
For example, if peers join a room with a waiting
role and now you want to change all these peers to viewer
role then use the changeRoleOfPeersWithRoles
method.
class Meeting implements HMSUpdateListener, HMSActionResultListener{ ... void changeRoleOfPeersWithRoles( {required HMSRole toRole, required List<HMSRole> ofRoles, HMSActionResultListener? hmsActionResultListener}) { ///[toRole]: the role you wish to move peers into(destination role) ///[ofRoles]: List of roles whose role needs to be changed ///[hmsActionResultListener]: an instance of a class which implements HMSActionResultListener //Here this is an instance of a class that implements HMSActionResultListener that is Meeting hmsSDK.changeRoleOfPeersWithRoles( toRole: toRole, ofRoles: ofRoles, hmsActionResultListener: this); } void onSuccess( {HMSActionResultListenerMethod methodType = HMSActionResultListenerMethod.unknown, Map<String, dynamic>? arguments}) { switch (methodType) { case HMSActionResultListenerMethod.changeRoleOfPeer: break; case HMSActionResultListenerMethod.changeRoleOfPeersWithRoles: //Here we will receive the success callback break; ... } } void onException( {HMSActionResultListenerMethod methodType = HMSActionResultListenerMethod.unknown, Map<String, dynamic>? arguments, required HMSException hmsException}) { switch (methodType) { case HMSActionResultListenerMethod.changeRoleOfPeer: break; case HMSActionResultListenerMethod.changeRoleOfPeersWithRoles: // Check the HMSException object for details about the error break; ... } } }
Edge cases with bulk role change
-
Note that if an empty list is sent to
ofRoles
, no roles will be changed. This is to avoid accidentally changing roles you may not have intended such as the bots that provide recording and streaming with the rolesbeam
. -
Also, Bulk Role Changes are always forced, that is, no option will be given for the peer to accept it, they will just be changed immediately.
Let's have a look at an example of bulk role change
Here's how the method could be called to change all waiting
and guest
roles to host
:
// fetch all available Roles in the room List<HMSRole> roles = await hmsSDK.getRoles(); // get the Host Role object HMSRole toHostRole = roles.firstWhere((element) => element.name == "host"); // get a list of Roles to be updated - in this case, "Waiting" and "Guest" Roles roles.retainWhere((element) => ((element.name == "waiting") || (element.name == "guest"))); // now perform Role Change of all peers in "Waiting" and "Guest" Roles to the "Host" Role hmsSDK.changeRoleOfPeersWithRoles( toRole: toHostRole, ofRoles: roles, hmsActionResultListener: hmsActionResultListener);
Bulk Role Change Errors
You may get the following errors for bulk role change:
Message | Meaning |
---|---|
invalid role | A role in the list of roles to change does not exist in this room. |
target role clash with requested roles | the 'toRole' is also listed as one to change to 'toRole' |
role does not have required permission | Peer does not have role change permission. |
peer left | The peer who's role was to be changed has left. |
role invalid | The 'toRole' is invalid. |
Accept Role change Request
When a peer wishes to change the role of another peer it calls changeRoleOfPeer
with a parameter force
.
The force
parameter in changeRoleOfPeer
,
- when
true
role is directly changed and the peer receives anonPeerUpdate
with method type asroleUpdated
. - when
false
, is a polite request: "Would you like to change your role from listener to speaker?" Which can be ignored by the peer. The way it works is the other peer will first receive anonRoleChangeRequest
callback inHMSUpdateListener
:
Let's understand this with a diagram:
Now let's do it step-by-step:
PeerA calls changeRoleOfPeer with force as false
//Assuming that HMSActionResultListener is implemented in the class where this function is being called hmsSDK.changeRoleOfPeer( forPeer: peerB, toRole: new-role, force: false, hmsActionResultListener: this);
PeerB receives onRoleChangeRequest
PeerB receives onRoleChangeRequest in the class wherever HMSUpdateListener is implemented.
class Meeting implements HMSUpdateListener, HMSActionResultListener{ ... void onRoleChangeRequest({required HMSRoleChangeRequest roleChangeRequest}) { //Show some popup asking for permissions } }
At this point, the app should show a prompt to the user asking for permission to accept or deny role change.
How to extract info from HMSRoleChangeRequest to show popups for permission
HMSRoleChangeRequest
is a class that contains info about the role change request.
It contains two attributes:
- suggestedRole -> This is an
HMSRole
object which contains info about the destination role - suggestedBy -> This is an
HMSPeer
object which contains info about the peer who performed a role change
To get information like role name and peer who performed role change we can do it like :
class Meeting implements HMSUpdateListener, HMSActionResultListener{ ... void onRoleChangeRequest({required HMSRoleChangeRequest roleChangeRequest}) { String? peerWhoPerformedRoleChange = roleChangeRequest.suggestedBy?.name; String? destinationRole = roleChangeRequest.suggestedRole.name } }
PeerB calls acceptChangeRole
If the user wants to accept the request, the app should invoke acceptChangeRole
on HMSSDK
instance:
//roleChangeRequest: this is the same request which we received in onRoleChangeRequest hmsSDK.acceptChangeRole(hmsRoleChangeRequest: roleChangeRequest, hmsActionResultListener: hmsActionResultListener);
All the peers receive onPeerUpdate with type as roleUpdated
Now, all peers in the room will receive an HMSPeerUpdate.roleUpdated
callback so that they can do the necessary UI updates.
PeerB will have all the permissions of new role.
Case with changeRoleOfPeer with
Now let's imagine the newly nominated speaker is not behaving nicely and we want to move him back to the listener without a prompt. This is where the force
parameter comes in.
When it is set to true the other party will not receive a confirmation roleChangeRequest
but instead will straight away receive a new set of updated permissions and stop publishing.
HMSPeerUpdate.roleUpdated
callback will still be fired so that the app can update the user's UI state.
Preview For Role
Preview for role is a feature that allows you to preview the camera/mic states of the new role in which you are transitioning to. This is useful when you want to check if your camera/mic is working before you transition to a new role. This provides two methods:
- previewForRole
- cancelPreview
previewForRole
This returns an object of Future<dynamic>
which can be either of HMSException
type or a List<HMSTrack>
type based on whether method execution is completed successfully or not.
It takes a HMSRole
as a parameter which is the role in which you want to preview.
void previewForRole({required String role}) async { HMSLocalVideoTrack? previewForRoleVideoTrack; HMSLocalAudioTrack? previewForRoleAudioTrack; ///hmsSDK is the instance of HMSSDK var result = await hmsSDK.previewForRole(role: role); if (result is HMSException) { //Handle the exception here } else{ ///Here we find the index of video track from the result list var indexForVideoTrack = (result as List<HMSTrack>).indexWhere( (element) => element.kind == HMSTrackKind.kHMSTrackKindVideo && element.source == "REGULAR"); if (indexForVideoTrack != -1) { ///We will use this track to display video preview previewForRoleVideoTrack = result[indexForVideoTrack] as HMSLocalVideoTrack; } ///Here we find the index of audio track from the result list var indexForAudioTrack = result.indexWhere( (element) => element.kind == HMSTrackKind.kHMSTrackKindAudio); if (indexForAudioTrack != -1) { previewForRoleAudioTrack = result[indexForAudioTrack] as HMSLocalAudioTrack; } } }
cancelPreview
If a [previewForRole] call was performed previously then calling this method clears the tracks created anticipating a change of role. This method only needs to be called if the user declined the request for role change.
This returns an object of Future<dynamic>
which can be either of HMSException
type or a boolean
value [true] based on whether method execution is completed successfully or not.
Future<dynamic> cancelPreview() async { ///hmsSDK is the instance of HMSSDK var result = await hmsSDK.cancelPreview(); ///If the result is of type HMSException then handle the exception if (result is HMSException) { //Handle the exception here } else{ ///If the result is of type bool then check if it is true if(result){ ///Preview cancelled successfully } } }