How to merge Call programmatically while other call is running (Conference call)
Categories:
Programmatic Conference Call Merging on Android

Learn how to programmatically merge an incoming call into an active call to create a conference call experience on Android devices.
Creating a conference call programmatically on Android involves managing multiple Call
objects and utilizing the device's telephony capabilities. This article will guide you through the process, focusing on the android.telecom
framework, which is essential for handling in-call experiences on modern Android versions. We'll cover the necessary permissions, how to detect and manage calls, and the specific API calls required to merge them into a conference.
Understanding Android's Telephony Framework
Before diving into the code, it's crucial to understand how Android handles calls. The android.telecom
package provides classes for managing calls, including Call
, Call.Details
, and InCallService
. An InCallService
is a specialized service that an application can implement to provide its own in-call user interface and manage calls. For programmatic merging, your application will typically need to interact with the active Call
objects provided by the system's TelecomManager
.
android.telecom
framework was introduced in Android 5.0 (Lollipop) and is the recommended way to interact with telephony services. Older APIs like TelephonyManager
might still exist but are less suitable for advanced call management like merging.flowchart TD A[Incoming Call Detected] --> B{Is there an Active Call?} B -->|Yes| C[Active Call Exists] B -->|No| D[Handle as New Call] C --> E[Accept Incoming Call] E --> F[Hold Active Call (Optional)] F --> G[Merge Calls] G --> H[Conference Call Established]
Flowchart illustrating the process of merging an incoming call into an active call.
Permissions and Setup
To manage calls, your application needs specific permissions. These must be declared in your AndroidManifest.xml
file. Additionally, your app needs to be set as the default dialer or have appropriate InCallService
capabilities to fully control the call state. For basic merging functionality, you'll primarily need READ_PHONE_STATE
and MANAGE_OWN_CALLS
.
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<application ...>
<service android:name=".YourInCallService"
android:permission="android.permission.BIND_INCALL_SERVICE"
android:exported="true">
<intent-filter>
<action android:name="android.telecom.InCallService" />
</intent-filter>
</service>
</application>
Required permissions and InCallService declaration in AndroidManifest.xml
Implementing Call Merging Logic
The core logic for merging calls resides within your InCallService
implementation. When a new incoming call arrives while another call is active, your service will receive updates. You'll need to identify the active call and the new incoming call, then use the Call.mergeCalls()
method to combine them. This method is available on the Call
object that represents the active call.
import android.telecom.Call;
import android.telecom.InCallService;
public class MyInCallService extends InCallService {
private Call activeCall = null;
private Call incomingCall = null;
@Override
public void onCallAdded(Call call) {
super.onCallAdded(call);
if (call.getState() == Call.STATE_ACTIVE) {
activeCall = call;
// Register a callback to monitor the active call
activeCall.registerCallback(activeCallCallback);
} else if (call.getState() == Call.STATE_RINGING) {
incomingCall = call;
// Register a callback to monitor the incoming call
incomingCall.registerCallback(incomingCallCallback);
// Attempt to merge if an active call already exists
if (activeCall != null && activeCall.can(Call.Details.CAPABILITY_MERGE_CONFERENCE)) {
// Answer the incoming call first
incomingCall.answer(0);
}
}
}
@Override
public void onCallRemoved(Call call) {
super.onCallRemoved(call);
if (call.equals(activeCall)) {
activeCall = null;
} else if (call.equals(incomingCall)) {
incomingCall = null;
}
}
private Call.Callback activeCallCallback = new Call.Callback() {
@Override
public void onStateChanged(Call call, int state) {
if (state == Call.STATE_ACTIVE && incomingCall != null && incomingCall.getState() == Call.STATE_ACTIVE) {
// Both calls are active, now merge them
if (call.can(Call.Details.CAPABILITY_MERGE_CONFERENCE)) {
call.mergeCalls();
// Clear incomingCall reference after merging
incomingCall = null;
} else {
// Handle cases where merging is not supported
// e.g., show a toast or log an error
Log.w("MyInCallService", "Active call cannot merge conference.");
}
}
}
};
private Call.Callback incomingCallCallback = new Call.Callback() {
@Override
public void onStateChanged(Call call, int state) {
if (state == Call.STATE_ACTIVE && activeCall != null && activeCall.getState() == Call.STATE_ACTIVE) {
// Both calls are active, now merge them
if (activeCall.can(Call.Details.CAPABILITY_MERGE_CONFERENCE)) {
activeCall.mergeCalls();
// Clear incomingCall reference after merging
incomingCall = null;
} else {
Log.w("MyInCallService", "Active call cannot merge conference.");
}
}
}
};
}
Example InCallService
logic for detecting and merging calls.
Call.Details.CAPABILITY_MERGE_CONFERENCE
flag indicates if the active call supports merging. Not all carriers or devices support this capability, so always check this flag before attempting to merge. If it's not supported, you might need to inform the user or handle the calls separately.1. Declare Permissions
Add READ_PHONE_STATE
, MANAGE_OWN_CALLS
, and CALL_PHONE
permissions to your AndroidManifest.xml
.
2. Implement InCallService
Create a class extending android.telecom.InCallService
and declare it in your manifest. This service will receive callbacks for call state changes.
3. Track Active and Incoming Calls
Within your InCallService
, maintain references to the current active call and any new incoming calls using onCallAdded()
and onCallRemoved()
.
4. Answer Incoming Call
When an incoming call is detected and an active call exists, answer the incoming call using incomingCall.answer(0)
.
5. Check Merge Capability
Before merging, verify that the active call supports conferencing using activeCall.can(Call.Details.CAPABILITY_MERGE_CONFERENCE)
.
6. Merge Calls
Once both calls are active and merge capability is confirmed, call activeCall.mergeCalls()
to combine them into a conference.
7. Handle Callbacks
Use Call.Callback
to monitor state changes of both calls, triggering the merge operation at the appropriate time (e.g., when both calls are STATE_ACTIVE
).