can doğan
can doğan

Reputation: 1

Android Kotlin: Placing a Call in the Background with Connection Service & Phone Account Does Not Make an Actual Call (CAPABILITY_SELF_MANAGED)

I'm working on a Kotlin Android application that won't be published on any store. I need to make a background call in my application and be able to ring the other number.

I implemented it using Connection Service and Phone Account. I can make a call, but the call doesn't work properly.

I am placing the call. I can also see the dialer screen when I set the capability to CAPABILITY_CONNECTION_MANAGER, and it blocks the actual dialer app. However, the number that I called is not ringing. When I close my app, I also hear the beep when you hang up the phone call.

I've tried it with different numbers and country codes.

I am new to Android development, so maybe I am missing something.

Let me know if there's anything else you'd like to adjust or add!

You can see my code and permissions below:

MainActivity.kt

fun makeTelecomCall() {

        if (ContextCompat.checkSelfPermission(
                applicationContext,
                android.Manifest.permission.CALL_PHONE
            ) == PackageManager.PERMISSION_GRANTED
        ) {
            // Permission is granted, you can proceed with making phone calls

            val phoneAccountHandle = PhoneAccountHandle(
                ComponentName(applicationContext, MyConnectionService::class.java),
                "UniqueIdentifier"
            )
            val phoneAccount = PhoneAccount.Builder(phoneAccountHandle, "YourAppLabel")
                .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)//CAPABILITY_CONNECTION_MANAGER CAPABILITY_SELF_MANAGED
                .build()
            val telecomManager = applicationContext.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
            telecomManager.registerPhoneAccount(phoneAccount)


            val uri = Uri.fromParts(PhoneAccount.SCHEME_TEL, "xxxxxxx", null)
            val bundle = Bundle()
            bundle.putParcelable(
                TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
                phoneAccountHandle
            )
            telecomManager.placeCall(uri, bundle)
        } else {
            // Permission is not granted, request the permission from the user
            ActivityCompat.requestPermissions(
                this,
                arrayOf(android.Manifest.permission.CALL_PHONE),
                CALL_PHONE_PERMISSION_REQUEST_CODE
            )

        }
        
    }

ConnectionService.kt


package com.example.helloandroid

import android.net.Uri
import android.telecom.Connection
import android.telecom.ConnectionRequest
import android.telecom.ConnectionService
import android.telecom.PhoneAccount.CAPABILITY_SELF_MANAGED
import android.telecom.PhoneAccountHandle
import android.telecom.TelecomManager
import android.util.Log

class MyConnectionService : ConnectionService() {
    override fun onCreateOutgoingConnection(
        phoneAccountHandle: PhoneAccountHandle?,
        connectionRequest: ConnectionRequest?
    ): Connection? {
        // Handle outgoing call creation
        return YourConnection(phoneAccountHandle, connectionRequest?.address)
    }

    override fun onCreateOutgoingConnectionFailed(
        phoneAccountHandle: PhoneAccountHandle?,
        connectionRequest: ConnectionRequest?
    ) {
        // Handle outgoing call creation failure
    }

    override fun onCreateIncomingConnection(
        phoneAccountHandle: PhoneAccountHandle?,
        connectionRequest: ConnectionRequest?
    ): Connection? {
        // Handle incoming call creation
        return YourConnection(phoneAccountHandle, connectionRequest?.address)
    }

    override fun onCreateIncomingConnectionFailed(
        phoneAccountHandle: PhoneAccountHandle?,
        connectionRequest: ConnectionRequest?
    ) {
        // Handle incoming call creation failure
        Log.i("OUTGOINGCALLFAILED","d")
    }
}

class YourConnection(
    phoneAccountHandle: PhoneAccountHandle?,
    address: Uri?
) : Connection() {
    init {
        setAddress(address, TelecomManager.PRESENTATION_ALLOWED)
        setConnectionCapabilities(CAPABILITY_SELF_MANAGED)
        setAudioModeIsVoip(true)
    }

    override fun onStateChanged(state: Int) {
        // Handle state changes of the call
        Log.i("CONNECTION",state.toString())
    }
}

AndroidManifest.xml


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-feature android:name="android.hardware.telephony" />

    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.android.permission.BIND_TELECOM_CONNECTION_SERVICE" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.HelloAndroid"
        android:usesCleartextTraffic="true"
        tools:targetApi="31">
        <activity
            android:name=".ui.SplashScreen"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".Telecom.Call.TelecomCallService"
            android:exported="false"
            android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE" />

        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

            </intent-filter>
        </activity>

        <service
            android:name=".MyConnectionService"
            android:exported="true"
            android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE">
            <intent-filter>
                <action android:name="android.telecom.ConnectionService" />
            </intent-filter>
        </service>
    </application>

</manifest>

Upvotes: 0

Views: 407

Answers (0)

Related Questions