本文所讲的内容是在Android系统中如何写程序进行电话拦截,并发出拦截提示音提醒用户,可以说此功能还是比较实用的。

       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:

       代码如下:

Java代码
  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如下:

XML/HTML代码
  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代码如下:

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代码如下:

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

       4、AndroidManifest.xml代码如下:

XML/HTML代码
  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>   
本文发布:Android开发网
本文地址:http://www.jizhuomi.com/android/example/348.html
2013年1月7日
发布:鸡啄米 分类:Android开发实例 浏览: 评论:0