I wanna to get voice call function in my app(using flutter). Here is my code and log.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'MainScreen.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:permission_handler/permission_handler.dart';
import 'dart:core';
// ChatRoom 모델
class ChatRoom {
final String title;
final int limit;
final bool isPrivate;
final String password;
final String ownerId;
final String ownerPhotoUrl;
final String ownerNickname;
ChatRoom({
required this.title,
required this.limit,
required this.isPrivate,
required this.password,
required this.ownerId,
required this.ownerPhotoUrl,
required this.ownerNickname,
});
Map<String, dynamic> toMap() {
return {
'title': title,
'limit': limit,
'isPrivate': isPrivate,
'password': password,
'ownerId': ownerId,
'ownerPhotoUrl': ownerPhotoUrl,
'ownerNickname': ownerNickname,
};
}
}
class VoiceChatRoomScreen extends StatefulWidget {
final String roomId;
VoiceChatRoomScreen({Key? key, required this.roomId}) : super(key: key);
@override
_VoiceChatRoomScreenState createState() => _VoiceChatRoomScreenState();
}
class _VoiceChatRoomScreenState extends State<VoiceChatRoomScreen> {
String appId = "af65ec64fd244043a786ba6b820fa01f";
int uid = 0; // uid of the local user
int? _remoteUid; // uid of the remote user
bool _isJoined = false; // Indicates if the local user has joined the channel
late RtcEngine agoraEngine; // Agora engine instance
final GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey
= GlobalKey<ScaffoldMessengerState>(); // Global key to access the scaffold
showMessage(String message) {
scaffoldMessengerKey.currentState?.showSnackBar(SnackBar(
content: Text(message),
));
}
List<Map<String, dynamic>> members = [];
String ownerId = '';
final DatabaseReference _userStatusRef = FirebaseDatabase.instance.reference()
.child('usersStatus');
List<String> onlineMembers = [];
@override
void initState() {
super.initState();
// 채팅방 정보와 멤버 정보를 로드하는 기존의 메서드를 유지합니다.
_loadRoomInfo();
_loadRoomMembers();
setupVoiceSDKEngine().then((_) {
join(); // Ensure join is called after setupVoiceSDKEngine is completed
});
}
Future<void> setupVoiceSDKEngine() async {
// retrieve or request microphone permission
await [Permission.microphone].request();
//create an instance of the Agora engine
agoraEngine = createAgoraRtcEngine();
await agoraEngine.initialize(RtcEngineContext(
appId: appId
));
// Register the event handler
agoraEngine.registerEventHandler(
RtcEngineEventHandler(
onJoinChannelSuccess: (RtcConnection connection, int elapsed) {
showMessage("Local user uid:${connection.localUid} joined the channel");
setState(() {
_isJoined = true;
});
print("Local user joined the channel");
},
onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) {
showMessage("Remote user uid:$remoteUid joined the channel");
setState(() {
_remoteUid = remoteUid;
});
print("Remote user joined the channel with uid: $remoteUid");
},
onUserOffline: (RtcConnection connection, int remoteUid,
UserOfflineReasonType reason) {
showMessage("Remote user uid:$remoteUid left the channel");
setState(() {
_remoteUid = null;
});
print("Remote user left the channel with uid: $remoteUid");
},
),
);
}
Future<void> join() async {
ChannelMediaOptions options = const ChannelMediaOptions(
clientRoleType: ClientRoleType.clientRoleBroadcaster,
channelProfile: ChannelProfileType.channelProfileCommunication,
);
await agoraEngine.joinChannel(
token: widget.roomId,
channelId: widget.roomId ,
options: options,
uid: uid,
);
print("Channel join request sent with channelId: ${widget.roomId}");
}
// 채팅방 정보를 로드하는 메서드
Future<void> _loadRoomInfo() async {
DocumentSnapshot roomSnapshot = await FirebaseFirestore.instance
.collection('chatRooms')
.doc(widget.roomId)
.get();
if (roomSnapshot.exists) {
Map<String, dynamic> roomData = roomSnapshot.data() as Map<String,
dynamic>;
setState(() {
ownerId = roomData['ownerId'];
print("방장 ID: $ownerId"); // 방장 ID 로그 출력
});
}
}
@override
void dispose() {
// WebRTC 리소스 정리
// 채팅방을 떠나는 로직. 예를 들어, 서버에 'leave' 메시지를 보낼 수 있습니다.
leaveChatRoom().then((_) {
// 채팅방을 떠난 후, 메인 화면으로 돌아갑니다.
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) => MainScreen()),
(Route<dynamic> route) => false,
);
});
agoraEngine.leaveChannel();
super.dispose();
}
Future<void> leaveChatRoom() async {
final userId = FirebaseAuth.instance.currentUser?.uid;
if (userId != null) {
// 사용자를 오프라인으로 설정
// 'chatRooms/{roomId}/members/{userId}' 문서 삭제
await FirebaseFirestore.instance
.collection('chatRooms')
.doc(widget.roomId)
.collection('members')
.doc(userId)
.delete();
setState(() {
_isJoined = false;
_remoteUid = null;
});
agoraEngine.leaveChannel();
}
}
Future<void> _loadRoomMembers() async {
FirebaseFirestore.instance
.collection('chatRooms')
.doc(widget.roomId)
.collection('members')
.snapshots()
.listen((snapshot) async {
// 온라인 상태인 사용자 ID 목록을 가져옵니다.
// 멤버 목록을 업데이트합니다.
List<Map<String, dynamic>> updatedMembers = [];
for (var doc in snapshot.docs) {
String memberId = doc.id;
Map<String, dynamic> memberData = doc.data() as Map<String, dynamic>;
updatedMembers.add(memberData);
}
if (mounted) {
setState(() {
members = updatedMembers;
});
}
});
}
@override
Widget build(BuildContext context) {
// UI 구성 부분은 이전과 동일하되, 방장 여부 확인 로직을 추가합니다.
return Scaffold(
appBar: AppBar(
title: Text('음성 채팅방'),
),
body: members.isEmpty
? Center(child: CircularProgressIndicator())
: ListView.builder(
itemCount: members.length,
itemBuilder: (context, index) {
bool isOwner = members[index]['uid'] == ownerId; // 방장 여부 판단
return ListTile(
leading: CircleAvatar(
backgroundImage: NetworkImage(members[index]['photoUrl']),
radius: 25,
),
title: Text(members[index]['nickname']),
trailing: isOwner
? Text(
'방장', style: TextStyle(color: Colors.red)) // 방장일 경우 "King" 표시
: null,
);
},
),
);
}
}
,,,,
and the log is saying I succeeded to enter the voice channel.
[info] [iris_rtc_api_engine.cc:407] api name RtcEngine_initialize_0320339 result 0 outdata {"result":0}
[info] [iris_rtc_api_engine.cc:343] api name RtcEngine_setAppType params "{"appType":4}"
[info] [iris_rtc_api_engine.cc:407] api name RtcEngine_setAppType result 0 outdata {"result":0}
[info] [iris_rtc_api_engine.cc:343] api name RtcEngine_registerEventHandler_5fc0465 params "{}"
[info] [i
ris_rtc_api_engine.cc:395] api name RtcEngine_registerEventHandler_5fc0465 extened params "{"event":10796528752}"
[info] [iris_rtc_api_engine.cc:407] api name RtcEngine_registerEventHandler_5fc0465 result 0 outdata {"result":0}
[info] [iris_rtc_api_engine.cc:341] api name RtcEngine_joinChannel_cdbb747 params "{"token":"qOEc***************GPsO","channelId":"qOEcnJcSyg1I4DgSGPsO","uid":0,"options":{"clientRoleType":1,"channelProfile":0}}"
[info] [iris_rtc_api_engine.cc:407] api name RtcEngine_joinChannel_cdbb747 result 0 outdata {"result":0}
flutter: Channel join request sent with channelId: qOEcnJcSyg1I4DgSGPsO
but the voice call doesn't work in my voiceroom... what do i have to do??!!
E/libc (17700): Access denied finding property "net.dns1"
E/libc (17700): Access denied finding property "net.dns2"
E/libc (17700): Access denied finding property "net.dns3"
E/libc (17700): Access denied finding property "net.dns4"
and whenever I say to phone, these emerged...
I wanna get voice call function in my flutter app