I was very much in search of the way in which we can control calls in Android and faced a lot of difficulties implementing it at the beginning. So I thought to share some knowledge about the same which I gained in the journey.
Now, let’s start.
First create a package in the ‘src’ folder in your project named com.android.internal.telephony and within that package create a file and copy paste the interface ITelephony(I’ve given the interface below) and save the file as ITelephony.aidl. When you compile the project you will get a corresponding java file for the ITelephony in the ‘gen’ folder.
Code for ITelephony.aidl:
package com.w7app.internal.telephony;
interface ITelephony {
boolean endCall();
void answerRingingCall();
void silenceRinger();
}
com.android.internal.telephony is an internal hidden class in the Android Telephony framework. As com.android.internal.telephony is not a public class in the sdk, we use java reflections for retrieving the internal class’s methods.
Now let’s see the permissions needed in the Manifest file:
<uses-permission android:name=”android.permission.READ_PHONE_STATE”/>
<uses-permission android:name=”android.permission.MODIFY_PHONE_STATE”/>
<uses-permission android:name=”android.permission.CALL_PHONE”/>
Now let’s look at the XML file where I’ve added a checkbox enabling which would block the incoming calls.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<CheckBox
android:id="@+id/cbBlockAll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Block all Calls" />
</LinearLayout>
First, we need to use a BroadcastReceiver which responds to the incoming call with action android.intent.action.PHONE_STATE to detect the incoming call and also we need a PhoneStateListener to listen to the call state and check whether the state is CALL_STATE_RINGING. If yes, then end the call using endcall() method.
BroadcastReceiver CallBlocker;
To get the Telephony services,
TelephonyManager telephonyManager;
To get the ITelephony methods:
ITelephony telephonyService;
Now look at the code snippet below which blocks calls when the checkbox is enabled.
blockAll_cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
CallBlocker =new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
//Java Reflections
Class c = null;
try {
c = Class.forName(telephonyManager.getClass().getName());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Method m = null;
try {
m = c.getDeclaredMethod("getITelephony");
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
m.setAccessible(true);
try {
telephonyService = (ITelephony)m.invoke(telephonyManager);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
telephonyManager.listen(callBlockListener, PhoneStateListener.LISTEN_CALL_STATE);
}//onReceive()
PhoneStateListener callBlockListener = new PhoneStateListener()
{
public void onCallStateChanged(int state, String incomingNumber)
{
if(state==TelephonyManager.CALL_STATE_RINGING)
{
if(blockAll_cb.isChecked())
{
try {
telephonyService.endCall();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
};
};//BroadcastReceiver
IntentFilter filter= new IntentFilter("android.intent.action.PHONE_STATE");
registerReceiver(CallBlocker, filter);
}
});
Here we use java reflections to get the instance of com.android .intenal.telephony class.
The code snippet is shown below:
Class c = null;
try {
c = Class.forName(telephonyManager.getClass().getName());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Method m = null;
try {
m = c.getDeclaredMethod("getITelephony");
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
m.setAccessible(true);
try {
telephonyService = (ITelephony)m.invoke(telephonyManager);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Now use the internal methods in the internal class to block calls as shown below:
Here endcall() is used to end a call without user intervention.
telephonyService.endCall();
Register the receiver as shown below:
IntentFilter filter= new IntentFilter("android.intent.action.PHONE_STATE");
registerReceiver(CallBlocker, filter);
We need to unregister the receiver after use. This is done in the onDestroy() callback.
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if (CallBlocker != null)
{
unregisterReceiver(CallBlocker);
CallBlocker = null;
}
}
Now the whole code:
package com.w7app.mycallcontroller;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import com.android.internal.telephony.ITelephony;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.os.Bundle;
import android.os.RemoteException;
import android.provider.ContactsContract;
import android.telephony.PhoneNumberUtils;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
public class MyCallControllerActivity extends Activity {
/** Called when the activity is first created. */
CheckBox blockAll_cb;//,blockcontacts_cb;
BroadcastReceiver CallBlocker;
TelephonyManager telephonyManager;
ITelephony telephonyService;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initviews();
blockAll_cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
CallBlocker =new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
//Java Reflections
Class c = null;
try {
c = Class.forName(telephonyManager.getClass().getName());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Method m = null;
try {
m = c.getDeclaredMethod("getITelephony");
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
m.setAccessible(true);
try {
telephonyService = (ITelephony)m.invoke(telephonyManager);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
telephonyManager.listen(callBlockListener, PhoneStateListener.LISTEN_CALL_STATE);
}//onReceive()
PhoneStateListener callBlockListener = new PhoneStateListener()
{
public void onCallStateChanged(int state, String incomingNumber)
{
if(state==TelephonyManager.CALL_STATE_RINGING)
{
if(blockAll_cb.isChecked())
{
try {
telephonyService.endCall();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
};
};//BroadcastReceiver
IntentFilter filter= new IntentFilter("android.intent.action.PHONE_STATE");
registerReceiver(CallBlocker, filter);
}
});
}
public void initviews()
{
blockAll_cb=(CheckBox)findViewById(R.id.cbBlockAll);
//blockcontacts_cb=(CheckBox)findViewById(R.id.cbBlockContacts);
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if (CallBlocker != null)
{
unregisterReceiver(CallBlocker);
CallBlocker = null;
}
}
}
Now the Screen Shots:
Hope this helped :) Happy Coding :)