Live Streaming Video Call Chat Audio Call Chatbot Call SDK Video Call SDK
With the available voice call features in, your business can resolve issues faster, measure and improve phone support operations, and deliver better customer experience across every channel. It’s easy to set without hiring additional technicians, or managing new vendors.
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 Audio Call Navigator.push(context, MaterialPageRoute( builder: (context) => AudioCall(destination: _channelController.text))); /* Use code below for Smart Audio Call */ // Navigator.push( context, MaterialPageRoute( // builder: (context) => SmartAudioCall( // 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 'dart:async'; import 'package:flutter/material.dart'; import 'package:nusa/newuniverse.dart'; import 'package:nusa/widget/timer_controller.dart'; class AudioCall extends StatefulWidget { final String destination; final bool isInitiator; final VoidCallback onAddCall; const AudioCall( {Key key, this.destination, this.isInitiator = true, this.onAddCall}) : super(key: key); @override StatecreateState() => _AudioCallState(); } class _AudioCallState extends State { var muted = false, speaker = false, accept = false; final _infoStrings = []; var title = ''; var controller = TimerController(); List destinationList = []; var pendingCall = ''; @override void initState() { super.initState(); destinationList = [widget.destination ?? "???"]; initialize(); controller.addListener(() { setState(() { title = controller.value; }); }); } @override void dispose() { Nusa.endAudioCall(); controller.dispose(); 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) { Nusa.initiateAudioCall(widget.destination); } }; void _audioCallState(int state, [String userid, int index]) { switch (state) { case -3: // offline title = 'Person is offline'; Future.delayed(Duration(seconds: 2), () { if (mounted) { if (destinationList.length > 1) { destinationList.remove(pendingCall); } else Navigator.of(context).pop(); } }); break; case -4: // busy title = 'Person is busy'; Future.delayed(Duration(seconds: 2), () { if (mounted) { if (destinationList.length > 1) { destinationList.remove(pendingCall); } else Navigator.of(context).pop(); } }); break; case 0: // outgoing title = 'Calling'; break; case 23: // ringing title = 'Ringing'; break; case 22: // off hook title = 'Connected'; controller.start(); Nusa.registerConferenceVideoCallIndex(userid, index); break; case 28: // end controller.stop(); title = 'End calling'; Future.delayed(Duration(seconds: 2), () { if (mounted) { Navigator.of(context).pop(); } }); break; } } Nusa.onInitiateAudioCallback = (String destination, int state, String message) { if (mounted) { setState(() { String info = 'onInitiate: $destination:$state:$message'; _infoStrings.add(info); if (!destinationList.contains(destination)) { destinationList.add(destination); } if (state == 22) { String userid = message.split(",")[1]; int index = int.parse(message.split(",")[2]); print('register index $userid $index'); _audioCallState(state, userid, index); } else { _audioCallState(state); } }); } }; Nusa.onAcceptAudioCallback = (String originator, int state, String message) { if (mounted) { setState(() { String info = 'onAccept: $originator:$state:$message'; _infoStrings.add(info); if (state == 22) { if (!destinationList.contains(originator)) { destinationList.add(originator); } String userid = message.split(",")[1]; int index = int.parse(message.split(",")[2]); print('register index $userid $index'); _audioCallState(state, userid, index); } else { _audioCallState(state); } }); } }; Nusa.onAudioCallReceiverTerminate = (int state, String message) { if (mounted) { setState(() { String info = 'onReceive: $state:$message'; _infoStrings.add(info); _audioCallState(state); }); } }; } Widget _profile() { return Center( child: Column( children: [ Flexible( child: Padding( padding: EdgeInsets.all(16), child: CircleAvatar( radius: MediaQuery.of(context).size.width * 0.4, backgroundImage: NetworkImage( "https://www.woolha.com/media/2019/06/buneary.jpg"), ), )), Text( (destinationList != null && destinationList.length > 0) ? destinationList .reduce((value, element) => value + ", " + element) : '???', // (widget.destination ?? ''), style: TextStyle(fontSize: 24, color: Colors.black87), ) ], ), ); } 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(() { speaker = !speaker; }); Nusa.speakerPhone(speaker); }, child: new Icon( speaker ? Icons.volume_up : Icons.volume_off, color: speaker ? Colors.white : Colors.blueAccent, size: 20.0, ), shape: new CircleBorder(), elevation: 2.0, fillColor: speaker ? Colors.blueAccent : 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.acceptAudioCall(); }, 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)))) ])); })), )); } Widget _members() { return Container( alignment: Alignment.bottomCenter, padding: EdgeInsets.symmetric(vertical: 160), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: destinationList .skip(1) .map((f) => CircleAvatar( radius: 36, backgroundImage: NetworkImage( "https://www.woolha.com/media/2019/06/buneary.jpg"))) .toList(), ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( iconTheme: IconThemeData(color: Colors.black54), title: Text( title, style: TextStyle(color: Colors.black54), ), backgroundColor: Colors.transparent, centerTitle: true, elevation: 0.0, actions: [ IconButton( onPressed: widget.onAddCall, icon: Icon(Icons.person_add), padding: EdgeInsets.all(0.0)) ], ), backgroundColor: Colors.white, body: Center( child: Stack( children: [_profile(), _panel(), _members(), _toolbar()], )), ); } }
import 'dart:async'; import 'package:flutter/material.dart'; import 'package:nusa/newuniverse.dart'; import 'package:nusa/widget/timer_controller.dart'; class SmartAudioCall extends StatefulWidget { final String destination; final bool isInitiator; final VoidCallback onAddCall; const SmartAudioCall( {Key key, this.destination, this.isInitiator = true, this.onAddCall}) : super(key: key); @override StatecreateState() => _SmartAudioCallState(); } class _SmartAudioCallState extends State { var muted = false, speaker = false, accept = false, receiveSS = false; final _infoStrings = []; var title = ''; var controller = TimerController(); List destinationList = []; var pendingCall = ''; @override void initState() { super.initState(); destinationList = [widget.destination ?? "???"]; initialize(); controller.addListener(() { setState(() { title = controller.value; }); }); } @override void dispose() { Nusa.endAudioCall(); Nusa.endScreenSharing(); controller.dispose(); super.dispose(); } void initialize() { _bindNusa(); _addNusaEvent(); } Future _bindNusa() async { Nusa.bind(); } void _audioCallState(int state, [String userid, int index]) { switch (state) { case -3: // offline title = 'Person is offline'; Nusa.stopNotification(); Future.delayed(Duration(seconds: 2), () { if (mounted) { if (destinationList.length > 1) { destinationList.remove(pendingCall); } else Navigator.of(context).pop(); } }); break; case -4: // busy title = 'Person is busy'; Nusa.stopNotification(); Future.delayed(Duration(seconds: 2), () { if (mounted) { if (destinationList.length > 1) { destinationList.remove(pendingCall); } else Navigator.of(context).pop(); } }); break; case 0: // outgoing title = 'Calling'; break; case 23: // ringing Nusa.playRingbackTone(); // rbt title = 'Ringing'; break; case 22: // off hook title = 'Connected'; controller.start(); Nusa.stopNotification(); break; case 28: // end controller.stop(); title = 'End calling'; Nusa.stopNotification(); Future.delayed(Duration(seconds: 2), () { if (mounted) { Navigator.of(context).pop(); } }); break; } } void _screenSharingState(int state) { switch (state) { case 88: setState(() { receiveSS = false; }); break; } } void _addNusaEvent() { Nusa.onError = (dynamic code) { print('onError $code'); }; Nusa.onFailed = (dynamic code) { print('onFailed $code'); }; Nusa.onSuccess = () async { print('onSuccess'); if (widget.isInitiator) { Nusa.initiateAudioCall(widget.destination); } else { Nusa.startNotification(title: "Incoming Call", text:"Incoming Call", vibrate: true, playRingtone: true); } Nusa.registerScreenSharingReceiver(); }; Nusa.onInitiateAudioCallback = (String destination, int state, String message) { if (mounted) { setState(() { String info = 'onInitiate: $destination:$state:$message'; _infoStrings.add(info); if (!destinationList.contains(destination)) { destinationList.add(destination); } if (state == 22) { String userid = message.split(",")[1]; int index = int.parse(message.split(",")[2]); print('register index $userid $index'); _audioCallState(state, userid, index); } else { _audioCallState(state); } }); } }; Nusa.onAcceptAudioCallback = (String originator, int state, String message) { if (mounted) { setState(() { String info = 'onAccept: $originator:$state:$message'; _infoStrings.add(info); if (state == 22) { if (!destinationList.contains(originator)) { destinationList.add(originator); } String userid = message.split(",")[1]; int index = int.parse(message.split(",")[2]); print('register index $userid $index'); _audioCallState(state, userid, index); } else { _audioCallState(state); } }); } }; Nusa.onAudioCallReceiverTerminate = (int state, String message) { if (mounted) { setState(() { String info = 'onReceive: $state:$message'; _infoStrings.add(info); _audioCallState(state); }); } }; Nusa.onInitiateScreenCallback = (int state, String message) { if (mounted) { setState(() { String info = 'onInitiate: $state:$message'; _infoStrings.add(info); _screenSharingState(state); }); } }; Nusa.onJoinScreenCallback = (int state, String message) { if (mounted) { setState(() { String info = 'onJoin: $state:$message'; _infoStrings.add(info); _screenSharingState(state); }); } }; Nusa.onScreenSharingReceiver = (String originator) { if (mounted) { setState(() { String info = 'onReceive: $originator'; _infoStrings.add(info); receiveSS = true; }); } }; } Widget _profile() { return Center( child: Column( children: [ Flexible( child: Padding( padding: EdgeInsets.all(16), child: CircleAvatar( radius: MediaQuery.of(context).size.width * 0.4, backgroundImage: NetworkImage( "https://www.woolha.com/media/2019/06/buneary.jpg"), ), )), Text( // (destinationList != null && destinationList.length > 0) // ? destinationList // .reduce((value, element) => value + ", " + element) // : '???', (widget.destination ?? ''), style: TextStyle(fontSize: 24, color: Colors.black87), ) ], ), ); } 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(() { speaker = !speaker; }); Nusa.speakerPhone(speaker); }, child: new Icon( speaker ? Icons.volume_up : Icons.volume_off, color: speaker ? Colors.white : Colors.blueAccent, size: 20.0, ), shape: new CircleBorder(), elevation: 2.0, fillColor: speaker ? Colors.blueAccent : 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.acceptAudioCall(); }, 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)))) ])); })), )); } Widget _members() { return Container( alignment: Alignment.bottomCenter, padding: EdgeInsets.symmetric(vertical: 160), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: destinationList .skip(1) .map((f) => CircleAvatar( radius: 36, backgroundImage: NetworkImage( "https://www.woolha.com/media/2019/06/buneary.jpg"))) .toList(), ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( iconTheme: IconThemeData(color: Colors.black54), title: Text( title, style: TextStyle(color: Colors.black54), ), backgroundColor: Colors.transparent, centerTitle: true, elevation: 0.0, actions: [ IconButton( onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => WhiteBoard( destination: widget.destination, isInitiator: widget.isInitiator, ))); }, icon: Icon(Icons.brush), padding: EdgeInsets.all(0.0)), IconButton( onPressed: () { if (receiveSS) { Navigator.push( context, MaterialPageRoute( builder: (context) => ScreenSharing( destination: widget.destination, isInitiator: false, ))); } else { Nusa.initiateScreenSharing(widget.destination); } }, icon: Icon(Icons.screen_share, color: receiveSS ? Colors.orange : Theme.of(context).primaryColor), padding: EdgeInsets.all(0.0)), IconButton( onPressed: widget.onAddCall, icon: Icon(Icons.person_add), padding: EdgeInsets.all(0.0)) ], ), backgroundColor: Colors.white, body: Center( child: Stack( children: [_profile(), _panel(), _members(), _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.audio.AudioCallActivity import io.newuniverse.nusdk.core.NuSDK import kotlinx.android.synthetic.main.audio_call_example.* class AudioCallExample : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.audio_call_example) NuSDK.init("abcd_1234", "yayandw") bind() NuSDK.registerAudioCallReceiver { var1, var2, var3, var4 -> val intent = Intent(var1, AudioCallActivity::class.java) .putExtra("Originator", var2) var1.startActivity(intent) } start.setOnClickListener { val intent = Intent(this, AudioCallActivity::class.java) .putExtra("Destination", "tesa") startActivity(intent) } } private var permissions = arrayOf( 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