CallRedirectionService实现无法正常运行

时间:2019-06-11 17:08:43

标签: android service androidq

Android Q引入了CallRedirectionService API-似乎第三方应用程序可以使用它的一种方式是取消呼叫并通过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才能工作-到目前为止,在developer.android.com中尚无用于实现CallRedirectionService的示例。我在minSdkVersion 29中设置了targetSdkVersion 29 build.gradle

无论何时拨打电话-服务中的onPlaceCall都不会被调用。

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

2 个答案:

答案 0 :(得分:6)

问题在于,当前文档不完整,文档中的样本不正确。 要解决此问题,需要在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的google文档中。

此外,还要求用户允许您的应用程序扮演此角色。在Google文档中,此部分目前不存在:

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

答案 1 :(得分:0)

使其正常运行(看起来https://github.com/mobxjs/mobx-react/issues/868)。下一个代码将阻止所有拨出电话(这只是一个示例...):

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>