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

由于毕业设计题目涉及到电话拦截这一块。所以鼓捣了一下。遇到了一些问题,总结一下,以免忘记,也希望能帮助其他新人们。

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

会遇到的问题: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()    );
        }
    }
以上就是我的经验和总结,欢迎大家讨论。



原文地址:https://www.cnblogs.com/muyuge/p/6333566.html