Get Current Active user from the Zoom iOS SDK Custom Meeting implementation - ios

I have implemented the Zoom iOS SDK to work with a custom UI. Everything works just as its supposed to but I haven't been able to figure out how I can get the userID of the currently active user.
I have implemented the below delegate method which tells about the current active video user, but unfortunately it shows all the other participants in the meeting except me.
func onSinkMeetingActiveVideo(_ userID: UInt) {
if let service = MobileRTC.shared().getMeetingService(), let username = service.userInfo(byID: userID)?.userName {
print("\(#function) : \(userID) : \(username)")
}
}
I need to know who is the current active user even if its me who is talking.

You can retrieve this kind of information from meeting service MobileRTCMeetingService.
MobileRTCMeetingService
func getActiveUserId() -> UInt? {
if let meetingService = MobileRTC.shared().getMeetingService() {
return meetingService.activeUserID()
}
return nil
}
Extra note: in Zoom there is also the concept of Pinned User that overrides active user in active video cell.
Pinned user id can be retrieved in this way:
func getPinnedUserId() -> UInt? {
if let meetingService = MobileRTC.shared().getMeetingService(), let userList = meetingService.getInMeetingUserList(){
for userId in userList {
if let userId = userId as? UInt, meetingService.isUserPinned(userId) {
return userId
}
}
return nil
}
return nil
}
So in order to establish which is the user id of the video in active video cell you have to check both, giving priority to pinned user.
let currentVideoUserId = getPinnedUserId() ?? getActiveUserId()
During the meeting you will never been the active user in your own video cell because even if your are speaking, you will continue to see the other person in active video cell.
On the other side if you are interested to know who is talking then you have to retrieve the user list and check the audioStatus [MobileRTCAudioStatus].
MobileRTCAudioStatus
MobileRTCMeetingUserInfo
Just pay attention that you can have more than one user speaking at the same time.
There is also another callback that can be useful if you are interested in active speaker user: it is the onSinkMeetingActiveVideoForDeck in MobileRTCVideoServiceDelegate
MobileRTCVideoServiceDelegate
According to the documentation it should be fired every time that there is a new speaker. It is used by ZOOM UI for changing the yellow frame around the active speaker user.

I according to the documentation, in order to get the current active video user info you should use the following class: MobileRTCMeetingUserInfo.
Check the doc for the video status class MobileRTCVideoStatus: https://marketplacefront.zoom.us/sdk/meeting/ios/interface_mobile_r_t_c_video_status.html
and you will see that is related with the MobileRTCMeetingUserInfo:
https://marketplacefront.zoom.us/sdk/meeting/ios/interface_mobile_r_t_c_meeting_user_info.html
On that class you will find info of the current user.
Hope you can figure out your problem!
Regards!
Gastón Montes.

Related

phone authentication using firebaseUI ios swift

i'm ios fresher. i want to retrieve phone number with country code from the default firebase phone authentication screen.
This is default screen that firebase provides. how can i retrieve country code & phone number on verify buttonClick that is enter by the user and how can i get verify buttonClick event? Is there any library provided function to get buttonClick?
i am stuck here
fileprivate func startLogin() {
self.authUI?.delegate = self
self.authStateListenerHandle = self.auth?.addStateDidChangeListener { (auth, user) in
if user != nil {
print(user)
}else {
do{
try self.auth?.signOut()
print("singning out done")
}catch{
print("Error while signing out!")
}
let phoneProvider = FUIPhoneAuth(authUI: self.authUI!)
self.authUI?.providers = [phoneProvider]
phoneProvider.signIn(withPresenting: self.rootController!, phoneNumber: nil)
}
}
}
this code open phone number login screen for me, bt after providing phone no. when i click to the verify button i have to pass user's phone no. in bellow code to send opt on users mobile, bt i don't know how can i get verify buttonClick event & how can i retrieve phone no. & country code that user input in the phone authentication screen.
PhoneAuthProvider.provider().verifyPhoneNumber(("need to pass phone number with country code here")!, uiDelegate: nil) { (verificationID, error) in
if let error = error {
// self.showMessagePrompt(error.localizedDescription)
return
}
// Sign in using the verificationID and the code sent to the user
// ...
}
Please also explain me right flow of verification.
Why dont you use the Firebase methods to access the phone number once the tocken is verified?
Access the tocken and verify the credibility and after that you can use decodedTocken.phone_number property . Use below to access the phone number
admin.auth().verifyIdToken(idToken).then(function(decodedToken) {
var uid = decodedToken.phone_number;
// ...
}).catch(function(error) {
// Handle error
});
Maybe after you access the phone number you can use the string and break down the country code, just a sugesstion, take a look at the below described answer with how to verify the phone number as well
https://stackoverflow.com/a/45227042/10021979

Identify incoming callers with CallKit when they are already contacts

I am creating an app that tracks money owed between friends. I would like to create a feature where incoming calls will show with a warning if that person owes you money.
I am using the Apple-provided approach to identify callers:
class CustomCallDirectoryProvider: CXCallDirectoryProvider {
override func beginRequest(with context: CXCallDirectoryExtensionContext) {
let labelsKeyedByPhoneNumber: [CXCallDirectoryPhoneNumber: String] = [ … ]
for (phoneNumber, label) in labelsKeyedByPhoneNumber.sorted(by: <) {
context.addIdentificationEntry(withNextSequentialPhoneNumber: phoneNumber, label: label)
}
context.completeRequest()
}
}
This works great so far for incoming calls. However, if the call is coming from a person that is already in the user's contact list then that name will show and our information will not show.
Is there a way to show our contract information even when the caller is in the user's contact list?
No, data from the CallKit identification extension is only used if there is no match against an existing contact.

IOS Swift Nested DispatchGroup for Nested Network requests handling arrays

I'm experiencing crashes and I'm not too sure how to handle the situation with nested dispatchgroup inside a dispatchgroup. I know I'm doing something wrong and getting crashes and would like some help with how to handle below situation:
I am using IOS Swift and Firebase and basically grabbing relevant mutual friends by first grabbing a friendList, and then grabbing the friends of each of the friends on my friendList (as those are my mutual friends), if I have not grabbed them earlier (I use a list to track ids of friends Ive already grabbed), I send another network request to fb to grab the number of mutual friends between current user and mutual friend and check if they are relevant enough to be added.
However I have another request after that grabs school friends from firebase and I need to make sure there arent duplicate entries because there are school friends that are also mutual friends. I'm using Dispatch groups like so:
// Iterates through friendList to grab mutual friends
for user in currUser.friendList {
// Grabs user friend list
let userFriendListRef = Database.database().reference().child("friend-list").child(user.userID)
userFriendListRef.observeSingleEvent(of: .value, with: { (snapshot) in
guard snapshot.exists(),
let userFriendList = snapshot.value as? [String: Any] else {
logger.info("No mutual friends grabbed from friend")
return
}
// Mutual friends dispatchGroup
self.mutualFriendsDispatchGroup.enter()
// If exists friends, then see if matches user's interest
self.filterMutualFriendsToMatchUserInterest(using: userFriendList)
})
}
self.mutualFriendsDispatchGroup.notify(queue: .main) {
logger.info("Done mutual friends")
}
// Checks if mutual friend matches interest and then adds it into collectionView
fileprivate func filterMutualFriends(using userFriendList: [String: Any]) {
// Maintains a counter
var searchedMutualFriendCounter = 0
// Iterates through userFriendList
for (userID, _) in userFriendList {
searchedMutualFriendCounter += 1 // Increments counter
// Ensures not repeating a mutual friend
guard usersAddedToHomeScroll[userID] == nil,
searchedUsers[userID] == nil,
!blockedUsers.contains(userID) else {
// Handles mutual friend dispatch group leave condition
if searchedMutualFriendCounter == userFriendList.count {
self.mutualFriendsDispatchGroup.leave()
return
}
continue
}
searchedUsers[userID] = true
grabFriendsDispatchGroup.enter()
// Checks if has enough mutual friends, if yes, grab mutual friend data, else skip
checkIfFriendHasEnoughMutualFriends(userID) { (result) -> Void in
// Makes sure that has enough mutual friends
guard result else {
logger.info("Not enough mutual friends to show in userFriendScroll for \(userID)")
self.grabFriendsDispatchGroup.leave()
// Handles mutual friend dispatch group leave condition
if searchedMutualFriendCounter == userFriendList.count {
self.mutualFriendsDispatchGroup.leave()
}
return
}
logger.info("Mutual friend ID grabbed for \(userID)")
self.grabMutualFriendData(userID, index: searchedMutualFriendCounter, total: userFriendList.count)
}
}
}
fileprivate func getAllFriends() {
// Grabs mutual friends
getMutualFriends()
// Gets school friends
getSchoolFriends()
// Reloads data after grabbing it all
grabFriendsDispatchGroup.notify(queue: .main) {
self.collectionView.reloadData()
}
}
I also call mutualFriendsDispatchGroup.leave() in grabMutualFriendData(...) method.
I apologize for the large amount of code, I was trying to figure out basically how to put in sync lots of network requests nest in a network request to grab mutual friends and before my grab school friends so that I dont get duplicate entries on my collectionView presenting the grabbed users.
Note: The counter thing in filterMutualFriends(...) is a hack I was attempting that would exit out of the outer dispatchgroup once you've iterated through the friendlist of a friend. The outer mutual friends dispatchGroup is the one crashing.
Could not figure out a proper long-term solution to fix the issue, so I had to hack around it and use a bad workaround which just removes duplicate users everytime a new user is grabbed and then reloads the collectionView. However, note that this will and can cause problems in the code.

How to check whether the user is new user or old user

I have one login screen, which have email, password. And in register screen after user registred they will come to login screen to login.
That time I need to check , if the user is first time user or old user. If first time user means I need to redirect them to my feedback screen. Or old user means I need to redirect them to my home screen. How to do that with firebase?
Her my code for login screen :
#IBAction func loginWithUserNamePassword(){
loginWithMailAndPassword((username.text?.trimWhiteSpace)!, password: (password.text?.trimWhiteSpace)!) { (user, error) in
if error != nil{
KRProgressHUD.dismiss()
SCLAlertView().showError("Login Error", subTitle: error!.localizedDescription)
}
else {
KRProgressHUD.dismiss()
if user!.emailVerified{
currentUser = user
enableSync()
self.callHomescreen()
}
else
{
AlertView().showError("Login Error", subTitle: "This email is has not been verified yet")
}
}
}
}
Or else in my feed back screen there are some text fields. And the model class is :
var feedbackData = [files]()
class files {
// having some string variables
}
By using this, if my data is empty in my feedback screen redirect the user to feedback screen or else redirect them to home screen. Can we do that?
Updated :
if profileData.FirstName.characters.count <= 0 {
print("Home screen calling")
}
else if profileData.FirstName.characters.count > 0 {
print("feedback screen calling")
}
Thought of trying like this. But no use.
If I understand your question currectly, once user is logged in, you want to check the creation date of the use account. To do so you have two options:
The server side. If you are using Firebase database just add the date of creation. Firebase documantation does not offer a method to get the creation date on the app side.
The app side. User user defaults, when the user login in the first time set the date for that user. When you get to the login screen again, check for existance. I would reccomend using the user id as the key.
For example:
Your user just logged in, you want to check if it the first time that he did:
if let displayName = FIRAuth.auth()?.currentUser?.displayName {
//Make sure we have the user
if UserDefaults.standard.bool(forKey: displayName) {
// try to get the user default for the spacific key
let wasConnected = UserDefaults.standard.bool(forKey: displayName)
if wasConnected {
print("This user was connected")
}
} else {
// This user was never connected
// We set the default to his ID
UserDefaults.standard.set(true, forKey: displayName)
UserDefaults.standard.synchronize()
}
}
To use the date, I think the easiest way is to convert the date to string.
Fiddle with the code to do exactly what you want.

How do I get the current user's name from Game Center

When the authenticated handler fires on return from Game Center, the local player is listed with displayName = "Me" and the alias is the player's username. However I'd like to display the user's full name instead, so want the actual displayName, not "Me".
Is there a way of specifying I want the full name, not "Me"?
I prefer showing the alias, especially when matching with random players but both the alias and the displayName require that the player's authentication be complete to start returning their appropriate values.
In order for the authentication process to start, you have to set the local player's authentication handler. Simply setting it starts the process and the method will be called within a few seconds. After that the local player's alias and displayName should be the right ones.
for example:
class YourGameCenterManager:GKGameCenterControllerDelegate,
GKLocalPlayerListener
{
var localGCAccount: GKLocalPlayer!
var active = false
init()
{
localGCAccount = GKLocalPlayer.localPlayer()
localGCAccount?.authenticateHandler = gameCenterAuthentication
}
func gameCenterAuthentication(gameCenterVC :UIViewController?, err:NSError?)
{
if gameCenterVC != nil
{
// Game center wants to display a sign-on view ...
// note: I personally never got this to actually happen
}
else if localGCAccount?.authenticated ?? false
{
if not(active)
{
active = true
localGCAccount?.unregisterAllListeners()
localGCAccount?.registerListener(self)
// ... whatever else you need to do when Game Center is ready
// at this point localGCAccount's alias and displayName should be ok
}
}
else if active
{
//... Game Center just went bad ... do what you have to to to handle it
active = false
}
}

Resources