如何绑定CallScreeningService?

How to bind CallScreeningService?

我想获取通话详情并阻止通话(如有必要)。 由于 TelecomManager endCall 方法已弃用,并且根据它建议使用 CallScreeningService 的文档。 https://developer.android.com/reference/android/telecom/CallScreeningService.html

如 Android 文档中所述,我正在尝试将 CallScreeningService 与我的应用程序绑定。

我创建了一个class

    public class CallUtil extends CallScreeningService {
      private Call.Details mDetails;
      private static CallScreeningUtil sCallScreeningUtil;

      @Override
      public void onScreenCall(Call.Details callDetails) {
        CallResponse.Builder response = new CallResponse.Builder();
        Log.e("CallBouncer", "Call screening service triggered");

        sCallScreeningUtil = this;
        mDetails = callDetails;
        respondToCall(callDetails, response.build() );
    }
}

这是一个系统应用程序,我在AndroidManifest.xml中添加了必要的权限,例如CALL_PHONE、MODIFY_PHONE_STATE、CALL_PHONE、ANSWER_PHONE_CALLS。

我已经添加了服务详细信息,如下所示,

 <service android:name=".CallUtil"
          android:permission="android.permission.BIND_SCREENING_SERVICE">
      <intent-filter>
          <action android:name="android.telecom.CallScreeningService"/>
      </intent-filter>
 </service>

我有点不知道如何将此服务与我的 activity 绑定,或者我如何将此服务与将调用 CallUtil 中的覆盖方法的应用程序绑定。

基于此处提供的文档https://android.googlesource.com/platform/frameworks/base/+/9e1d4f86ba43e87264aba178f2bb037a3c3b26fb/telecomm/java/android/telecom/CallScreeningService.java

    Intent mCallServiceIntent = new Intent(this,"android.telecom.CallScreeningService");
        ServiceConnection mServiceConnection = new ServiceConnection(){

            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                // iBinder is an instance of CallScreeningService.CallScreenBinder
                // CallScreenBinder is an inner class present inside CallScreenService
            }

            @Override
            public void onServiceDisconnected(ComponentName componentName) {

            }

            @Override
            public void onBindingDied(ComponentName name) {

            }
        }

并从 activity 绑定到您可以使用的服务

bindService(mCallServiceIntent, mServiceConnection, Context.BIND_AUTO_CREATE)

您是否要求它充当呼叫筛选角色??

您是否尝试过 android docs... 中提到的类似方法?

public void requestRole() {
     RoleManager roleManager = (RoleManager) getSystemService(ROLE_SERVICE);
     Intent intent = roleManager.createRequestRoleIntent("android.app.role.CALL_SCREENING");
     startActivityForResult(intent, REQUEST_ID);
 }

 @Override
 public void onActivityResult(int requestCode, int resultCode, Intent data) {
     if (requestCode == REQUEST_ID) {
         if (resultCode == android.app.Activity.RESULT_OK) {
             // Your app is now the call screening app
         } else {
             // Your app is not the call screening app
         }
     }
 }

这是最基本的实现(基于 here, easier one here 的示例存储库,如果有人想查看):

主要Activity

@RequiresApi(Build.VERSION_CODES.Q)
class MainActivity : AppCompatActivity() {
    private val roleManager by lazy { getSystemService(RoleManager::class.java) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        when {
            roleManager.isRoleHeld(RoleManager.ROLE_CALL_SCREENING) ->
                Log.d("AppLog", "got role")
            roleManager.isRoleAvailable(RoleManager.ROLE_CALL_SCREENING) ->
                Log.d("AppLog", "cannot hold role")
            else ->
                startActivityForResult(roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_SCREENING), REQUEST_CALLER_ID_APP)
        }
    }

//TODO handle onActivityResult if you wish. This is just the basic stuff...

    companion object {
        private const val REQUEST_CALLER_ID_APP = 1
    }
}

BasicCallScreeningService

@RequiresApi(Build.VERSION_CODES.Q)
class BasicCallScreeningService : CallScreeningService() {
    override fun onScreenCall(callDetails: Call.Details) {
        val phoneNumber = callDetails.handle.schemeSpecificPart
        val callDirection = callDetails.callDirection
        //TODO do something with callDetails. Maybe call respondToCall(callDetails, CallResponse.Builder().build())
    }
}

清单:

...
<service android:name=".BasicCallScreeningService"
    android:permission="android.permission.BIND_SCREENING_SERVICE">
    <intent-filter>
        <action android:name="android.telecom.CallScreeningService"/>
    </intent-filter>
</service>
...

此外,您可以使用 ACTION_POST_CALL Intent 为 phone 来电显示 after-call Activity 显示:

<activity
    android:name=".AfterCallActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="android.telecom.action.POST_CALL" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

在 Activity 本身中,您可以获得一些关于 phone 调用的信息。示例:

{android.telecom.extra.HANDLE:tel:6505551212,android.telecom.extra.DISCONNECT_CAUSE:5,android.telecom.extra.CALL_DURATION:0}