Monday, November 9, 2015

Blocking a call without user intervention in android with an example

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