This guide shows you how to make an audio call in your Android app. We assume you have already set up your Android app with the In‑app Calling SDK.
If you haven't already, first create an app. Or, if you prefer, continue to handle incoming calls.
Before you can make a call, you need to set up the app's UI.
The UI for placing a call is handled inside a dedicated activity: PlaceCallActivity (earlier references to LoggedInActivity in some samples serve broader post‑login functionality). Define this activity inside your AndroidManifest.xml file.
app/src/main/AndroidManifest.xml
<activity android:name=".PlaceCallActivity" />- Similarly to
LoginActivity, create a basic layout containing an input field for the callee username and a button that initiates the call.
app/src/main/res/layout/main.xml
<!-- PlaceCallActivity layout excerpt -->
<com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_big"
android:layout_marginBottom="@dimen/input_layout_bottom"
android:hint="@string/enter_callee_id"
app:counterMaxLength="50"
app:endIconCheckable="true"
app:startIconDrawable="@android:drawable/presence_audio_online"
app:startIconTint="@color/colorPrimaryDark">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/callName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:imeOptions="actionDone" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/callButton"
style="@style/Widget.MaterialComponents.Button.Icon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_average"
android:layout_marginTop="@dimen/margin_small"
android:layout_marginEnd="@dimen/margin_average"
android:padding="@dimen/margin_base_plus"
android:text="@string/call"
android:textAlignment="center"
android:textColor="@color/white"
app:backgroundTint="@color/sinch_green"
app:icon="@drawable/ic_outline_phone_in_talk_24"
app:iconGravity="textEnd" />- Inside
SinchService's binder implementation, add a method that uses the call controller to initiate the call:
app/src/main/java/com/sinch/rtc/sample/push/SinchService.kt
fun callUser(userId: String): Call {
val sinchClient = sinchClient ?: throw IllegalStateException("Sinch client is not created")
return sinchClient.callController.callUser(userId, MediaConstraints(false))
}- Bind the call button to the method and assign a
CallListenerto be notified about changes in the call state:
app/src/main/java/com/sinch/rtc/sample/push/PlaceCallActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ...
callButton.apply {
isEnabled = false
setOnClickListener { callButtonClicked() }
}
}
private fun callButtonClicked() {
val userName = calleeNameEditText.text.toString()
// Validate input (non-empty) before calling if needed
val call = sinchServiceInterface?.callUser(userName)
// Launch in-call UI
startActivity(callScreen)
}If you try to initiate an audio call now, the application will crash with the following error output:
Process: com.sinch.rtc.demovvsdk, PID: 876
com.sinch.android.rtc.MissingPermissionException: Requires permission: android.permission.RECORD_AUDIOAlthough Internet permissions were declared earlier, RECORD_AUDIO is a runtime permission and must be requested during the user's interaction with the app.
- Modify the Android Manifest file by declaring usage of the
RECORD_AUDIOpermission.
app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.RECORD_AUDIO" />- Before the user logs in, request the permission explicitly and start the client only if it was granted.
app/src/main/java/com/sinch/rtc/sample/push/BaseActivity.kt
private val messenger = Messenger(object : Handler() {
override fun handleMessage(msg: Message) {
when (msg.what) {
SinchService.MESSAGE_PERMISSIONS_NEEDED -> {
val requiredPermission = msg.data.getString(SinchService.REQUIRED_PERMISSION)
ActivityCompat.requestPermissions(
this@BaseActivity,
arrayOf(
requiredPermission,
Manifest.permission.POST_NOTIFICATIONS
),
0
)
}
else -> { /* ignore */ }
}
}
})
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
// ... evaluate grantResults
sinchServiceInterface?.retryStartAfterPermissionGranted()
}An in‑depth overview of runtime permissions, grant results, and handling workflow can be found in the official Android documentation: Permissions overview.
Now that you've made a call, you can set up your application to handle incoming calls.