7

Android Q引入了CallRedirectionServiceAPI——似乎是第 3 方应用程序可以使用它的方式之一是取消呼叫并通过 VoIP 重新路由它们——本质上是拦截电话。

我试图实现这个类如下

public class CallMonitorService extends CallRedirectionService {
    private static final String TAG = "CallMonitorService";

    public CallMonitorService() {
    }

    @Override
    public void onPlaceCall(Uri uri, PhoneAccountHandle phoneAccountHandle, boolean b) {
        Log.e(TAG, "onPlaceCall:### ");
    }


}

正如您所看到的,我正在覆盖onPlaceCall其中的抽象方法,CallRedirectionService并简单地保留一个日志语句来检查/测试此回调方法挂钩是否被 Android 框架调用。

我在我的 Manifest.xml 以及下面添加了此服务,这是CallRedirectionService类的源代码中记录的内容

<service
                android:name=".CallMonitorService"
                android:permission="android.permission.BIND_REDIRECTION_SERVICE"
                android:enabled="true"
                android:exported="true">
            <intent-filter>
                <action android:name="android.telecom.CallRedirectionService"/>
            </intent-filter>
        </service>

我的猜测是,当 Android 系统发出拨出电话时,它onPlaceCall会被调用,然后我们可以编写自定义代码来对拨出电话进行进一步的操作。我不是 100% 确定这是否CallRedirectionService应该是这样工作的 - 顺便说一下,在CallRedirectionService撰写本文时,developer.android.com 中没有关于如何实现的示例。我将两者都设置 minSdkVersion 29 targetSdkVersion 29在我的build.gradle

但是,当调用时 -onPlaceCall我的服务内部没有被调用。

我正在使用 Android Q Emulator 进行测试,因为我没有运行 Android Q 的 Android 手机来对此进行测试 - 是否可以通过拨打模拟电话在 Android 模拟器上进行测试,或者我还缺少什么?

4

2 回答 2

11

问题是目前文档不完整,文档中的示例不正确。要解决此问题,需要在您的 AndroidManifest 中进行更改

android:permission="android.permission.BIND_REDIRECTION_SERVICE"

android:permission="android.permission.BIND_CALL_REDIRECTION_SERVICE"

目前,此权限在https://developer.android.com/reference/android/telecom/CallRedirectionService.html的谷歌文档中被错误地写入。

此外,需要要求用户允许您的应用程序扮演此角色。在谷歌文档中,这部分目前缺少:

 RoleManager roleManager = null;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
        roleManager = (RoleManager) getSystemService(Context.ROLE_SERVICE);

        Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_REDIRECTION);
        startActivityForResult(intent, 1);}
于 2019-08-12T12:55:02.123 回答
1

得到它的工作(看这里)。下一个代码将阻止所有拨出电话(这只是一个示例......):

MainActivity.kt

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        if (!isRedirection())
            roleAcquire(RoleManager.ROLE_CALL_REDIRECTION)
    }

    private fun isRedirection(): Boolean {
        return isRoleHeldByApp(RoleManager.ROLE_CALL_REDIRECTION)
    }

    private fun isRoleHeldByApp(roleName: String): Boolean {
        val roleManager: RoleManager?
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            roleManager = getSystemService(RoleManager::class.java)
            return roleManager.isRoleHeld(roleName)
        }
        return false
    }

    private fun roleAcquire(roleName: String) {
        val roleManager: RoleManager?
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            if (roleAvailable(roleName)) {
                roleManager = getSystemService(RoleManager::class.java)
                val intent = roleManager.createRequestRoleIntent(roleName)
                startActivityForResult(intent, ROLE_ACQUIRE_REQUEST_CODE)
            } else {
                Toast.makeText(this, "Redirection call with role in not available", Toast.LENGTH_SHORT).show()
            }
        }
    }

    private fun roleAvailable(roleName: String): Boolean {
        val roleManager: RoleManager?
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            roleManager = getSystemService(RoleManager::class.java)
            return roleManager.isRoleAvailable(roleName)
        }
        return false
    }

    companion object {
        private const val ROLE_ACQUIRE_REQUEST_CODE = 4378
    }
}

MyCallRedirectionService.kt

class MyCallRedirectionService : CallRedirectionService() {

    override fun onPlaceCall(handle: Uri, initialPhoneAccount: PhoneAccountHandle, allowInteractiveResponse: Boolean) {
        Log.d("AppLog", "handle:$handle , initialPhoneAccount:$initialPhoneAccount , allowInteractiveResponse:$allowInteractiveResponse")
        cancelCall()
    }
}

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.callredirectionservicesample">

    <application
        android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <service
            android:name=".MyCallRedirectionService"
            android:permission="android.permission.BIND_CALL_REDIRECTION_SERVICE">
            <intent-filter>
                <action android:name="android.telecom.CallRedirectionService" />
            </intent-filter>
        </service>
    </application>

</manifest>
于 2020-10-07T10:34:44.557 回答