make a custom call using TelecomManager.placeCall

1.7k views Asked by At

I'm trying to make a custom implementation of a call using TelecomManager between two users who had installed my app on their devices

Following this guide I implemented connection service, subclass of Connection, added permissions, registered a PhoneAccount and so on...

The thing I'm struggling to understand for a third week already how to place a call between users of my app without using telephone number but user name or userId.

Below code starting to make a call from my device but this call never reaches end user device

telecomManager.placeCall(Uri.fromParts(/*tried also with PhoneAccount.SCHEME_SIP and PhoneAccount.SCHEME_TEL*/
                        TripmateConnectionService.SCHEME_AG, "userId", null), extras)

Need to mention, that in my BroadcastReceiver implementation I can detect incoming calls from other apps, so it's seems that I handling call detection correct and the call from above code is never really send to device of the user it was intended to.

Now is the question. I feel like I missing something vital. How exactly do devices with same app can communicate to each other without phone number? Does it really enough just to pass a user name to a telecomManager.placeCall and it should somehow manage to find right device with installed app and make a call to it? How can telecomManager distinguish where to make a call?

Sorry for unclear question, it's my first time doing something related to calls and I feel I luck understanding of the subject and it hard to make a question more concrete because I don't exactly know what am I missing.

I will put below some code I'm using now

Start an outgoing call

 private fun placeSystemCall(myUid: String, peerUid: String, channel: String, role: Int) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val extras = Bundle()
            extras.putInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, VideoProfile.STATE_BIDIRECTIONAL)
            val extraBundle = Bundle()
            extraBundle.putString(Constants.CS_KEY_UID, myUid)
            extraBundle.putString(Constants.CS_KEY_SUBSCRIBER, peerUid)
            extraBundle.putString(Constants.CS_KEY_CHANNEL, channel)
            extraBundle.putInt(Constants.CS_KEY_ROLE, Constants.CALL_ID_OUT)
            extras.putBundle(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extraBundle)
            try {
                val telecomManager = applicationContext.getSystemService(TELECOM_SERVICE) as TelecomManager
                val pa: PhoneAccount = telecomManager.getPhoneAccount(
                        config().phoneAccountOut?.accountHandle)
                extras.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, true);
                extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, pa.accountHandle)
                telecomManager.placeCall(Uri.fromParts(
                        TripmateConnectionService.SCHEME_AG, peerUid, null), extras)
            } catch (e: SecurityException) {
                e.printStackTrace()
            }
        }
    }

In ConnectionService

override fun onCreateOutgoingConnection(phoneAccount: PhoneAccountHandle?, request: ConnectionRequest): Connection {
        Log.i(TAG, "onCreateOutgoingConnection: called. $phoneAccount $request")
        val extras = request.extras
        val uid = extras.getString(Constants.CS_KEY_UID) ?: "0"
        val channel = extras.getString(Constants.CS_KEY_CHANNEL) ?: "0"
        val subscriber = extras.getString(Constants.CS_KEY_SUBSCRIBER) ?: "0"
        val role = extras.getInt(Constants.CS_KEY_ROLE)
        val videoState = extras.getInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE)
        val connection = TripmateConnection(applicationContext, uid, channel, subscriber, role)
        connection.setVideoState(videoState)
        connection.setAddress(Uri.fromParts(SCHEME_AG, subscriber, null), TelecomManager.PRESENTATION_ALLOWED)
        connection.setCallerDisplayName(subscriber, TelecomManager.PRESENTATION_ALLOWED)
        connection.setRinging()
        TMApplication.getInstance().config().setConnection(connection)
        return connection
    }

creating PhoneAccounts

private fun registerPhoneAccount(context: Context) {
        val telecomManager = context.getSystemService(Context.TELECOM_SERVICE) as? TelecomManager
                ?: throw RuntimeException("cannot obtain telecom system service")

        val accountHandleIn = PhoneAccountHandle(
                ComponentName(context, TripmateConnectionService::class.java), Constants.PA_LABEL_CALL_IN)
        val accountHandleOut = PhoneAccountHandle(
                ComponentName(context, TripmateConnectionService::class.java), Constants.PA_LABEL_CALL_OUT)
        try {
            var paBuilder: PhoneAccount.Builder = PhoneAccount.builder(accountHandleIn, Constants.PA_LABEL_CALL_IN)
                    .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
            val phoneIn = paBuilder.build()
            paBuilder = PhoneAccount.builder(accountHandleOut, Constants.PA_LABEL_CALL_OUT)
                    .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
            val extra = Bundle()
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                extra.putBoolean(PhoneAccount.EXTRA_LOG_SELF_MANAGED_CALLS, true)
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                paBuilder.setExtras(extra)
            }
            val phoneOut = paBuilder.build()
            telecomManager.registerPhoneAccount(phoneIn)
            telecomManager.registerPhoneAccount(phoneOut)
            if (telecomManager.getPhoneAccount(phoneIn.accountHandle) == null || telecomManager.getPhoneAccount(phoneOut.accountHandle) == null) {
                throw RuntimeException("cannot create account");
            }
            mCallSession = TripmateCallSession()
            mCallSession?.phoneAccountIn = phoneIn
            mCallSession?.phoneAccountOut = phoneOut
        } catch (e: SecurityException) {
            throw RuntimeException("cannot create account", e);
        }
    }

Thank you for your time! Any suggestions and links that could help me to understand more will be highly appreciated!

0

There are 0 answers