Making an audio call

This guide shows you to how to make an audio call in your Android app. We assume you've already set up your Android app with the In-app Calling Android SDK.

If you haven't already, create an app first. Or, if you want, move on to handling incoming calls.

Setting up the UI

Before you can make a call, you need to set up the app's UI.

The UI part of the rest of the app's functionality (initiating and receiving an audio call) is handled inside another activity: LoggedInActivity.

Start with defining this activity inside your AndroidManifest.xml file.

app/src/main/AndroidManifest.xml

Copy
Copied
    <activity android:name=".LoggedInActivity"/>

Initiating an audio call

  1. Similarly as inside LoginActivity, create a basic layout containing an edit field for typing the callee username and a button that initates the call.

app/src/main/res/layout/activity_logged_in.xml

Copy
Copied
   <LinearLayout
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:gravity="center"
       android:orientation="vertical"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintLeft_toLeftOf="parent"
       app:layout_constraintRight_toRightOf="parent"
       app:layout_constraintTop_toTopOf="parent">

       <TextView
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:text="Enter callee name" />

       <EditText
           android:id="@+id/calleeIdEditText"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:hint="Callee name" />

       <Button
           android:id="@+id/callButton"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:text="Call" />

   </LinearLayout>
  1. Inside SinchService's binder implementation add a method that uses call client to initiate the call:

app/src/main/java/com/sinch/rtc/demovvsdk/SinchService.kt

Copy
Copied
   inner class SinchServiceBinder : Binder() {

       fun callUser(username: String): Call? {
           return sinchClient?.callClient?.callUser(username)
       }

   }
  1. Bind the call button with the method and assign a CallListener to be notified about the changes of the call state:

app/src/main/java/com/sinch/rtc/demovvsdk/LoggedInActivity.kt

Copy
Copied
   binding.callButton.setOnClickListener {
       val call = serviceBinder?.
            callUser(binding.calleeIdEditText.text.toString())
       call?.addCallListener(LoggedInCallListener())
   }

   private inner class LoggedInCallListener: CallListener {

       override fun onCallProgressing(p0: Call?) {
           Log.d(TAG, "onCallProgressing")
       }

       override fun onCallEstablished(p0: Call?) {
           Log.d(TAG, "onCallEstablished")
       }

       override fun onCallEnded(call: Call?) {
           Log.d(TAG, "onCallEnded ${call?.details?.endCause}")
       }

   }

Managing required permissions

If you try to initiate an audio call by pressing the call button at this point the application would crash with the following error output:

Copy
Copied
    Process: com.sinch.rtc.demovvsdk, PID: 876
         com.sinch.android.rtc.MissingPermissionException: Requires permission: android.permission.RECORD_AUDIO

Although we already handled some of the permissions in an earlier step (Internet permissions), the difference here is that RECORD_AUDIO permission is an example of a runtime permission that must be handled during the user's interaction with the app.

  1. Modify the Android Manifest file by decalring usage of the RECORD_AUDIO permission.

app/src/main/AndroidManifest.xml

Copy
Copied
   <uses-permission android:name="android.permission.RECORD_AUDIO"/>
  1. Once the user presses the call button, ask for the permission explicitly and invoke binder's callUser method only if it was granted.

app/src/main/java/com/sinch/rtc/demovvsdk/LoggedInActivity.kt

Copy
Copied
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // Layout initialization
        
        binding.callButton.setOnClickListener {
            requestPermissions(
                arrayOf(Manifest.permission.RECORD_AUDIO),
                REQUEST_CODE
            )
        }

    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, 
                        grantResults)
        if (requestCode == REQUEST_CODE && grantResults.isNotEmpty() && 
            grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            val call = serviceBinder?.callUser(
                binding.calleeIdEditText.text.toString()
                )
            call?.addCallListener(LoggedInCallListener()
            )
        } else {
            //Adopt UI to handle non granted permissions
        }
    }
Note:

In depth overview of possible permission grant results and general handling workflow can be found on the offical Android documentation website.

Next steps

Now that you've made a call, you can set up your application to handle incoming calls.

Was this page helpful?