Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CallRedirectionService Implementation not working

Android Q has introduced CallRedirectionService API - seems like one of the way 3rd party apps can use it is to cancel calls and reroute them over VoIP - essentially intercepting the phone calls.

I was trying to implement this class as below

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:### ");
    }


}

As you can see I am overriding onPlaceCall which is abstract method in the CallRedirectionService and simply keeping a log statement to check/test if this callback method hook is invoked by Android framework.

I added this service in my Manifest.xml as well as below, which is what is documented in the Source code of CallRedirectionService class

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

My Guess is that when Android system places a outgoing call this onPlaceCall will be invoked and then we can write our custom code to do further action on the outgoing call. Am not 100% sure if this is how CallRedirectionService is supposed to work - By the way there is no example available in developer.android.com for how to implement CallRedirectionService as of this writing. I set both minSdkVersion 29 targetSdkVersion 29 in my build.gradle

However when the call is made - the onPlaceCall inside my Service is not getting invoked.

I am using Android Q Emulator for testing as i do not have Android phone running Android Q to test this - can this be not tested on Android emulator by placing a emulated phone call or What else Am I missing?

like image 392
AADProgramming Avatar asked Jun 11 '19 17:06

AADProgramming


People also ask

What is CallRedirectionService in android?

android.telecom.CallRedirectionService. This service can be implemented to interact between Telecom and its implementor for making outgoing call with optional redirection/cancellation purposes.

Which permission is required to monitor modify or about outgoing calls?

permission. PROCESS_OUTGOING_CALLS. Allows the app to process outgoing calls and change the number to be dialed. This permission allows the app to monitor, redirect, or prevent outgoing calls.


2 Answers

The problem is that at the moment documentation is not full and sample in documentation is not correct. To fix this, in your AndroidManifest it is needed to change

android:permission="android.permission.BIND_REDIRECTION_SERVICE"

to

android:permission="android.permission.BIND_CALL_REDIRECTION_SERVICE"

This permission is incorrectly written inside the google documentation for https://developer.android.com/reference/android/telecom/CallRedirectionService.html currently.

Also, it is required to ask user to allow your application play this role. In google documentation this part missing at the moment :

 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);}
like image 95
Alex Kutsko Avatar answered Sep 24 '22 08:09

Alex Kutsko


Got it working (looking here). The next code will block all outgoing calls (it's just a sample...) :

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>
like image 39
android developer Avatar answered Sep 24 '22 08:09

android developer