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