Live Streaming Video Call Chat Audio Call Chatbot Call SDK Video Call SDK
Video call technology is now plays a larger role within the customer service industry. There’s an old adage in customer service that a real person, whose smiling face the customer can see, always wins. Why not let technology deliver that smile to your customer’s face? video conferencing is predicted to be a top trend in 2019. Better, faster and cheaper - video conferencing has it all.
Get StartedWelcome to Live Chat
Please fill the details below before chatting with us
Customer Support
to start live chat.
is now online.
Your chat has ended
Ask more question by starting a new chat
Simply Practical
Call our API in a single line. We have been working hard to ensure the utmost practicality and ease.
import 'package:flutter/material.dart'; import 'package:nusa/newuniverse.dart'; class Home extends StatefulWidget { @override StatecreateState() { return new HomeState(); } } class HomeState extends State { final _channelController = TextEditingController(); bool _validateError = false; @override void initState() { super.initState(); _initialize(); } Future _initialize() async { _initNusa(); _addNusaEvent(); } Future _initNusa() async { // Change initiation with your credential here.. await Nusa.init('abcd_1234', 'tesa'); Nusa.bind(); } Future _addNusaEvent() async { Nusa.onAudioCallReceiver = (String originator, int state, String message) { Navigator.push( context, MaterialPageRoute( builder: (context) => SmartAudioCall(destination: originator, isInitiator: false))); }; Nusa.onVideoCallReceiver = (String originator, int state, String message) { Navigator.push( context, MaterialPageRoute(builder: (context) => VideoCall())); }; Nusa.onMessageCallback = (int messageId, int contentType, int status) { print( 'onMessageCallback -> messageId: $messageId, contentType: $contentType, status: $status'); Nusa.getMessage(messageId).then((f) { print('getMessage: $f'); }); }; Nusa.onMessageReceiver = (int messageId) { print('onMessageReceiver -> messageId: $messageId'); Nusa.getMessage(18109917689132).then((f) { print('getMessage: $f'); }); }; Nusa.onForumCallback = (String name, String message) { print('onForumCallback: $name/$message'); }; } @override void dispose() { _channelController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Nusa Example'), ), floatingActionButton: new Builder(builder: (BuildContext context) { return new FloatingActionButton( onPressed: () { Nusa.getForumDetail('5YfqTiDbKVQu').then((f) { print('f: $f'); }); }, child: new Icon(Icons.info), ); }), body: Center( child: Container( padding: EdgeInsets.symmetric(horizontal: 8), height: 400, child: Column( children: [ Row(children: []), Row(children: [ Expanded( child: TextField( controller: _channelController, decoration: InputDecoration( errorText: _validateError ? 'Destination is mandatory' : null, border: UnderlineInputBorder( borderSide: BorderSide(width: 1)), hintText: 'Destination'), )) ]), Padding( padding: EdgeInsets.symmetric(vertical: 8), child: Row( children: [ Expanded( child: RaisedButton( onPressed: () => _onInitiate(true), child: Text('Initiate'), color: Colors.blueAccent, textColor: Colors.white, ), ) ], )), Padding( padding: EdgeInsets.symmetric(vertical: 8), child: Row( children: [ Expanded( child: RaisedButton( onPressed: () => _onInitiate(false), child: Text('Join'), color: Colors.blueAccent, textColor: Colors.white, ), ) ], )) ], )), )); } _onInitiate(bool isInitiator) async { setState(() { _channelController.text.isEmpty ? _validateError = true : _validateError = false; }); if (_channelController.text.isNotEmpty) { // Common Video Call Navigator.push(context,MaterialPageRoute( builder: (context) => VideoCall(destination: _channelController.text))); /* Use code below for Smart Video Call */ // Navigator.push(context, MaterialPageRoute( // builder: (context) => SmartVideoCall( // destination: _channelController.text, // isInitiator: isInitiator))); } } void _showToast(BuildContext context, String status) { final scaffold = Scaffold.of(context); scaffold.showSnackBar( SnackBar( content: Text('User Status : ' + status), action: SnackBarAction( label: 'Close', onPressed: scaffold.hideCurrentSnackBar), ), ); } }
import 'package:flutter/material.dart'; import 'package:nusa/nusa.dart'; import 'package:nusa/widget/camera.dart'; import 'package:nusa/widget/remote.dart'; import 'dart:async'; class VideoCall extends StatefulWidget { final String destination; const VideoCall({Key key, this.destination}) : super(key: key); @override StatecreateState() => _VideoCallState(); } class _VideoCallState extends State { bool muted = false, camera = false, accept = false; final _infoStrings = []; var _videoCallIndex = []; String subTitle = ''; @override void initState() { super.initState(); initialize(); } @override void dispose() { Nusa.speakerPhone(false); Nusa.endVideoCall(); super.dispose(); } void initialize() { _bindNusa(); _addNusaEvent(); } Future _bindNusa() async { Nusa.bind(); } void _addNusaEvent() { Nusa.onError = (dynamic code) { print('onError $code'); }; Nusa.onFailed = (dynamic code) { print('onFailed $code'); }; Nusa.onSuccess = () async { print('onSuccess'); if (widget.destination != null) { Future.delayed(Duration(seconds: 1), () { Nusa.initiateVideoCall(widget.destination); }); } }; void _videoCallState(int state, [String userid, int index]) { switch (state) { case -3: // offline subTitle = 'Offline'; Future.delayed(Duration(seconds: 2), () { if (mounted) { Navigator.of(context).pop(); } }); break; case -4: // busy subTitle = 'Busy'; Future.delayed(Duration(seconds: 2), () { if (mounted) { Navigator.of(context).pop(); } }); break; case 0: // outgoing subTitle = 'Calling'; break; case 33: // ringing subTitle = 'Ringing'; break; case 32: // off hook subTitle = 'New Universe Video Call'; Future.delayed(Duration(seconds: 1), () { Nusa.speakerPhone(true); }); if (mounted) { setState(() { print("index vcall --> $index"); _videoCallIndex.add(index); var lgth = _videoCallIndex.length; print("panjang array --> $lgth"); }); } break; case 38: // end subTitle = 'End calling'; Future.delayed(Duration(seconds: 2), () { if (mounted) { setState(() { _videoCallIndex.remove(index); }); Navigator.of(context).pop(); } }); break; } } Nusa.onInitiateVideoCallback = (String destination, int state, String message) { if (mounted) { setState(() { String info = 'onInitiate: $destination:$state:$message'; _infoStrings.add(info); if (state == 32) { String userid = message.split(",")[1]; int index = int.parse(message.split(",")[2]); print('register index $userid $index'); _videoCallState(state, userid, index); } else { _videoCallState(state); } }); } }; Nusa.onAcceptVideoCallback = (String originator, int state, String message) { if (mounted) { setState(() { String info = 'onAccept: $originator:$state:$message'; _infoStrings.add(info); _videoCallState(state); }); } }; Nusa.onVideoCallReceiverTerminate = (String originator, int state, String message) { if (mounted) { setState(() { String info = 'onReceive: $originator:$state:$message'; _infoStrings.add(info); _videoCallState(state); }); } }; } Widget _cameraView() { return Container( height: 160, width: 120, child: Camera(), ); } Widget _remoteView() { return Container( child: Remote(), ); } Widget _remoteOtherView() { return Container( height: 160, width: 120, ); } Widget _toolbarOnGoing() { return Container( alignment: Alignment.bottomCenter, padding: EdgeInsets.symmetric(vertical: 48), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ RawMaterialButton( onPressed: () { setState(() { muted = !muted; }); Nusa.muteMicrophone(muted); }, child: new Icon( muted ? Icons.mic_off : Icons.mic, color: muted ? Colors.white : Colors.blueAccent, size: 20.0, ), shape: new CircleBorder(), elevation: 2.0, fillColor: muted ? Colors.blueAccent : Colors.white, padding: const EdgeInsets.all(12.0), ), RawMaterialButton( onPressed: () { Navigator.of(context).pop(); }, child: new Icon( Icons.call_end, color: Colors.white, size: 35.0, ), shape: new CircleBorder(), elevation: 2.0, fillColor: Colors.redAccent, padding: const EdgeInsets.all(15.0), ), RawMaterialButton( onPressed: () { setState(() { camera = !camera; }); Nusa.changeCamera(camera); }, child: new Icon( Icons.switch_camera, color: Colors.blueAccent, size: 20.0, ), shape: new CircleBorder(), elevation: 2.0, fillColor: Colors.white, padding: const EdgeInsets.all(12.0), ) ], ), ); } Widget _toolbarReceive() { return Container( alignment: Alignment.bottomCenter, padding: EdgeInsets.symmetric(vertical: 48), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ RawMaterialButton( onPressed: () { Navigator.of(context).pop(); }, child: new Icon( Icons.call_end, color: Colors.white, size: 20.0, ), shape: new CircleBorder(), elevation: 2.0, fillColor: Colors.redAccent, padding: const EdgeInsets.all(12.0), ), RawMaterialButton( onPressed: () { setState(() { accept = true; }); Nusa.acceptVideoCall(); }, child: new Icon( Icons.call, color: Colors.white, size: 20.0, ), shape: new CircleBorder(), elevation: 2.0, fillColor: Colors.blueAccent, padding: const EdgeInsets.all(12.0), ) ], ), ); } Widget _toolbar() { if (widget.destination != null) { return _toolbarOnGoing(); } else if (accept) { return _toolbarOnGoing(); } else { return _toolbarReceive(); } } TextEditingController addFriendTextFieldController = TextEditingController(); showAddRecipientDialog(BuildContext context) async { return showDialog( context: context, builder: (context) { return AlertDialog( title: Text('Add Call'), titleTextStyle: TextStyle(fontSize: 24, color: Colors.blueAccent), content: TextField( controller: addFriendTextFieldController, decoration: InputDecoration(hintText: "Add username to call"), ), actions: [ new FlatButton( child: new Text('CANCEL'), onPressed: () { Navigator.of(context).pop(); }, ), new FlatButton( child: new Text('CALL'), onPressed: () { String destination = addFriendTextFieldController.text; Future.delayed(Duration(seconds: 1), () { Nusa.initiateVideoCall(destination); }); // setState(() { // String destination = addFriendTextFieldController.text; // if(!destinationList.contains(destination)){ // destinationList.add(destination); // } // }); Navigator.of(context).pop(); }, ), ], ); }); } Widget _panel() { return Container( padding: EdgeInsets.symmetric(vertical: 48), alignment: Alignment.bottomCenter, child: FractionallySizedBox( heightFactor: 0.5, child: Container( padding: EdgeInsets.symmetric(vertical: 48), child: ListView.builder( physics: NeverScrollableScrollPhysics(), reverse: true, itemCount: _infoStrings.length, itemBuilder: (BuildContext context, int index) { if (_infoStrings.length == 0) { return null; } return Padding( padding: EdgeInsets.symmetric(vertical: 3, horizontal: 10), child: Row(mainAxisSize: MainAxisSize.min, children: [ Flexible( child: Container( padding: EdgeInsets.symmetric( vertical: 2, horizontal: 5), decoration: BoxDecoration( color: Colors.yellowAccent, borderRadius: BorderRadius.circular(5)), child: Text(_infoStrings[index], style: TextStyle(color: Colors.blueGrey)))) ])); })), )); } @override Widget build(BuildContext context) { return Stack( children: [ _remoteView(), Scaffold( appBar: AppBar( backgroundColor: Colors.transparent, title: Column( children: [ Text(widget.destination ?? ''), Text( subTitle, style: TextStyle(fontSize: 12.0), ) ], ), centerTitle: true, elevation: 0.0, actions: [ IconButton( onPressed: () => showAddRecipientDialog(context), icon: Icon(Icons.person_add), padding: EdgeInsets.all(0.0)) ], ), backgroundColor: Colors.transparent, body: Center( child: Stack( children: [ _cameraView(), Container( alignment: Alignment.centerLeft, child: Visibility( visible: true, child: _remoteOtherView(), ), ), Container( alignment: Alignment.centerRight, child: Visibility( visible: true, child: _remoteOtherView(), ), ), _panel(), _toolbar() ], )), ), ], ); } }
import 'dart:async'; import 'package:flutter/material.dart'; import 'package:nusa/nusa.dart'; import 'package:nusa/widget/board.dart'; import 'package:nusa/widget/camera.dart'; import 'package:nusa/widget/remote.dart'; class SmartVideoCall extends StatefulWidget { final String destination; final bool isInitiator; const SmartVideoCall({Key key, this.destination, this.isInitiator = true}) : super(key: key); @override StatecreateState() => _SmartVideoCallState(); } class _SmartVideoCallState extends State { bool muted = false, camera = false, accept = false; final _infoStrings = []; String subTitle = ''; @override void initState() { super.initState(); initialize(); } @override void dispose() { Nusa.endVideoCall(); super.dispose(); } void initialize() { _bindNusa(); _addNusaEvent(); } Future _bindNusa() async { Nusa.bind(); } void _addNusaEvent() { Nusa.onError = (dynamic code) { print('onError $code'); }; Nusa.onFailed = (dynamic code) { print('onFailed $code'); }; Nusa.onSuccess = () async { print('onSuccess'); if (widget.isInitiator) { Future.delayed(Duration(seconds: 1), () { Nusa.initiateVideoCall(widget.destination); Nusa.whiteboardInit(widget.destination); }); } else { Nusa.startNotification(title: "Incoming Video Call", text:"Incoming Video Call", vibrate: true, playRingtone: true); } }; void _videoCallState(int state) { switch (state) { case -3: // offline subTitle = 'Offline'; Nusa.stopNotification(); Future.delayed(Duration(seconds: 2), () { if (mounted) { Navigator.of(context).pop(); } }); break; case -4: // busy subTitle = 'Busy'; Nusa.stopNotification(); Future.delayed(Duration(seconds: 2), () { if (mounted) { Navigator.of(context).pop(); } }); break; case 0: // outgoing subTitle = 'Calling'; break; case 33: // ringing // Nusa.playRingtone(); // rbt subTitle = 'Ringing'; break; case 32: // off hook subTitle = 'New Universe Video Call'; Nusa.stopNotification(); Future.delayed(Duration(seconds: 1), () { Nusa.speakerPhone(true); }); break; case 38: // end subTitle = 'End calling'; Nusa.stopNotification(); Future.delayed(Duration(seconds: 2), () { if (mounted) { Navigator.of(context).pop(); } }); break; } } Nusa.onInitiateVideoCallback = (String destination, int state, String message) { if (mounted) { setState(() { String info = 'onInitiate: $destination:$state:$message'; _infoStrings.add(info); _videoCallState(state); }); } }; Nusa.onAcceptVideoCallback = (String originator, int state, String message) { if (mounted) { setState(() { String info = 'onAccept: $originator:$state:$message'; _infoStrings.add(info); _videoCallState(state); }); } }; Nusa.onVideoCallReceiverTerminate = (String originator, int state, String message) { if (mounted) { setState(() { String info = 'onReceive: $originator:$state:$message'; _infoStrings.add(info); _videoCallState(state); }); } }; } Widget _cameraView() { return Container( height: 160, width: 120, child: Camera(), ); } Widget _remoteView() { return Container( child: Remote(), ); } Widget _toolbarOnGoing() { return Container( alignment: Alignment.bottomCenter, padding: EdgeInsets.symmetric(vertical: 48), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ RawMaterialButton( onPressed: () { setState(() { muted = !muted; }); Nusa.muteMicrophone(muted); }, child: new Icon( muted ? Icons.mic_off : Icons.mic, color: muted ? Colors.white : Colors.blueAccent, size: 20.0, ), shape: new CircleBorder(), elevation: 2.0, fillColor: muted ? Colors.blueAccent : Colors.white, padding: const EdgeInsets.all(12.0), ), RawMaterialButton( onPressed: () { Nusa.stopNotification(); Nusa.stopRingbackTone(); Navigator.of(context).pop(); }, child: new Icon( Icons.call_end, color: Colors.white, size: 35.0, ), shape: new CircleBorder(), elevation: 2.0, fillColor: Colors.redAccent, padding: const EdgeInsets.all(15.0), ), RawMaterialButton( onPressed: () { setState(() { camera = !camera; }); Nusa.changeCamera(camera); }, child: new Icon( Icons.switch_camera, color: Colors.blueAccent, size: 20.0, ), shape: new CircleBorder(), elevation: 2.0, fillColor: Colors.white, padding: const EdgeInsets.all(12.0), ) ], ), ); } Widget _toolbarReceive() { return Container( alignment: Alignment.bottomCenter, padding: EdgeInsets.symmetric(vertical: 48), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ RawMaterialButton( onPressed: () { Nusa.stopNotification(); // Nusa.stopRingtone(); Navigator.of(context).pop(); }, child: new Icon( Icons.call_end, color: Colors.white, size: 20.0, ), shape: new CircleBorder(), elevation: 2.0, fillColor: Colors.redAccent, padding: const EdgeInsets.all(12.0), ), RawMaterialButton( onPressed: () { setState(() { accept = true; }); Nusa.acceptVideoCall(); Nusa.whiteboardJoin(widget.destination); }, child: new Icon( Icons.call, color: Colors.white, size: 20.0, ), shape: new CircleBorder(), elevation: 2.0, fillColor: Colors.blueAccent, padding: const EdgeInsets.all(12.0), ) ], ), ); } Widget _toolbar() { if (widget.isInitiator) { return _toolbarOnGoing(); } else if (accept) { return _toolbarOnGoing(); } else { return _toolbarReceive(); } } Widget _panel() { return Container( padding: EdgeInsets.symmetric(vertical: 48), alignment: Alignment.bottomCenter, child: FractionallySizedBox( heightFactor: 0.5, child: Container( padding: EdgeInsets.symmetric(vertical: 48), child: ListView.builder( physics: NeverScrollableScrollPhysics(), reverse: true, itemCount: _infoStrings.length, itemBuilder: (BuildContext context, int index) { if (_infoStrings.length == 0) { return null; } return Padding( padding: EdgeInsets.symmetric(vertical: 3, horizontal: 10), child: Row(mainAxisSize: MainAxisSize.min, children: [ Flexible( child: Container( padding: EdgeInsets.symmetric( vertical: 2, horizontal: 5), decoration: BoxDecoration( color: Colors.yellowAccent, borderRadius: BorderRadius.circular(5)), child: Text(_infoStrings[index], style: TextStyle(color: Colors.blueGrey)))) ])); })), )); } @override Widget build(BuildContext context) { return Stack( children: [ _remoteView(), Scaffold( appBar: AppBar( backgroundColor: Colors.transparent, title: Column( children: [ Text(widget.destination ?? ''), Text( subTitle, style: TextStyle(fontSize: 12.0), ) ], ), centerTitle: true, elevation: 0.0, ), backgroundColor: Colors.transparent, body: Center( child: Stack( children: [ _cameraView(), _panel(), Board( backgroundColor: Colors.transparent, penColor: Colors.white), _toolbar() ], )), ), ], ); } }
FLUTTER 4
//repository repositories { google() jcenter() maven { url "http://192.168.0.6:8040/artifactory/libs-release-local" credentials { username = "${artifactory_username}" password = "${artifactory_password}" } } } //dependencies dependencies { implementation 'io.newuniverse:api:1.0.0' }
# Project-wide Gradle settings. # IDE (e.g. Android Studio) users: # Gradle settings configured through the IDE *will override* # any settings specified in this file. # For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. org.gradle.jvmargs=-Xmx1536m # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true # AndroidX package structure to make it clearer which packages are bundled with the # Android operating system, and which are packaged with your app's APK # https://developer.android.com/topic/libraries/support-library/androidx-rn android.useAndroidX=true # Automatically convert third-party libraries to use AndroidX android.enableJetifier=true # Kotlin code style for this project: "official" or "obsolete": kotlin.code.style=official artifactory_username=universe artifactory_password=AP6yjFzMDSCUqAX2f2inpXoTUog
package io.newuniverse.luna import android.Manifest import android.content.Intent import android.content.pm.PackageManager import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import io.newuniverse.nusdk.core.NuSDK import io.newuniverse.nusdk.video.VideoCallActivity import kotlinx.android.synthetic.main.video_call_example.* class VideoCallExample : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.video_call_example) NuSDK.init("abcd_1234", "yayandw") bind() NuSDK.registerVideoCallReceiver { var1, var2, var3, var4 -> val intent: Intent = Intent(var1, VideoCallActivity::class.java) .putExtra("Originator", var2) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) var1.startActivity(intent) } start.setOnClickListener { val intent = Intent(this, VideoCallActivity::class.java) .putExtra("Destination", "tesa") startActivity(intent) } } private var permissions = arrayOf( Manifest.permission.CAMERA, Manifest.permission.READ_PHONE_STATE, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.MODIFY_AUDIO_SETTINGS ) private fun isAllowPermission(): Boolean { for (permission in permissions) { if (ContextCompat.checkSelfPermission( this, permission ) != PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions(this, permissions, 1) return false } } return true } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (!isAllowPermission()) { finish() return } bind() } private fun bind() { if (ActivityCompat.checkSelfPermission( this, Manifest.permission.READ_PHONE_STATE ) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission( this, Manifest.permission.WRITE_EXTERNAL_STORAGE ) != PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions(this, permissions, 1) return } NuSDK.bind(this, object : NuSDK.BindListener { override fun success() { } override fun failed(sMessage: String) { } }) } }
NATIVE 4