Multiple user Video Call using WebRTC SDK Directly - ios

Hi I am working on a Video Call Solution by using WebRTC directly. I have achieved 1-1 video call using firebase as Signaling service and using default google ICE Servers.
Core Req: Multiple users with in a Room using WebRTC at least 4 users using the default ice/stun servers available. I'm using pod 'GoogleWebRTC'
Issue comes when multiple users joins the same room ID.
So, I am maintaining Peerconnection reference as this
var peerConnection: RTCPeerConnection! = nil
When a new user i.e., remote user joins I set its description as below
self.peerConnection.setRemoteDescription(offer, completionHandler: {(error: Error?) in
if error == nil {
LOG("setRemoteDescription(offer) succsess")
self.makeAnswer() // Create Answer if setRemoteDescription succeeds
} else {
LOG("setRemoteDescription(offer) ERROR: " + error.debugDescription)
}
})
What I feel ? Issue is when third user joins again I set the remote Description with above mentioned code which makes my previous video stops to render sometimes or most of the times.
I looked for solutions and found need to maintain multiple peer connection references, but how? Any help with my requirement will be appreciated.
Just give me clue or sample code will be really great.

In case of multiple user call you should have multiple peerconnections, because it's isn't possible to set different sdps to one pc.
So you can use something like this
var peerConnectionMap = [String: RTCPeerConnection]()
Where String here is some constant user id.
When new user is joined to the room, then you create new pc and store it in this dictionary. Then you exchange with sdps as usual.
Don't forget that you should reuse local audio-video track created when first peerconnection is created.

Related

iOS 11.4 not asking Privacy Usage ( Privacy - Motion Usage Description has been set )

I'm stumped, iOS 11.4 ( 15F79 ), iPhone 6. Cannot get the App to Ask for Motion Data. info.plist has been set via the editor and double checked via the info.plist open in textWrangler, Also deleted key and saved via textWrangler.
<key>NSMotionUsageDescription</key>
<string>This app needs your Phones motion manager to update when the phone is tilted. Please allow this App to use your phones tilt devices</string>
I have deleted then reinstalled the app about 10 times. I have restared the phone 5 times. I have checked through settings and my app does NOT show up in Privacy-Motion and Fitness or anywhere else in settings. I am using a free developer account, maybe that has something to do with it?
I created a new Xcode game template and changed nothing apart from importing CoreMotion and this code
**** Edited, sorry I forgot to say I had started the instance, just forgot to put it here, just in case someone thinks that's the problem ************
let motionManager = CMMotionManager()
override func didMove(to view: SKView) {
motionManager.startDeviceMotionUpdates()
if motionManager.isDeviceMotionActive == true {
motionManager.accelerometerUpdateInterval = 0.2
motionManager.startAccelerometerUpdates(to: OperationQueue.current!, withHandler: {
(accelerometerData: CMAccelerometerData!, error: NSError!) in
let acceleration = accelerometerData.acceleration
print(accelerometerData)
} as! CMAccelerometerHandler)
}else{
print(CMMotionActivityManager.authorizationStatus().rawValue)
}
which prints a 0 ( an Enum - case not determined ) to the console.
In my actual app it was a 3 ( same Enum - case Denied ).
As I've said, I have uninstalled, reinstalled, edited plist via Xcode and text wrangler ( a code editor ) , tried different versions of the code above, tried the code in different places ( in did move to view, in class )tried code off apple docs. etc.... I haven't been asked the NSUsage question and the App keeps crashing.
I have looked for ways to get the Alert fired up, As in CLLocationManager.requestWhenInUseAuthorization() but I cannot find a comparable CMMotion version ( I don't think there is one. ) I have created a new swift file , imported Foundation and CMMotion and just put that code there, But still no Alert asking for Motion Data.
I tried a single view app template instead of a game template thinking that might be the issue, Nope.
What do I do?
Any help Appreciated. Thanks
You are confusing two related but different classes.
CMMotionManager gives access to accelerometer, magnetometer and gyroscope data. It does not require any user permission as this information is not considered privacy related.
In your else clause you are checking the authorisation status of CMMotionActivityManager. This object reports the device motion type (walking, running, driving). This information is considered privacy related and when you create an instance of this class and request data from it, the permissions alert is displayed.
The reason your else is being triggered is because you are checking isDeviceMotionActive; this will be false until you call startDeviceMotionUpdates, which you never do. Even if you used isAccelerometerActive you would have a problem because you call startAccelerometerUpdates in the if clause which will never be reached.
You probably meant to check isAccelerometerAvailable. If this returns false then there isn't much you can do; the device doesn't have an accelerometer.
Update
It doesn't make sense to check isDeviceMotionActive immediately after calling startDeviceMotion:
You know it's active; you just started it
I imagine the start up takes some time, so you could expect to get false if you check immediately.
Apple recommends that you do not have more than one observer in place for each motion device type, so the purpose of check the is...Active to ensure you don't call start... again if you have already done so.
If you only want gyroscope data then you don't need to call startDeviceMotionUpdates at all.

Trying to use Realm Object Server Tutorial

I have created an Amazon Web Services EC2 instance and deploy one of the AMIs with a Realm Object Server as its documentation explains:
https://realm.io/docs/realm-object-server/#install-realm-object-server
Once installed and created my admin user, I have completed the iOS tutorial: https://realm.io/docs/tutorials/realmtasks/, just until point 7, enough for creating task, but when I add new task in app, nothing happens. Debugging, I notice that next sentence try, is not executing:
let items = self.items
try! items.realm?.write {
items.insert(Task(value: ["text": text]), at: items.filter("completed = false").count)
}
The items collection seems to be initialized properly:
In the ROS dashboard, can see the database referenced in Xcode:
In image can be see "Default permissions" property is no access, is this the reason of not creating new task? If so, how can I change that permissions? If that is not the reason, anyone could help me?
thanks in advance
The problem was that I did not follow al the complete tutorial because I do not want to use the desktop application, just mobile example, but realm init objects in desktop app, so I never got a valid realm where perform actions.
For a quick and simple start with this realm tutorial pointing to an online server, not local, you must initialize the TaskList object and add it to self.realm on setup
// Show initial tasks
func updateList() {
if self.realm.objects(TaskList.self).count == 0 {
let list = TaskList()
list.id = "000001"
list.text = "lista de prueba"
// Add to the Realm inside a transaction
try! self.realm.write {
self.realm.add(list)
}
}
if self.items.realm == nil, let list = self.realm.objects(TaskList.self).first {
self.items = list.items
}
self.tableView.reloadData()
}
checking if there is not a TaskList with if self.realm.objects(TaskList.self).count == 0 {, you can create one and init realm.
You probably forgot to launch Mac demo app first or login with a different user. The tutorial assumes that existing data will be synced at login. If you have never launched the Mac app or logged in a different user, it may happen that items are not managed by Realm.
The tutorial says the following:
First, please follow the Get Started instructions to get set up with the Realm Mobile Platform and to launch the macOS version of RealmTasks.
Also, you attempt to try this tutorial with ROS on AWS. The tutorial assumes running ROS on a same local machine.
So you should modify the Mac app code to connect to the AWS, then run it to synchronize the initial data. Then run the tutorial iOS app.
The default permissions here show whether all other users can access the Realm or not, which isn't the case here. We already have an internal issue around clarifying this.
The registered user who owns the Realm has individual permissions to it by default. If you wouldn't have permissions opening the synchronized Realm from the client would also fail because of insufficient permissions, so this isn't the problem here.
So going back to your code:
try! items.realm?.write { … }
My guess would be that the problem here is that the collection isn't already attached to a Realm, so that items.realm? evaluates to null. In that case the write transaction wouldn't be executed.
You can resolve this by making sure to add the items first to a Realm or executing the write directly on a synchronized Realm.

Firebase Offline Store - Query not returning changes in online store

I’m using Firebase with the offline ability set to true.
let ref = FIRDatabase.database().referenceWithPath(“my data”).child(“my users id”)
scoresRef.keepSynced(true)
This path also has keep Synced set to true, as with out this with changes in the database are not seen within the app immediately as it is using the local cache.
I have another top level node / path in my app that I want to search - containing other users.
I want to use a singleEvent query and find an email address, I’m doing this via
studios.queryOrderedByChild("email").queryEqualToValue(email).observeSingleEventOfType(.Value, withBlock: { snapshot in // etc
I am able to find the node, however I keep getting the local cached version and not the most recent one in the firebase online store.
If I make some changes to the node online, I don’t get these back within the fetch.
If I changed my fetch to a monitor type i.e.
studios.queryOrderedByChild("email").queryEqualToValue(email).observeEventType(.Value, withBlock: { snapshot in // etc
I get the local cache node first, then get the online updated version as well.
I would rather use the SingleEvent fetch, but I don’t want to monitor the users entire node with keepSynced as it is a high level node and I don’t want to keep all that data locally, as its not directly related to the user.
One fix I found was prior to the single query was add .keepSynced(true) and in the completion block add .keepSynced(false). I'm not sure how much of the node is downloaded this was and may as well use the monitor fetch rather than the singleEvent.
Should I just use the monitorEvent or is there a better way to use SingleEventFetch that goes to the online store and instead of just returning my local node.
PS I am online and this is confirmed via
var connectedRef = FIRDatabase.database().referenceWithPath(".info/connected")
connectedRef.observeEventType(.Value, withBlock: { snapshot in
let connected = snapshot.value as? Bool
if connected != nil && connected! {
println("Connected")
} else {
println("Not connected")
}
})
Thanks

For plug in running on iOS

What I want to implement is as follow:
A-app (calling app) : request the return value of a-string sent as parameter : request(a-string) -> b-string.
B-app (plug-in installed separately by me or others, it plays the role of dictionary or database ) : search a-string from database and return the result (b-string).
With successful experiences of plug-in on android and with Apple's confident rhetoric of plug-in, I thought plug-in, of course, run on iOS. After a lot of hard work, however, I finally found out:
* Note : The creation and use of loadable bundles is not supported in iOS.*
Nonetheless, not giving up, I finally made it with custom URl and pasteboard:
A-app : write a-string and false state to pasteboard & call B-app via custom URL.
B-app : viewDidLoad runs following func and thereafter exit program ; func { read pasteboard and search from database & write the result(b-string) and true state to pasteboard }
A-app : while-loop detects whether state is false or true. if true, catch b-string from pasteboard.
Anyway it works but it's too long thus almost useless. Do you have any idea for better solutions? Why doesn't Apple allow plug-in for iOS? Any responses are welcome. Thank you.
I can't answer why Apple doesn't allow plug-ins, but I can offer some advice on what you're trying to achieve.
The common pattern for sending data back to your application is to implement a callback url, so the A-app would also implement a custom URI and add that to the uri sent to B-app.
B-app would then process the uri as you have already implemented, but then instead of exiting, it simply sends the data you requested in the uri passed to it.
See http://x-callback-url.com for more details and example implementations.

Gracenote API - No track link data

Currently, in my AppDelegate, I have an instance variable declared for GNConfig that is set up with all properties I would like to receive.
This instance of GNconfig is used by any class that makes a gracenote request.
The requests I am using are recognition from an audio stream, recognition by local file and a text search which populates an array. The array is then used for track lookups by id for the corresponding array item.
I am able to get all the content I need, except for track and album link data (always returns null).
I have tried plenty of different suggestions and guides with no luck.
Could somebody please help me out? This data is essential to my app and my app is pretty much complete except for this big obstacle.
Thanks in advance.
** edit **
This is in my appDelegate:
_gnConfig = [GNConfig init:#"XXXXXXX-XXXXXXXXXXXXXXXXXXXXXXX"];
[_gnConfig setProperty:#"content.coverArt" value:#"1"];
[_gnConfig setProperty:#"content.coverArt.sizePreference" value:#"LARGE"];
[_gnConfig setProperty:#"content.allowFullResponse" value:#"1"];
I have this in one of my class methods:
NSURL *filePath = [item valueForProperty:MPMediaItemPropertyAssetURL];
[GNOperations recognizeMIDFileFromFile:self config:[[AppDelegate sharedDelegate] gnConfig] fileUrl:filePath];
In the delegate method I have:
gracenoteResponseItem = [result bestResponse];
NSLog("%#", [gracenoteResponseItem trackLinkData]);
Some tracks may not have link data available.
Also if you are doing a local lookup then you will have to set this config option:
[publicProperties setObject:#“1"forKey:#"content.allowfullresponse"];
Unless you have explicitly had your client ID entitled for Link IDs (aka 'external' or '3rd party' IDs), you won't get any in your responses.
By default, Gracenote Open Developer client IDs aren't entitled for any external IDs. You need to coordinate with Gracenote to entitle your client ID to start receiving the desired IDs.

Resources