Android 自定义拨号器应用,连接未激活

Posted

技术标签:

【中文标题】Android 自定义拨号器应用,连接未激活【英文标题】:Android custom dialer app, connections are not activated 【发布时间】:2019-09-19 00:27:33 【问题描述】:

我正在尝试实现一个基本的拨号器应用程序,它还应该处理来电。场景是用户将应用设置为默认拨号器,从那时起,每个传入和传出呼叫都应该到达应用的 ConnectionService 实现。

我不想覆盖内置的调用 UI,我只需要在 Connection 回调中添加一些额外的逻辑。例如我想发送一个广播意图,当一个连接被回答时等等。

根据this 文档,我认为我应该实现一个系统管理的 ConnectionService。

我已经通过以下方式实现了 ConnectionService,并且效果很好,在传入或传出呼叫的情况下会调用回调:

public class DialerConnectionService extends ConnectionService 

NotificationManagerUtil notificationManager;

public DialerConnectionService() 
    notificationManager = NotificationManagerUtil.getInstance();


@Override
public Connection onCreateOutgoingConnection(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) 
    return createConnection(request, false);


@Override
public void onCreateOutgoingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) 
    notificationManager.createToast(getApplicationContext(), getString(R.string.error_place_outgoing_call));


@Override
public Connection onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) 
    return createConnection(request, true);


@Override
public void onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) 
    notificationManager.createToast(getApplicationContext(), getString(R.string.error_create_incoming_call));


private TelecomConnection createConnection(ConnectionRequest request, boolean isIncoming) 
    TelecomConnection connection = new TelecomConnection(getApplicationContext(), isIncoming);
    connection.setConnectionProperties(Connection.PROPERTY_SELF_MANAGED);
    connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
    String normalizedPhoneNumber = ContactsUtil.getInstance().normalizePhoneNumberFromUri(request.getAddress());
    connection.setNormalizedPhoneNumber(normalizedPhoneNumber);
    connection.setCallerDisplayName(ContactsUtil.getInstance().getContactName(getApplicationContext(), normalizedPhoneNumber), TelecomManager.PRESENTATION_ALLOWED);
    connection.setExtras(request.getExtras());
    if (isIncoming) 
        connection.setRinging();
     else 
        connection.setDialing();
    
    connection.setInitializing();
    CallManager.getInstance().addConnection(connection);
    return connection;




问题是,如果我注册了一个具有PhoneAccount.CAPABILITY_CONNECTION_MANAGER 功能的 PhoneAccount,则创建的调用不会变为 - 因为缺少更好的词 - 活动,但正确调用了 Connection 的回调。所以我可以拨出电话,但另一部电话永远不会收到来电通知。 或者,如果我从另一部手机拨打电话,运行我的应用程序的设备将进入其 onCreateIncomingConnection() 方法,我将能够接听该电话,但发起电话仍会拨号。

我已通过以下方式注册了 PhoneAccount,我怀疑问题出在此处:

public boolean checkAccountHandler(Context ctx) 
    PhoneAccountHandle phoneAccountHandle = getPhoneAccountHandle(ctx);
    telecomManager = (TelecomManager) ctx.getSystemService(Context.TELECOM_SERVICE);

    PhoneAccount phoneAccount = telecomManager.getPhoneAccount(phoneAccountHandle);
    if (phoneAccount == null)
        PhoneAccount account = PhoneAccount.builder(phoneAccountHandle, PHONE_ACCOUNT_LABEL)
                .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
                .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
                .build();
        telecomManager.registerPhoneAccount(account);
        return false;
    
    return true;

这样注册的账号不会出现在android的设置中,所以我不能让用户启用它。 有没有可能这是问题的主要原因?

我的清单使用以下权限:

<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />

这里是活动的注册和 ConnectionService 的实现:

<activity
        android:name=".activity.MainActivity"
        android:screenOrientation="portrait">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <action android:name="android.intent.action.DIAL" />

            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />

            <data android:scheme="tel" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.DIAL" />

            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
</activity>
<service
     android:name=".service.DialerConnectionService"
     android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE">
     <intent-filter>
     <action android:name="android.telecom.ConnectionService" />
     </intent-filter>
 </service>

【问题讨论】:

如果你找到答案。告诉我 @apropovics 你找到答案了吗? 【参考方案1】:
Bundle extras = new Bundle();
extras.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, true);
extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, telecomManager.getUserSelectedOutgoingPhoneAccount());//This is the most important thing
telecomManager.placeCall(uri,extras);

【讨论】:

extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, telecomManager.getUserSelectedOutgoingPhoneAccount());//在PlaceCall之前使用这个();

以上是关于Android 自定义拨号器应用,连接未激活的主要内容,如果未能解决你的问题,请参考以下文章

为 android 创建自定义拨号盘视图

android M拨号盘开源之旅--- 初窥M拨号盘

如何在 Android 中使用 Phonegap 拨打自定义电话号码?

iPhone 和Android应用,特殊的链接:打电话,短信,email

是否可以用自定义 UI 替换 Android 的内置 Caller?

在我的项目中构建和重用 android 开源 Dialer 源代码