Here, I am going to share the code of Agora voice call and Flutter integration. Here we need to make sure you have agora sdk installed using the plugin.
In this flutter application I have used Getx for state management. It’s a complete about audio and video voice call.
Make sure you installed the plugin.
agora_rtc_engine: ^6.1.0
Here’s the complete code
class VoiceCallController extends GetxController {
VoiceCallController();
final state = VoiceCallState();
final player = AudioPlayer();
String appId = APPID;
final db = FirebaseFirestore.instance;
final profile_token = UserStore.to.profile.token;
late final RtcEngine engine;
ChannelProfileType channelProfileType = ChannelProfileType.channelProfileCommunication;
@override
void onInit(){
super.onInit();
var data = Get.parameters;
state.to_name.value = data["to_name"]??"";
state.to_avatar.value = data["to_avatar"]??"";
state.call_role.value = data["call_role"]??"";
state.doc_id.value = data["doc_id"]??"";
state.to_token.value = data['to_token']??"";
print("...your name id ${state.to_name.value}");
initEngine();
}
Future<void> initEngine()async {
await player.setAsset("assets/Sound_Horizon.mp3");
engine = createAgoraRtcEngine();
await engine.initialize(RtcEngineContext(
appId: appId,
));
engine.registerEventHandler(RtcEngineEventHandler(
onError: (ErrorCodeType err, String msg){
print('[....onError] err: $err, ,msg:$msg');
},
onJoinChannelSuccess: (RtcConnection connection, int elapsed){
print('....onConnection ${connection.toJson()}');
state.isJoined.value = true;
},
onUserJoined: (RtcConnection connection, int remoteUid, int elasped) async {
await player.pause();
},
onLeaveChannel: (RtcConnection connection, RtcStats stats){
print('...user left the room...');
state.isJoined.value= false;
},
onRtcStats: (RtcConnection connection, RtcStats stats){
print("time....");
print(stats.duration);
}
));
await engine.enableAudio();
await engine.setClientRole(role: ClientRoleType.clientRoleBroadcaster);
await engine.setAudioProfile(
profile: AudioProfileType.audioProfileDefault,
scenario: AudioScenarioType.audioScenarioGameStreaming
);
await joinChannel();
if(state.call_role=="anchor"){
// send notifcation to the other user
await sendNotification("voice");
await player.play();
}
}
Future<void> sendNotification(String call_type)async {
CallRequestEntity callRequestEntity= CallRequestEntity();
callRequestEntity.call_type = call_type;
callRequestEntity.to_token = state.to_token.value;
callRequestEntity.to_avatar = state.to_avatar.value;
callRequestEntity.doc_id = state.doc_id.value;
callRequestEntity.to_name = state.to_name.value;
print("...the other user's token is ${state.to_token.value}");
var res = await ChatAPI.call_notifications(params: callRequestEntity);
if(res.code==0){
print("notification success");
}else
print("could not send notification");
}
Future<String> getToken() async {
if(state.call_role=="anchor"){
state.channelId.value = //12 //13
md5.convert(utf8.encode("${profile_token}_${state.to_token}")).toString();
}else{
state.channelId.value = //12 //13
md5.convert(utf8.encode("${state.to_token}_${profile_token}")).toString();
}
CallTokenRequestEntity callTokenRequestEntity= CallTokenRequestEntity();
callTokenRequestEntity.channel_name = state.channelId.value;
print("...channel id is ${state.channelId.value}");
print("...my access token is ${UserStore.to.token}");
var res = await ChatAPI.call_token(params: callTokenRequestEntity);
if(res.code==0){
return res.data!;
}else{
print("my data is ${res.data}");
return res.data!;
}
return "";
}
Future<void> joinChannel() async {
await Permission.microphone.request();
EasyLoading.show(
indicator: CircularProgressIndicator(),
maskType: EasyLoadingMaskType.clear,
dismissOnTap: true
);
String token = await getToken();
if(token.isEmpty){
EasyLoading.dismiss();
Get.back();
return;
}
await engine.joinChannel(
token: token,
channelId: state.channelId.value,
uid: 0,
options: ChannelMediaOptions(
channelProfile: channelProfileType,
clientRoleType: ClientRoleType.clientRoleBroadcaster
)
);
EasyLoading.dismiss();
}
Future<void> leaveChannel() async {
EasyLoading.show(
indicator: CircularProgressIndicator(),
maskType: EasyLoadingMaskType.clear,
dismissOnTap: true
);
await player.pause();
await sendNotification("cancel");
state.isJoined.value = false;
EasyLoading.dismiss();
Get.back();
}
Future<void> _dispose() async {
await player.pause();
await engine.leaveChannel();
await engine.release();
await player.stop();
}
@override
void onClose(){
_dispose();
super.onClose();
}
}
It includes notification as well. The code shows notification, playing audio, connecting with other on the agora server.
Other features include
- join channel
- get device token
- leave channel