How to bind CallScreeningService?

微笑、不失礼 提交于 2021-01-27 06:27:13

问题


I want to get the Call Details and block the calls(if necessary). As the TelecomManager endCall method is deprecated and as per the documentation it is suggesting to use the CallScreeningService. https://developer.android.com/reference/android/telecom/CallScreeningService.html

As mentioned in the Android documentation, I am trying to bind the CallScreeningService with my application.

I have created a 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() );
    }
}

This is a system app and I have added necessary permission in AndroidManifest.xml such as CALL_PHONE, MODIFY_PHONE_STATE, CALL_PHONE, ANSWER_PHONE_CALLS.

I have added the Service details as well like below,

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

I am kinda lost on how to bind this service with my activity or how do I bind this service with my application that will call the Overridden methods in CallUtil.


回答1:


Based on the documentation provided over here 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) {

            }
        }

And from an activity, to bind to the service you can use

bindService(mCallServiceIntent, mServiceConnection, Context.BIND_AUTO_CREATE)



回答2:


Have you request that it fills the call screening role??

Have you tried something like this as mentioned in 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
         }
     }
 }



回答3:


Here's the most basic implementation (based on sample repository from here, easier one here, if anyone wishes to check out):

MainActivity

@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())
    }
}

manifest:

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

In addition, you can have an after-call Activity being shown for phone calls you didn't block, using the ACTION_POST_CALL Intent :

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

In the Activity itself, you can have a bit of information about the phone call. Example:

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


来源:https://stackoverflow.com/questions/56987962/how-to-bind-callscreeningservice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!