在 ConnectionService.onCreateIncomingConnection 中调用 TelecomManager.addNewIncomingCall 时,如何接收传入的 Bundle 'extras'?

问题描述

我正在尝试使用 Android 的 ConnectionService 创建一个通话应用。我可以成功接听电话,但我正在尝试通过 TelecomManager.addNewIncomingCall 中的“extras”参数传递特定于应用程序的数据。但是,当我在 ConnectionService 类中实际创建 Connection 对象时,我找不到可以访问我设置和传入的 Bundle 的位置。

当我检查 onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount,ConnectionRequest request) 中的传入参数时,connectionManagerPhoneAccount.getExtras() 或 request.getExtras() 都不是我传递给 TelecomManager.addNewIncomingCall 的额外参数。

在将这个额外的对象传递给 TelecomManager.addNewIncomingCall 之后,有没有人有设置和检索它的经验?

我正在尝试将正在呼叫的电话号码传递给 Connection 对象,以便我可以从设备的联系人正确解析来电显示显示它。

代码

package com.twilio.voice.quickstart;

...

public class VoiceActivity extends AppCompatActivity {

   

    @RequiresApi(api = Build.VERSION_CODES.M)
    private void handleIncomingCall() {
        Log.d(TAG,"handleIncomingCall() triggered");

        Bundle extras = new Bundle();
        Uri uri = Uri.fromParts(PhoneAccount.SCHEME_TEL,activeCallInvite.getFrom(),null);
        extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,uri);
        extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,handle);
        extras.putParcelable(Constants.INCOMING_CALL_INVITE,activeCallInvite);
        telecomManager.addNewIncomingCall(handle,extras);
    }



package com.twilio.voice.quickstart;

@RequiresApi(api = Build.VERSION_CODES.M)
public class VoiceConnectionService extends ConnectionService {
    private static final String TAG = "VoiceConnectionService";

    private static Connection connection;

    public static Connection getConnection() {
        return connection;
    }

    public static void deinitConnection() {
        connection = null;
    }

    @Override
    public Connection onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount,ConnectionRequest request) {
        //Not sure how to get the extra information to rebuild the twilio call invitation back up..
        Log.i(TAG,"Incoming Connection Request,came with extras: " + request.getExtras());
//        CallInvite activeCallInvite = intent.getParcelableExtra(Constants.INCOMING_CALL_INVITE);

        Connection incomingCallConnection = createConnection(request);
        incomingCallConnection.setRinging();
        return incomingCallConnection;
    }

    @Override
    public Connection onCreateOutgoingConnection(PhoneAccountHandle connectionManagerPhoneAccount,ConnectionRequest request) {
        Connection outgoingCallConnection = createConnection(request);
        outgoingCallConnection.setDialing();
        return outgoingCallConnection;
    }

    private Connection createConnection(ConnectionRequest request) {
        connection = new Connection() {

            @Override
            public void onStateChanged(int state) { //Is this where we can get the phone number & set the caller id?
                Log.i(TAG,"Connection Request: " + request.toString());
                if (state == Connection.STATE_DIALING) {
                    final Handler handler = new Handler();
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
//                            sendCallRequestToActivity(ACTION_OUTGOING_CALL); //I think this is getting triggered as an extra thing....
                        }
                    });
                }
            }

            @Override
            public void onCallAudioStateChanged(CallAudioState state) {
                Log.d(TAG,"onCallAudioStateChanged called,current state is " + state);
            }

            @Override
            public void onPlayDtmfTone(char c) {
                Log.d(TAG,"onPlayDtmfTone called with DTMF " + c);
                Bundle extras = new Bundle();
                extras.putString(DTMF,Character.toString(c));
                connection.setExtras(extras);
                final Handler handler = new Handler();
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        sendCallRequestToActivity(ACTION_DTMF_SEND);
                    }
                });
            }

            @Override
            public void ondisconnect() {
                super.ondisconnect();
                connection.setdisconnected(new disconnectCause(disconnectCause.LOCAL));
                connection.destroy();
                connection = null;
                final Handler handler = new Handler();
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        sendCallRequestToActivity(ACTION_disCONNECT_CALL);
                    }
                });
            }

            @Override
            public void onSeparate() {
                super.onSeparate();
            }

            @Override
            public void onAbort() {
                super.onAbort();
                connection.setdisconnected(new disconnectCause(disconnectCause.CANCELED));
                connection.destroy();
            }

            @Override
            public void onAnswer() {
                super.onAnswer();
                Log.i(TAG,"Connection was answered!");
                connection.setActive();
                final Handler handler = new Handler();
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        sendCallRequestToActivity(ACTION_ANSWER_CALL);
                    }
                });
            }

            @Override
            public void onReject() {
                super.onReject();
                connection.setdisconnected(new disconnectCause(disconnectCause.CANCELED));
                connection.destroy();
            }

            @Override
            public void onPostDialContinue(boolean proceed) {
                super.onPostDialContinue(true);
            }
        };

        //How to get the phone number,and resolve it to a contact/address?
        //https://developer.android.com/reference/android/telecom/Connection
        Log.i(TAG,"Creating the connection object for the incoming call,here are the extras: " + request.getExtras() + "; " + connection.getExtras());

        connection.setConnectionCapabilities(Connection.CAPABILITY_MUTE);
        if (request.getExtras().getString(CALLEE) == null) {
            connection.setAddress(request.getAddress(),TelecomManager.PRESENTATION_ALLOWED);
        } else {
            connection.setAddress(Uri.parse(request.getExtras().getString(CALLEE)),TelecomManager.PRESENTATION_ALLOWED);
        }

//both returning null
//        Log.i(TAG,"CALLEE: " + request.getExtras().getString(CALLEE)); 
//        Log.i(TAG,"CALLER: " + request.getExtras().getString(CALLER));
//        connection.setDialing();
        connection.setExtras(request.getExtras()); //This is where we want to connect..?

        //How can we get the caller Id...?
        connection.setCallerdisplayName("Example Contact.",TelecomManager.PRESENTATION_ALLOWED);
        return connection;
    }

    /*
     * Send call request to the VoiceConnectionServiceActivity
     */
    private void sendCallRequestToActivity(String action) {
        Log.i(TAG,"Transmitting broadcast from VoiceConnectionService to Voice Activity with action: " + action);
        Intent intent = new Intent(action);
        Bundle extras = new Bundle();
        switch (action) {
            case ACTION_OUTGOING_CALL:
                Uri address = connection.getAddress();
                extras.putString(OUTGOING_CALL_ADDRESS,address.toString());
                intent.putExtras(extras);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
                LocalbroadcastManager.getInstance(this).sendbroadcast(intent);
                break;
            case ACTION_disCONNECT_CALL:
                extras.putInt("Reason",disconnectCause.LOCAL);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
                intent.putExtras(extras);
                LocalbroadcastManager.getInstance(this).sendbroadcast(intent);
                break;
            case ACTION_DTMF_SEND:
                String d = connection.getExtras().getString(DTMF);
                extras.putString(DTMF,connection.getExtras().getString(DTMF));
                intent.putExtras(extras);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
                LocalbroadcastManager.getInstance(this).sendbroadcast(intent);
                break;
            case ACTION_ANSWER_CALL:
//                Uri address2 = connection.getAddress();
//                extras.putString(OUTGOING_CALL_ADDRESS,address2.toString());
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
                intent.putExtras(extras);
                LocalbroadcastManager.getInstance(this).sendbroadcast(intent);
                break;
            default:
                break;
        }
    }

}

解决方法

我曾经遇到过同样的问题,花了很长时间才找到解决方案。

关键是将我自己的捆绑存储在密钥 EXTRA_INCOMING_CALL_EXTRAS 中,类似于在拨出呼叫情况下使用 EXTRA_OUTGOING_CALL_EXTRAS 的建议。

val myBundle = Bundle().apply { 
    putParcelable(TWILIO_CALL_INVITE,callInvite)
}
telecomManager.addNewIncomingCall(
                phoneAccountHandle,Bundle().apply {
                    putBundle(EXTRA_INCOMING_CALL_EXTRAS,myBundle)
                    putParcelable(EXTRA_PHONE_ACCOUNT_HANDLE,phoneAccountHandle)
                }
            )