Android电话拦截实现以及TelephonyManager监听的取消

jopen 9年前

本篇博客目的:实现电话的拦截

会遇到的问题:android studio下AIDL的使用,TelephonyManager.Listen()的监听取消。

首先,电话状态监听需要涉及到系统服务TelephonyManager,我们需要获取到他的实例

mTelephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);

之后我们就可以向他添加状态改变的监听,需要重写监听器PhoneStateListener

他的state值有如下几种

TelephonyManager.CALL_STATE_IDLE:  空闲状态
TelephonyManager.CALL_STATE_RINGING:  响铃状态
TelephonyManager.CALL_STATE_OFFHOOK:  挂掉电话

class MyPhoneListener extends PhoneStateListener{                @Override              public void onCallStateChanged(int state, String incomingNumber) {                  if(state==TelephonyManager.CALL_STATE_RINGING){                      endCall();                      super.onCallStateChanged(state,incomingNumber);                  }              }          }
这里我给他加了个模式来设置监听与取消。

我们需要用一个FLAG : PhoneStateListener.LISTEN_NONE来取消监听。如果新加监听器,会同时监听

private void setTelephonyListener(int mode){          if(mode==INTERRUPTED){              mTelephonyManager.listen(mMyPhoneListener,PhoneStateListener.LISTEN_CALL_STATE);          }else{              mTelephonyManager.listen(mMyPhoneListener,PhoneStateListener.LISTEN_NONE);          }      }
好了,以上就是状态监听的步骤。

那么如何实现电话的拦截呢?由于安卓隐藏了PHONE类的API,所以我们需要用AIDL将它的方法反射出来。

1,新建AIDL文件,ITelephony.aidl。注意包名为com.android.internal.telephony,不可更改,此时需要rebuild project才能正常使用。

内容如下:

package com.android.internal.telephony;       /**        * Interface used to interact with the phone.  Mostly this is used by the        * TelephonyManager class.  A few places are still using this directly.        * Please clean them up if possible and use TelephonyManager instead.        * {@hide}        */         interface ITelephony {           /**            * End call or go to the Home screen      * @return whether it hung up           */         boolean endCall();                    /**              * Answer the currently-ringing call.              *              * If there's already a current active call, that call will be              * automatically put on hold.  If both lines are currently in use, the             * current active call will be ended.              *            * TODO: provide a flag to let the caller specify what policy to use             * if both lines are in use.  (The current behavior is hardwired to             * "answer incoming, end ongoing", which is how the CALL button              * is specced to behave.)              *              * TODO: this should be a oneway call (especially since it's called             * directly from the key queue thread).              */             void answerRingingCall();                 /**         * Allow mobile data connections.         */        boolean enableDataConnectivity();            /**         * Disallow mobile data connections.         */        boolean disableDataConnectivity();            /**         * Report whether data connectivity is possible.         */        boolean isDataConnectivityPossible();    }
之后来反射出来endcall方法,当来电的时候 即可对电话进行拦截

private void endCall()      {          Class<TelephonyManager> c = TelephonyManager.class;          try          {              Method getITelephonyMethod = c.getDeclaredMethod("getITelephony", (Class[]) null);              getITelephonyMethod.setAccessible(true);              ITelephony iTelephony = null;              iTelephony = (ITelephony) getITelephonyMethod.invoke(mTelephonyManager, (Object[]) null);              iTelephony.endCall();                Log.i("wing", "iTelePhony endcall");          }          catch (Exception e)          {                Log.i("wing", "iTelePhony endcall failed"+e.getMessage()    );          }      }
以上就是我的经验和总结,欢迎大家讨论。



来自: http://blog.csdn.net/wingichoy/article/details/48555809