1. 电话拦截
这个功能大家可能都知道了,就是利用反射原理调用ITelephony的隐藏方法来实现。这个就不说了,在附件的代码里有。

2.拦截后提示忙音/空号/已关机/已停机
这个功能其实是要用到MMI指令,具体如何设置呼叫转移的指定可以参考这里 http://baike.baidu.com/view/206402.html?fromTaglist 。
在本文中我们会用到“遇忙转移”转移的功能。中国移动的设置方式是 **67#电话号码#,取消方式为 ##67#。”无条件转移“用21代替67即可。这两个指令可以直接在手机的拨号界面输入并拨号测试。ITelephony的endcall方法挂断电话后,会提示电话忙。如果事前设置好了忙时转移到一个空号/已关机/已停机的电话号码,就会提示您拨的电话号码是空号/已关机/已停机。
其实大家可以下载 xxx卫士看下,它设置来电拒接模式后,都是会启动设置MMI指令的界面。然后再去“设置》通话设置》来电转接”,看看 “占线时转接” 设置好的电话号码,就可以知道空号/已关机/已停机对应的电话号码是什么了。

1. 修改一下BLOCKED_NUMBER这个变量值,把它设置为你要测试拦截的电话号码。
2. 全部功能是在一个Activity里实现的,所以大家要先运行这个Activity,然后点击“设置呼叫转移”,设置好呼叫转移后,不要关闭这个Activity,关了就拦截不了电话了。有心的朋友可以自己去写一个Service在后台运行拦截功能。
实现方式1:
代码如下:

  1. package net.toeach.android.callforwarding;  
  2.  
  3. import java.lang.reflect.Method;  
  4.  
  5. import android.app.Activity;  
  6. import android.content.BroadcastReceiver;  
  7. import android.content.Context;  
  8. import android.content.Intent;  
  9. import android.content.IntentFilter;  
  10. import android.media.AudioManager;  
  11. import android.net.Uri;  
  12. import android.os.Bundle;  
  13. import android.os.Handler;  
  14. import android.os.Message;  
  15. import android.os.RemoteException;  
  16. import android.telephony.TelephonyManager;  
  17. import android.util.Log;  
  18. import android.view.View;  
  19. import android.view.View.OnClickListener;  
  20.  
  21. import com.android.internal.telephony.ITelephony;  
  22.  
  23. /**  
  24.  * 演示如何设置呼叫转移,拦截电话(拦截后提示为空号)的例子  
  25.  * @author Tony from ToEach.  
  26.  * @email wan1976@21cn.com  
  27.  */ 
  28. public class MainActivity extends Activity {  
  29.  private static final String TAG = MainActivity.class.getSimpleName();  
  30.     
  31.  private final static int OP_REGISTER = 100;  
  32.  private final static int OP_CANCEL = 200;  
  33.    
  34.  private final static String BLOCKED_NUMBER = "1892501xxxx";//要拦截的号码  
  35.  //占线时转移,这里13800000000是空号,所以会提示所拨的号码为空号  
  36.     private final String ENABLE_SERVICE = "tel:**67*13800000000%23";  
  37.     //占线时转移  
  38.     private final String DISABLE_SERVICE = "tel:%23%2367%23";  
  39.  
  40.  private IncomingCallReceiver mReceiver;  
  41.     private ITelephony iTelephony;  
  42.     private AudioManager mAudioManager;  
  43.    
  44.     @Override 
  45.     public void onCreate(Bundle savedInstanceState) {  
  46.         super.onCreate(savedInstanceState);  
  47.         setContentView(R.layout.main);  
  48.          
  49.         findViewById(R.id.btnEnable).setOnClickListener(new OnClickListener(){  
  50.    public void onClick(View v) {  
  51.           //设置呼叫转移  
  52.           Message message = mHandler.obtainMessage();  
  53.     message.what = OP_REGISTER;  
  54.     mHandler.dispatchMessage(message);  
  55.    }  
  56.         });  
  57.          
  58.         findViewById(R.id.btnDisable).setOnClickListener(new OnClickListener(){  
  59.    public void onClick(View v) {  
  60.     //取消呼叫转移  
  61.              Message message = mHandler.obtainMessage();  
  62.        message.what = OP_CANCEL;  
  63.        mHandler.dispatchMessage(message);  
  64.    }  
  65.         });  
  66.          
  67.         mReceiver = new IncomingCallReceiver();  
  68.   IntentFilter filter = new IntentFilter("android.intent.action.PHONE_STATE");      
  69.         registerReceiver(mReceiver, filter);// 注册BroadcastReceiver   
  70.          
  71.         mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);  
  72.          
  73.         //利用反射获取隐藏的endcall方法  
  74.         TelephonyManager telephonyMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);  
  75.   try {  
  76.    Method getITelephonyMethod = TelephonyManager.class.getDeclaredMethod("getITelephony", (Class[]) null);  
  77.    getITelephonyMethod.setAccessible(true);  
  78.    iTelephony = (ITelephony) getITelephonyMethod.invoke(telephonyMgr, (Object[]) null);  
  79.      } catch (Exception e) {  
  80.       e.printStackTrace();  
  81.      }  
  82.     }  
  83.      
  84.     private Handler mHandler = new Handler() {  
  85.   public void handleMessage(Message response) {  
  86.       int what = response.what;  
  87.       switch(what) {  
  88.        case OP_REGISTER:{  
  89.         Intent i = new Intent(Intent.ACTION_CALL);  
  90.               i.setData(Uri.parse(ENABLE_SERVICE));  
  91.               startActivity(i);  
  92.         break;  
  93.        }  
  94.        case OP_CANCEL:{  
  95.         Intent i = new Intent(Intent.ACTION_CALL);  
  96.               i.setData(Uri.parse(DISABLE_SERVICE));  
  97.               startActivity(i);  
  98.         break;  
  99.        }  
  100.       }  
  101.   }  
  102.  };  
  103.    
  104.  private class IncomingCallReceiver extends BroadcastReceiver{  
  105.   @Override 
  106.   public void onReceive(Context context, Intent intent) {  
  107.    String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);  
  108.          Log.i(TAG, "State: "+ state);  
  109.           
  110.    String number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);  
  111.          Log.d(TAG, "Incomng Number: " + number);  
  112.           
  113.          if(state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING)){//电话正在响铃            
  114.           if(number.equals(BLOCKED_NUMBER)){//拦截指定的电话号码  
  115.            //先静音处理  
  116.            mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);  
  117.            Log.d(TAG, "Turn ringtone silent");  
  118.              
  119.            try {  
  120.             //挂断电话  
  121.       iTelephony.endCall();  
  122.      } catch (RemoteException e) {  
  123.       e.printStackTrace();  
  124.      }  
  125.        
  126.      //再恢复正常铃声  
  127.                  mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);  
  128.           }  
  129.          }  
  130.   }  
  131.  }  
  132. }   

AndroidManifest.xml如下:
 

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android " 
  3.       package="net.toeach.android.callforwarding" 
  4.       android:versionCode="1" 
  5.       android:versionName="1.0"> 
  6.     <application android:icon="@drawable/icon" android:label="@string/app_name"> 
  7.         <activity android:name=".MainActivity" 
  8.                   android:label="@string/app_name"> 
  9.             <intent-filter> 
  10.                 <action android:name="android.intent.action.MAIN" /> 
  11.                 <category android:name="android.intent.category.LAUNCHER" /> 
  12.             </intent-filter> 
  13.         </activity> 
  14.  
  15.     </application> 
  16.     <uses-sdk android:minSdkVersion="8" /> 
  17.      
  18.     <uses-permission android:name="android.permission.READ_PHONE_STATE"/> 
  19.     <uses-permission android:name="android.permission.CALL_PHONE"/> 
  20.  
  21. </manifest>   

实现方式2: 代码如下:

1,建立包android.refuseCalling , refuseCalling.java代码如下:

  1. package android.refuseCalling;  
  2.  
  3. import android.app.Activity;  
  4. import android.net.Uri;  
  5. import android.os.Bundle;  
  6.  
  7. import java.lang.reflect.InvocationTargetException;  
  8. import java.lang.reflect.Method;  
  9.  
  10. import android.content.Context;  
  11. import android.content.Intent;  
  12. import android.os.RemoteException;  
  13. import android.telephony.PhoneStateListener;  
  14. import android.telephony.TelephonyManager;  
  15. import android.util.Log;  
  16. import android.widget.TextView;  
  17. import com.android.internal.telephony.ITelephony;  
  18.  
  19. public class refuseCalling extends Activity {  
  20.  
  21.     private static final String TAG = "Telephony";  
  22.     private TextView view = null;  
  23.     private TelephonyManager tManager = null;  
  24.     private ITelephony iTelephony  = null;  
  25.       
  26.      //占线时转移,提示所拨的号码为空号  
  27.     private final String ENABLE_SERVICE = "tel:**67*13800000000%23";  
  28.      //占线时转移,提示所拨的号码为关机  
  29.     private final String ENABLE_POWEROFF_SERVICE = "tel:**67*13810538911%23";  
  30.     //占线时转移,提示所拨的号码为停机  
  31.     private final String ENABLE_STOP_SERVICE = "tel:**21*13701110216%23";  
  32.       
  33.     //占线时转移  
  34.     private final String DISABLE_SERVICE = "tel:%23%2321%23";  
  35.  
  36.     @Override 
  37.     protected void onCreate(Bundle savedInstanceState) {  
  38.         super.onCreate(savedInstanceState);  
  39.           
  40.         //打开监听电话功能  
  41.         TelephonyManager mTelephonyMgr = (TelephonyManager) this 
  42.                 .getSystemService(Context.TELEPHONY_SERVICE);  
  43.         mTelephonyMgr.listen(new TeleListener(),  
  44.                 PhoneStateListener.LISTEN_CALL_STATE);  
  45.           
  46.         //gui  
  47.         view = new TextView(this);  
  48.         view.setText("listen the state of phone\n");  
  49.         setContentView(view);  
  50.           
  51.         tManager = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);  
  52.         //初始化iTelephony  
  53.         Class <TelephonyManager> c = TelephonyManager.class;  
  54.         Method getITelephonyMethod = null;  
  55.         try {  
  56.         getITelephonyMethod = c.getDeclaredMethod("getITelephony", (Class[])null);  
  57.         getITelephonyMethod.setAccessible(true);  
  58.         } catch (SecurityException e) {  
  59.         // TODO Auto-generated catch block  
  60.         e.printStackTrace();  
  61.         } catch (NoSuchMethodException e) {  
  62.         // TODO Auto-generated catch block  
  63.         e.printStackTrace();  
  64.         }  
  65.  
  66.         try {  
  67.         iTelephony = (ITelephony) getITelephonyMethod.invoke(tManager, (Object[])null);  
  68.         } catch (IllegalArgumentException e) {  
  69.         // TODO Auto-generated catch block  
  70.         e.printStackTrace();  
  71.         } catch (IllegalAccessException e) {  
  72.         // TODO Auto-generated catch block  
  73.         e.printStackTrace();  
  74.         } catch (InvocationTargetException e) {  
  75.         // TODO Auto-generated catch block  
  76.         e.printStackTrace();  
  77.         }  
  78.           
  79.         //启用空号提示  
  80.         Intent i = new Intent(Intent.ACTION_CALL);  
  81.         i.setData(Uri.parse(ENABLE_STOP_SERVICE));  
  82.         startActivity(i);  
  83.         Log.v(TAG, "启用空号提示");  
  84.     }  
  85.  
  86.     class TeleListener extends PhoneStateListener {  
  87.  
  88.         @Override 
  89.         public void onCallStateChanged(int state, String incomingNumber) {  
  90.             super.onCallStateChanged(state, incomingNumber);  
  91.             switch (state) {  
  92.             case TelephonyManager.CALL_STATE_IDLE: {  
  93.                 Log.e(TAG, "CALL_STATE_IDLE");  
  94.                 view.append("CALL_STATE_IDLE " + "\n");  
  95.                 break;  
  96.             }  
  97.             case TelephonyManager.CALL_STATE_OFFHOOK: {  
  98.                 Log.e(TAG, "CALL_STATE_OFFHOOK");  
  99.                 view.append("CALL_STATE_OFFHOOK" + "\n");  
  100.                 break;  
  101.             }  
  102.             case TelephonyManager.CALL_STATE_RINGING: {  
  103.                 Log.e(TAG, "CALL_STATE_RINGING");  
  104.                 view.append("CALL_STATE_RINGING" + "\n");  
  105.                 try {  
  106.                     iTelephony.endCall();                      
  107.                 } catch (RemoteException e1) {  
  108.                     // TODO Auto-generated catch block  
  109.                     e1.printStackTrace();  
  110.                 }                  
  111.                 break;  
  112.             }  
  113.             default:  
  114.                 break;  
  115.             }  
  116.         }  
  117.     }  
  118.     protected void onStop() {  
  119.         super.onStop();  
  120.         }  
  121.     protected void onDestroy() {  
  122.         super.onDestroy();  
  123.         finish();  
  124.         Intent i = new Intent(Intent.ACTION_CALL);  
  125.         i.setData(Uri.parse(DISABLE_SERVICE));  
  126.         startActivity(i);  
  127.         }  
  128. }  

2,建立包android.telephony

NeighboringCellInfo.aidl代码如下:

package android.telephony;


3,建立包 com.android.internal.telephony,

ITelephony.aidl代码如下:

  1. /*  
  2.  *  
  3.  * Licensed under the  android License, Version 2.0 (the "License");  
  4.  * you may not use this file except in compliance with the License.  
  5.  * You may obtain a copy of the License at  
  6.  *  
  7.  *      http://www.apache.org/licenses/LICENSE-2.0  
  8.  *  
  9.  * Unless required by applicable law or agreed to in writing, software  
  10.  * distributed under the License is distributed on an "AS IS" BASIS,  
  11.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
  12.  * See the License for the specific language governing permissions and  
  13.  * limitations under the License.  
  14.  */ 
  15.  
  16. package com.android.internal.telephony;  
  17.  
  18. import android.os.Bundle;  
  19. import java.util.List;  
  20. import android.telephony.NeighboringCellInfo;  
  21. //import com.FrameSpeed.NeighboringCellInfo;  
  22.  
  23. /**  
  24.  * Interface used to interact with the phone.  Mostly this is used by the  
  25.  * TelephonyManager class.  A few places are still using this directly.  
  26.  * Please clean them up if possible and use TelephonyManager insteadl.  
  27.  *  
  28.  * {@hide}  
  29.  */ 
  30. interface ITelephony {  
  31.  
  32.     /**  
  33.      * Dial a number. This doesn't place the call. It displays  
  34.      * the Dialer screen.  
  35.      * @param number the number to be dialed. If null, this  
  36.      * would display the Dialer screen with no number pre-filled.  
  37.      */ 
  38.     void dial(String number);  
  39.  
  40.     /**  
  41.      * Place a call to the specified number.  
  42.      * @param number the number to be called.  
  43.      */ 
  44.     void call(String number);  
  45.  
  46.     /**  
  47.      * If there is currently a call in progress, show the call screen.  
  48.      * The DTMF dialpad may or may not be visible initially, depending on  
  49.      * whether it was up when the user last exited the InCallScreen.  
  50.      *  
  51.      * @return true if the call screen was shown.  
  52.      */ 
  53.     boolean showCallScreen();  
  54.  
  55.     /**  
  56.      * Variation of showCallScreen() that also specifies whether the  
  57.      * DTMF dialpad should be initially visible when the InCallScreen  
  58.      * comes up.  
  59.      *  
  60.      * @param showDialpad if true, make the dialpad visible initially,  
  61.      *                    otherwise hide the dialpad initially.  
  62.      * @return true if the call screen was shown.  
  63.      *  
  64.      * @see showCallScreen  
  65.      */ 
  66.     boolean showCallScreenWithDialpad(boolean showDialpad);  
  67.  
  68.     /**  
  69.      * End call if there is a call in progress, otherwise does nothing.  
  70.      *  
  71.      * @return whether it hung up  
  72.      */ 
  73.     boolean endCall();  
  74.  
  75.     /**  
  76.      * Answer the currently-ringing call.  
  77.      *  
  78.      * If there's already a current active call, that call will be  
  79.      * automatically put on hold.  If both lines are currently in use, the  
  80.      * current active call will be ended.  
  81.      *  
  82.      * TODO: provide a flag to let the caller specify what policy to use  
  83.      * if both lines are in use.  (The current behavior is hardwired to  
  84.      * "answer incoming, end ongoing", which is how the CALL button  
  85.      * is specced to behave.)  
  86.      *  
  87.      * TODO: this should be a oneway call (especially since it's called  
  88.      * directly from the key queue thread).  
  89.      */ 
  90.     void answerRingingCall();  
  91.  
  92.     /**  
  93.      * Silence the ringer if an incoming call is currently ringing.  
  94.      * (If vibrating, stop the vibrator also.)  
  95.      *  
  96.      * It's safe to call this if the ringer has already been silenced, or  
  97.      * even if there's no incoming call.  (If so, this method will do nothing.)  
  98.      *  
  99.      * TODO: this should be a oneway call too (see above).  
  100.      *       (Actually *all* the methods here that return void can  
  101.      *       probably be oneway.)  
  102.      */ 
  103.     void silenceRinger();  
  104.  
  105.     /**  
  106.      * Check if we are in either an active or holding call  
  107.      * @return true if the phone state is OFFHOOK.  
  108.      */ 
  109.     boolean isOffhook();  
  110.  
  111.     /**  
  112.      * Check if an incoming phone call is ringing or call waiting.  
  113.      * @return true if the phone state is RINGING.  
  114.      */ 
  115.     boolean isRinging();  
  116.  
  117.     /**  
  118.      * Check if the phone is idle.  
  119.      * @return true if the phone state is IDLE.  
  120.      */ 
  121.     boolean isIdle();  
  122.  
  123.     /**  
  124.      * Check to see if the radio is on or not.  
  125.      * @return returns true if the radio is on.  
  126.      */ 
  127.     boolean isRadioOn();  
  128.  
  129.     /**  
  130.      * Check if the SIM pin lock is enabled.  
  131.      * @return true if the SIM pin lock is enabled.  
  132.      */ 
  133.     boolean isSimPinEnabled();  
  134.  
  135.     /**  
  136.      * Cancels the missed calls notification.  
  137.      */ 
  138.     void cancelMissedCallsNotification();  
  139.  
  140.     /**  
  141.      * Supply a pin to unlock the SIM.  Blocks until a result is determined.  
  142.      * @param pin The pin to check.  
  143.      * @return whether the operation was a success.  
  144.      */ 
  145.     boolean supplyPin(String pin);  
  146.       
  147.      /**  
  148.      * [ASD2-ES1|Connice|2011.04.14]  
  149.      */ 
  150.     boolean supplyPuk(String puk, String pin);  
  151.  
  152.     /**  
  153.      * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated  
  154.      * without SEND (so <code>dial</code> is not appropriate).  
  155.      *  
  156.      * @param dialString the MMI command to be executed.  
  157.      * @return true if MMI command is executed.  
  158.      */ 
  159.     boolean handlePinMmi(String dialString);  
  160.  
  161.     /**  
  162.      * Toggles the radio on or off.  
  163.      */ 
  164.     void toggleRadioOnOff();  
  165.  
  166.     /**  
  167.      * Set the radio to on or off  
  168.      */ 
  169.     boolean setRadio(boolean turnOn);  
  170.  
  171.     /**  
  172.      * Request to update location information in service state  
  173.      */ 
  174.     void updateServiceLocation();  
  175.  
  176.     /**  
  177.      * Enable location update notifications.  
  178.      */ 
  179.     void enableLocationUpdates();  
  180.  
  181.     /**  
  182.      * Disable location update notifications.  
  183.      */ 
  184.     void disableLocationUpdates();  
  185.  
  186.     /**  
  187.      * Enable a specific APN type.  
  188.      */ 
  189.     int enableApnType(String type);  
  190.  
  191.     /**  
  192.      * Disable a specific APN type.  
  193.      */ 
  194.     int disableApnType(String type);  
  195.  
  196.     /**  
  197.      * Allow mobile data connections.  
  198.      */ 
  199.     boolean enableDataConnectivity();  
  200.  
  201.     /**  
  202.      * Disallow mobile data connections.  
  203.      */ 
  204.     boolean disableDataConnectivity();  
  205.  
  206.     /**  
  207.      * Report whether data connectivity is possible.  
  208.      */ 
  209.     boolean isDataConnectivityPossible();  
  210.  
  211.     Bundle getCellLocation();  
  212.  
  213.     /**  
  214.      * Returns the neighboring cell information of the device.  
  215.      */ 
  216.     List<NeighboringCellInfo> getNeighboringCellInfo();  
  217.  
  218.      int getCallState();  
  219.      int getDataActivity();  
  220.      int getDataState();  
  221.  
  222.     /**  
  223.      * Returns the current active phone type as integer.  
  224.      * Returns TelephonyManager.PHONE_TYPE_CDMA if RILConstants.CDMA_PHONE  
  225.      * and TelephonyManager.PHONE_TYPE_GSM if RILConstants.GSM_PHONE  
  226.      */ 
  227.     int getActivePhoneType();  
  228.  
  229.     /**  
  230.      * Returns the CDMA ERI icon index to display  
  231.      */ 
  232.     int getCdmaEriIconIndex();  
  233.  
  234.     /**  
  235.      * Returns the CDMA ERI icon mode,  
  236.      * 0 - ON  
  237.      * 1 - FLASHING  
  238.      */ 
  239.     int getCdmaEriIconMode();  
  240.  
  241.     /**  
  242.      * Returns the CDMA ERI text,  
  243.      */ 
  244.     String getCdmaEriText();  
  245.  
  246.     /**  
  247.      * Returns true if OTA service provisioning needs to run.  
  248.      * Only relevant on some technologies, others will always  
  249.      * return false.  
  250.      */ 
  251.     boolean needsOtaServiceProvisioning();  
  252.  
  253.     /**  
  254.       * Returns the unread count of voicemails  
  255.       */ 
  256.     int getVoiceMessageCount();  
  257.  
  258.     /**  
  259.       * Returns the network type  
  260.       */ 
  261.     int getNetworkType();  
  262.       
  263.     /**  
  264.      * Return true if an ICC card is present  
  265.      */ 
  266.     boolean hasIccCard();  
  267. }  
  268.  
  269. parcelable NeighboringCellInfo; 

4,AndroidManifest.xml代码如下

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android" 
  3.       package="android.refuseCalling" 
  4.       android:versionCode="1" 
  5.       android:versionName="1.0"> 
  6.      <uses-permission android:name="android.permission.READ_PHONE_STATE" />    
  7.      <uses-permission android:name="android.permission.CALL_PHONE" />    
  8.      <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />             
  9.  
  10.     <application android:icon="@drawable/icon" android:label="@string/app_name"> 
  11.         <activity android:name=".refuseCalling" 
  12.                   android:label="@string/app_name"> 
  13.             <intent-filter> 
  14.                 <action android:name="android.intent.action.MAIN" /> 
  15.                 <category android:name="android.intent.category.LAUNCHER" /> 
  16.             </intent-filter> 
  17.         </activity> 
  18.  
  19.     </application> 
  20. </manifest>