2

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

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

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

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

代码:

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;
        }
    }

}

4

1 回答 1

3

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

关键是将我自己的包存储在 keyEXTRA_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)
                }
            )

于 2021-03-31T18:35:45.577 回答