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



No comments:
Post a Comment