Sinch video doen't want to work on iOS (Swift) - ios

So basically I want to enable Sinch Video in iOS application.
For testing purposes I've created SinchManaevger which is singleton and I instatiate it in AppDelegate:
class SinchManager: NSObject, SINClientDelegate, SINCallClientDelegate {
static let sharedInstance = SinchManager()
var client: SINClient?
func initSinchClientWithUserId(id: String) {
if client == nil {
if case .Authenticated(let currentUser, _) = SessionManager.sharedInstance.state.value {
self.client = Sinch.clientWithApplicationKey("xyz", applicationSecret: "xyz", environmentHost: "sandbox.sinch.com", userId: currentUser.username)
print("sinchClient")
print(client!)
self.client!.delegate = self
self.client!.setSupportCalling(true)
self.client!.enableManagedPushNotifications()
self.client!.start()
self.client!.startListeningOnActiveConnection()
}
}
}
func clientDidStart(client: SINClient!) {
print("clientDidStart")
self.client!.callClient().delegate = self
}
func clientDidStop(client: SINClient!) {
print("clientDidStop")
}
func clientDidFail(client: SINClient!, error: NSError!) {
print("clientDidFail")
}
func client(client: SINCallClient!, didReceiveIncomingCall call: SINCall!) {
print("didReceiveIncomingCall")
let sinchVC = SinchVC(username: currentUser.username)
let sinchNC = DNMMainNC(rootViewController: sinchVC)
sinchVC.call = call
}
}
And I've created Sinch ViewController which is initialized with username which will be called:
class SinchVC: UIViewController, SINCallDelegate {
private let videoController = SinchManager.sharedInstance.client!.videoController()
private let audioController = SinchManager.sharedInstance.client!.audioController()
private let callClient: SINCallClient
private var call: SINCall!
let username: String
private var mainView: SinchView { return view as! SinchView }
override func loadView() {
view = SinchView()
}
init(username: String) {
self.username = username
self.callClient = SinchManager.sharedInstance.client!.callClient()
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
call.delegate = self
self.mainView.videoView.addSubview(self.videoController.localView())
self.videoController.localView().contentMode = .ScaleToFill
if self.call.direction == SINCallDirection.Incoming {
self.audioController.startPlayingSoundFile(self.pathForSound("incoming.wav") as String, loop: true)
}
if self.call.details.videoOffered {
print("video offered")
self.mainView.videoView.addSubview(self.videoController.localView())
self.videoController.localView().contentMode = .ScaleToFill
}
mainView.videoView.addSubview(self.videoController.localView())
mainView.answerButton.addTarget(self, action: #selector(answer), forControlEvents: .TouchUpInside)
mainView.declineButton.addTarget(self, action: #selector(decline), forControlEvents: .TouchUpInside)
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.audioController.enableSpeaker()
}
func pathForSound(string: String) -> NSString {
let nsSt = NSBundle.mainBundle().resourcePath! as NSString
return nsSt.stringByAppendingPathComponent(string)
}
func answer() {
call.answer()
}
func decline() {
call.hangup()
}
func callDidEstablish(call: SINCall!) {
print("callDidEstablish")
}
func callDidEnd(call: SINCall!) {
print("callDidEnd")
}
func callDidProgress(call: SINCall!) {
print("callDidProgress")
self.audioController.startPlayingSoundFile(self.pathForSound("ringback.wav") as String, loop: true)
}
func callDidAddVideoTrack(call: SINCall!) {
print("callDidAddVideoTrack")
mainView.videoView.addSubview(self.videoController.remoteView())
}
}
Problem is when I try to call from my app to other phone with my app nothing happens (didReceiveIncomingCall delegate method doesn't get called at all)
If I try to call from my app to SinchVideo sample app then video call gets initiated normal. But when i call from SinchVideo app to my app nothing happens in my app. So probably i've forgot to add some notification or something to tell my app when the call is incoming. If you could help I would be very grateful. Thanks
EDIT: I managed to make didReceiveIncomingCall work but now call.answer isnt working. (nothing happens when call.answer is called and i see that my phone is ringing)

I am not sure what DNMMainNC does in your did recieve incoming call,
let sinchNC = DNMMainNC(rootViewController: sinchVC) What does DNMMainNC do?
sinchVC.call = call // private var?
But its looks kind of weird to set a private var call from your code, should that not be public or have a constructor like your init but with a call

Related

ios Swift Protocol Data

I don't use storyboards.
I want to send protocol data using #objc button action.
However, the sent view controller does not run the protocol function.
May I know what the reason is?
In fact, there's a lot more code.
Others work, but only protocol functions are not executed.
The didUpdataChampion function is
Data imported into a different protocol.
I have confirmed that there is no problem with this.
protocol MyProtocolData {
func protocolData(dataSent: String)
func protocolCount(dataInt: Int)
}
class PickViewController: UIViewController,ChampionManagerDelegate{
static let identifier = "PickViewController"
var count = 0
var urlArray = [URL]()
var pickDelegate : MyProtocolData?
override func viewDidLoad() {
super.viewDidLoad()
champions.riot(url: "myURL")
}
#objc func topHand(){
pickDelegate?.protocolData(dataSent: "top")
print(count)
pickDelegate?.protocoCount(dataInt: count)
let cham = ChampViewController()
cham.modalPresentationStyle = .fullScreen
present(cham, animated: true, completion: nil)
}
//Data imported to another protocol
func didUpdataChampion(_ championManager: ChampionManager, champion: [ChampionRiot]) {
print(#function)
count = champion.count
for data in champion {
let id = data.id
guard let url = URL(string: "https://ddragon.leagueoflegends.com/cdn/11.16.1/img/champion/\(id).png") else { return }
urlArray.append(url)
count = urlArray.count
}
}
func didFailWithError(error: Error) {
print(error)
}
}
class ChampViewController: UIViewController,MyProtocolData {
var pickData = ""
var arrayCount = 0
override func viewDidLoad() {
super.viewDidLoad()
}
func protocolData(dataSent: String) {
print(#function)
pickData = dataSent
print(pickData)
}
func protocoCount(dataInt: Int) {
print(#function)
arrayCount = dataInt
print(arrayCount)
}
}
i don't see full code, for instance how you call bind to topHand(), my advice is:
check that topHand - is called
check that pickDelegate isn't nil inside topHand
Create Object fo your PickViewController class and set its delegate to self.
var yourObj = PickViewController()
override func viewDidLoad() {
super.viewDidLoad()
yourObj.delegate = self
}

Calling function inside function in another function

I'm new in iOS Programming, and I had this problem. Let's say I have these two function:
class BaseViewController: UIViewController, ErrorMessageDelegate {
var uiView = UIView();
var viewErrorMessage:ErrorMessage!
func refresh(_sender: AnyObject) {
print("testing")
}
func getErrorMessage(message:String) {
super.viewDidLoad()
Dialog.dismiss()
ErrorMessage.message = message
viewErrorMessage = Bundle.main.loadNibNamed("ErrorMessage", owner: self, options: nil)?.first as! ErrorMessage
viewErrorMessage.delegate = self
self.view.addSubview(viewErrorMessage)
func removeSubView() {
viewErrorMessage.removeFromSuperview()
}
}
}
I want to call function removeSubView inside function refresh. I had to do that because I need to override refresh function to my subclass. And I need to put the function removeSubView in getErrorMessage because I should to. Does anyone know how to do that?
Please refer below code. It will help you to resolve the issue.
Code:
class BaseViewController: UIViewController, ErrorMessageDelegate {
var uiView = UIView();
var viewErrorMessage:ErrorMessage!
func refresh(_sender: AnyObject) {
removeSubView()
}
func getErrorMessage(message:String) {
super.viewDidLoad()
Dialog.dismiss()
ErrorMessage.message = message
viewErrorMessage = Bundle.main.loadNibNamed("ErrorMessage", owner: self, options: nil)?.first as! ErrorMessage
viewErrorMessage.delegate = self
self.view.addSubview(viewErrorMessage)
}
func removeSubView() {
viewErrorMessage.removeFromSuperview()
}
}
Yes, that is possible
func a() {
c()
}
func b() {
c()
}
func c() {
print("hello world")
}
no it is not possible - but I wonder why you would do that?

Customize FUIAuthPickerViewController

How can I customize the Firebase UI Auth Picker controller with custom buttons, custom actions, background, loader etc..
I already try to subclass the FUIAuthPickerViewController but we can't access to login buttons
This is how you can create your own class of FUIAuthPickerViewController:
Create FUICustomLoginController.swift with:
import UIKit
import FirebaseUI
import FirebaseAuth
class FUICustomLoginController: ViewController {
var authUI: FUIAuth! = FUIAuth.defaultAuthUI()
var auth: Auth = Auth.auth()
private func didSignIn(auth: AuthCredential?, error: Error?, callBack: AuthResultCallback?) {
let callBack: (AuthDataResult?, Error?) -> Void = { [unowned self] result, error in
callBack?(result?.user, error)
self.authUI.delegate?.authUI?(self.authUI, didSignInWith: result, error: error)
}
if let auth = auth {
self.auth.signInAndRetrieveData(with: auth, completion: callBack)
} else if let error = error {
callBack(nil, error)
}
}
func signIn<T: FUIAuthProvider>(type: T.Type, defaultValue: String? = nil) {
try? self.authUI.signOut() // logout from google etc..
self.authUI.providers.first(where: { $0 is T })?.signIn(withDefaultValue: defaultValue, presenting: self, completion: self.didSignIn)
}
}
Subclass your controller from FUICustomLoginController:
class LoginPickerController: FUICustomLoginController {
override func viewDidLoad() {
super.viewDidLoad()
// Customize authUI if needed
//self.authUI.providers = ...
self.authUI.delegate = self
}
#IBAction func loginFacebook(_ sender: Any) {
self.signIn(type: FUIFacebookAuth.self)
}
#IBAction func loginGoogle(_ sender: Any) {
self.signIn(type: FUIGoogleAuth.self)
}
#IBAction func loginPhone(_ sender: Any) {
self.signIn(type: FUIPhoneAuth.self)
}
}
extension LoginPickerController: FUIAuthDelegate {
func authUI(_ authUI: FUIAuth, didSignInWith authDataResult: AuthDataResult?, error: Error?) {
// perform login actions
}
}
You can customize the default buttons, add images etc.. (a working hack )
class SignInViewController: FUIAuthPickerViewController {
weak var delegate: signInProtocol?
// Unhashed nonce.
fileprivate var currentNonce: String?
var backgView: UIView?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .clear
for each in view.subviews[0].subviews[0].subviews[0].subviews {
if let button = each as? UIButton {
button.layer.cornerRadius = 20.0
button.layer.masksToBounds = true
///do any other button customization here
}
}
///add background image
let scrollView = view.subviews[0]
scrollView.backgroundColor = .clear
let contentView = scrollView.subviews[0]
contentView.backgroundColor = .clear
let background = UIImage(named: "imagename")
let backgroundImageView = UIImageView(image: background)
backgroundImageView.contentMode = .scaleToFill
view.insertSubview(backgroundImageView, at: 0)
}
}

Sinch Video calling sound is coming from front speaker

I have implemented sinch video calling in ios swift project i have followed all process given in sinch implementation document https://www.sinch.com/docs/video/ios/#calling. And i am successfully able to implement but i am getting on issue my video sound in coming from front speaker. how can i solve this problem?? Below my code:
var client: SINClient?
var sinCall : SINCall?
Configuring sinch
//MARK: Configuring Sinch Delegate
func configuringSinch(){
//Configuring Client Key
client = Sinch.client(withApplicationKey: Constants.SINCH_APP_KEY, applicationSecret: Constants.SINCH_PRIVATE_KEY, environmentHost: Constants.SANDBOX_ENVIRONMENT, userId: Utility().getUserId())
client?.call().delegate = self
client?.setSupportCalling(true)
client?.enableManagedPushNotifications()
client?.start()
client?.startListeningOnActiveConnection()
let vcCont = client?.videoController()
self.vwLocalView.addSubview((vcCont?.localView())!)
self.sinCall?.delegate = self
}
//MARK: Sinch Video Call Delegate
func clientDidStart(_ client: SINClient!) {
print("Client Did Start")
}
func clientDidFail(_ client: SINClient!, error: Error!) {
print("Client failed : \(error)")
player?.stop()
}
func clientDidStop(_ client: SINClient!) {
print("Client Did Stop")
player?.stop()
}
//MARK: Video Call Did Recieve
func client(_ client: SINCallClient!, didReceiveIncomingCall call: SINCall!) {
print("Did Recieve Incoming Call")
playRingtoneSound() // Playing Audio
call.delegate = self;
self.sinCall = call
}
//MARK: Call Did Add Video Track
func callDidAddVideoTrack(_ call: SINCall!) {
let videoCont = client?.videoController()
vwRemoteView.addSubview((videoCont?.remoteView())!)
}
func callDidEnd(_ call: SINCall!) {
sinCall?.hangup()
}
This is how you can manage SINAudioController to manage audio output.
func audioController() -> SINAudioController {
return (client?.audioController())!
}
//MARK: Video Call Did Recieve
func client(_ client: SINCallClient!, didReceiveIncomingCall call: SINCall!) {
audioController().enableSpeaker()
playRingtoneSound() // Playing Audio
call.delegate = self;
self.sinCall = call
}
// In SINCallDelegate
func callDidEstablish(_ call: SINCall!) {
//to disableSpeaker
audioController().disableSpeaker()
}
try this to manage AudioOutput Session manually
// MARK: AudioOutput Session
// to enable front speaker manually
func setSessionPlayerOn()
{
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord)
} catch _ {
}
do {
try AVAudioSession.sharedInstance().setActive(true)
} catch _ {
}
do {
try AVAudioSession.sharedInstance().overrideOutputAudioPort(AVAudioSessionPortOverride.none)
} catch _ {
}
}
// to enable speaker manually
func setSessionPlayerSpeaker()
{
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord)
} catch _ {
}
do {
try AVAudioSession.sharedInstance().setActive(true)
} catch _ {
}
do {
try AVAudioSession.sharedInstance().overrideOutputAudioPort(AVAudioSessionPortOverride.speaker)
} catch _ {
}
}
// to turnoff AudioOutput Session manually
func setSessionPlayerOff()
{
do {
try AVAudioSession.sharedInstance().setActive(false)
} catch _ {
}
}
Use this function
func callDidEstablish(_ call: SINCall!) {
let audio = APPDELEGATE.client?.audioController()
audio?.disableSpeaker()
// self.startCallDurationTimerWithSelector()
appDelegate.client?.audioController().stopPlayingSoundFile()
}
this is work for me.
class MainVC: UIViewController,SINCallDelegate {
// var client: SINClient?
private let videoController = SinchManager.sharedInstance.client!.videoController()
private let audioController = SinchManager.sharedInstance.client!.audioController()
private let callClient: SINCallClient
private var call: SINCall!
let username: String
#IBOutlet weak var otherView: UIView!
// private var mainView: SinchView { return view as! SinchView }
#IBAction func call_btn(_ sender: UIButton) {
answer()
}
#IBAction func end_btn(_ sender: UIButton) {
decline()
}
override func loadView() {
// view = SinchView()
view = otherView
}
init(username: String) {
self.username = username
self.callClient = SinchManager.sharedInstance.client!.call()
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
print("init(coder:) has not been implemented " + String(describing: aDecoder))
fatalError("init(coder:) has not been implemented " + String(describing: aDecoder))
}
override func viewDidLoad() {
super.viewDidLoad()
call.delegate = self
//self.mainView.videoView.addSubview(self.videoController.localView())
otherView.addSubview((self.videoController?.localView())!)
self.videoController?.localView().contentMode = .scaleToFill
if self.call.direction == SINCallDirection.incoming {
self.audioController?.startPlayingSoundFile(self.pathForSound(string: "incoming.wav") as String, loop: true)
}
if self.call.details.isVideoOffered {
print("video offered")
//self.mainView.videoView.addSubview(self.videoController.localView())
otherView.addSubview((self.videoController?.localView())!)
self.videoController?.localView().contentMode = .scaleToFill
}
otherView.addSubview((self.videoController?.localView())!)
// mainView.answerButton.addTarget(self, action: #selector(answer), forControlEvents: .TouchUpInside)
// mainView.declineButton.addTarget(self, action: #selector(decline), forControlEvents: .TouchUpInside)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.audioController?.enableSpeaker()
}
func pathForSound(string: String) -> NSString {
let nsSt = Bundle.main.resourcePath! as NSString
return nsSt.appendingPathComponent(string) as NSString
}
func answer() {
call.answer()
}
func decline() {
call.hangup()
}
func callDidEstablish(call: SINCall!) {
print("callDidEstablish")
let audio = SinchManager.sharedInstance.client!.audioController()
audio?.disableSpeaker()
// self.startCallDurationTimerWithSelector()
SinchManager.sharedInstance.client!.audioController().stopPlayingSoundFile()
}
func callDidEnd(call: SINCall!) {
print("callDidEnd")
}
func callDidProgress(call: SINCall!) {
print("callDidProgress")
self.audioController?.startPlayingSoundFile(self.pathForSound(string: "ringback.wav") as String, loop: true)
}
func callDidAddVideoTrack(call: SINCall!) {
print("callDidAddVideoTrack")
otherView.addSubview((self.videoController?.localView())!)
}

GoogleCast deviceDidComeOnline(device: GCKDevice!) never getting Called #GoogleCastSDK

Implemented GCKDeviceScannerListener Singleton Class on ViewController, however its delegate methods are not getting called even if Logger displays message of Cast Device that is available to connect with status code 1.
deviceDidComeOnline method of GCKDeviceScannerListener does not get called.
Could any one help please
class ViewController: UIViewController, GCKDeviceScannerListener, GCKDeviceManagerDelegate, GCKMediaControlChannelDelegate {
private var deviceScanner: GCKDeviceScanner!
private var selectedDevice:GCKDevice!
private var deviceManager:GCKDeviceManager!
private var mediaInformation:GCKMediaInformation!
private var kReceiverAppID = kGCKMediaDefaultReceiverApplicationID
override func viewDidLoad() {
super.viewDidLoad()
self.startScan()
}
func startScan() {
let filterCriteria = GCKFilterCriteria(forAvailableApplicationWithID: kReceiverAppID)
self.deviceScanner = GCKDeviceScanner(filterCriteria: filterCriteria)
if let deviceScanner = self.deviceScanner {
deviceScanner.addListener(self)
deviceScanner.startScan()
print("scanning started")
deviceScanner.passiveScan = true
}
}
// MARK: GCKDeviceScannerListener
func deviceDidComeOnline(device: GCKDevice!) {
print("deviceDidComeOnline()")
print("Device found: \(device.friendlyName)");
self.updateButtonStates()
}
func deviceDidGoOffline(device: GCKDevice!) {
print("deviceDidGoOffline()")
print("Device went away: \(device.friendlyName)");
self.updateButtonStates()
}
func deviceDidChange(device: GCKDevice!) {
print("deviceDidChange()");
}
}
Enter the ID that you receive after registering your App at Google Cast Registration
I have just used your code and it worked Perfect.
Don't use the default ID. It wouldn't work i.e
kGCKMediaDefaultReceiverApplicationID
let filterCriteria = GCKFilterCriteria(forAvailableApplicationWithID: kReceiverAppID)
Instead of it, Enter the ID to pass in the filter criteria and implement it like this.
let chromecastID = "ABC123" // Enter the correct ID here
let filterCriteria = GCKFilterCriteria(forAvailableApplicationWithID: chromecastID)

Resources