• Android学习小记-----拦截电话/拒接电话,规避拒接电话前响一声或者两声的问题


      前段时间做了一个简单的Demo,拦截电话并拒接。其中遇到一个小问题,拦截会有延迟,偶尔会响一声或者两声,之后才能拒接成功。那么怎么解决响一两声的问题呢?确实还费了点时间呢!谁叫咱的技术不行呢?这里记录一下拦截来电并拒接以及响铃声的问题的处理。

      1,拦截电话需要接收来电的广播,android.intent.action.PHONE_STATE。写一个Receiver来接收广播。

     1 import android.content.BroadcastReceiver;
     2 import android.content.ComponentName;
     3 import android.content.Context;
     4 import android.content.Intent;
     5 import android.net.Uri;
     6 import android.util.Log;
     7 
     8 public class PhoneBroadcastReceiver  extends BroadcastReceiver{ 
     9        
    10     private static final String TAG = "PhoneBroadcastReceiver"; 
    11     
    12     @Override
    13     public void onReceive(Context context, Intent intent) {
    14         String action = intent.getAction();
    15         Log.i(TAG, "zjq action:"+ action);
    16         String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
    17         //如果是去电 
    18         if((Intent.ACTION_NEW_OUTGOING_CALL).equals(action)){
    19             Log.i(TAG, "call out:"+ phoneNumber);  
    20             Intent i = new Intent(Intent.ACTION_CALL,Uri.parse("tel:" + phoneNumber));
    21             i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    22             context.startActivity(i);
    23         }else if("android.intent.action.PHONE_STATE".equals(action)){ 
    24             //ACTION_PHONE_STATE_CHANGED
    25             //监听电话状态的改变
    26             Log.i(TAG, "phone state changed");
    27             
    28             //来电,判定是否拒接等操作,在这里处理:
    29             Intent inte = new Intent();
    30             inte.setComponent(new ComponentName("com.zjq.calldemo"
    31                     ,"com.zjq.calldemo.PhoneHangUpService"));
    32             inte.setAction("yd.calldemo.action.PhoneHangUpService");
    33             context.startService(inte);
    34         }
    35     }    
    36 }

    2,广播需要在Manifest.xml中注册:

    1 <receiver android:name=".PhoneBroadcastReceiver">
    2             <intent-filter >
    3                 <action android:name="android.intent.action.BOOT_COMPLETED" />
    4                 <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
    5                 <action android:name="android.intent.action.PHONE_STATE"/> 
    6             </intent-filter>
    7         </receiver>

    增加权限:

    1  <uses-permission android:name="android.permission.CALL_PHONE" >
    2  <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    3 <uses-permission android:name="android.permission.READ_PHONE_STATE" />  

    3,接下来处理广播,拦截到的来电,放在service中处理,监听来电的三种状态:

    CALL_STATE_RINGING   正在响铃,电话进来时

    CALL_STATE_IDLE   已挂断,无任何状态时

    CALL_STATE_OFFHOOK  接听,接起电话时

    延时导致的响一声问题,通过切换声音模式来处理,当判断来电为需要拒接的电话时,将铃声设置为静音,不让其响铃,待成功拒接后,回复为普通模式(回复声音)这样就规避了铃声的问题。当然方法有很多,可能我这种比较投机,通过尝试来看,这种相对简单一些。代码如下:

      1 import android.app.Service;
      2 import android.content.Context;
      3 import android.content.Intent;
      4 import android.media.AudioManager;
      5 import android.os.Handler;
      6 import android.os.IBinder;
      7 import android.os.Message;
      8 import android.os.RemoteException;
      9 import android.telephony.PhoneStateListener;
     10 import android.telephony.SmsManager;
     11 import android.telephony.TelephonyManager;
     12 import android.text.TextUtils;
     13 import android.util.Log;
     14 
     15 import com.android.internal.telephony.ITelephony;
     16 
     17 import java.lang.reflect.InvocationTargetException;
     18 import java.lang.reflect.Method;
     19 import java.util.List;
     20 
     21 public class PhoneHangUpService extends Service {
     22     private static final String TAG = "PhoneHangUpService";
     23     private static final int MSG_DELETE_CALL_LOG = 1;
     24 
     25     private MyPhoneStateListener mPhoneStateListener;
     26     private TelephonyManager mTelephonyManager;
     27     private Context context;
     28     public AudioManager am ;
     29     private Handler mHandler = new Handler() {
     30         @Override
     31         public void dispatchMessage(Message msg) {
     32             switch (msg.what) {
     33                 case MSG_DELETE_CALL_LOG:
     34                     String number = (String) msg.obj;
     35 //
     36                     break;
     37             }
     38         }
     39 
     40     };
     41 
     42     @Override
     43     public void onCreate() {
     44         super.onCreate();
     45         Log.i(TAG, "onCreate");
     46         context = this;
     47         //声明监听类,在监听类中实现具体处理
     48         mPhoneStateListener = new MyPhoneStateListener();
     49         mTelephonyManager = (TelephonyManager) getSystemService(Service.TELEPHONY_SERVICE);
     50         mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
     51         
     52         am = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
     53     }
     54 
     55     @Override
     56     public void onDestroy() {
     57         super.onDestroy();
     58         mTelephonyManager.listen(mPhoneStateListener, 0);
     59     }
     60 
     61     @Override
     62     public int onStartCommand(Intent intent, int flags, int startId) {
     63         return super.onStartCommand(intent, flags, startId);
     64     }
     65 
     66     @Override
     67     public IBinder onBind(Intent intent) {
     68         return null;
     69     }
     70 
     71     //挂断电话方法
     72     private boolean hangUp() {
     73         Class<TelephonyManager> c = TelephonyManager.class;
     74         ITelephony iTelephony = null;
     75         Method getITelephonyMethod = null;
     76         try {
     77             getITelephonyMethod = c.getDeclaredMethod("getITelephony", (Class[]) null);
     78             getITelephonyMethod.setAccessible(true);
     79         } catch (SecurityException e) {
     80             e.printStackTrace();
     81         } catch (NoSuchMethodException e) {
     82             e.printStackTrace();
     83         }
     84         try {
     85             iTelephony = (ITelephony)
     86                     getITelephonyMethod.invoke(mTelephonyManager, (Object[]) null);
     87         } catch (IllegalArgumentException e) {
     88             e.printStackTrace();
     89         } catch (IllegalAccessException e) {
     90             e.printStackTrace();
     91         } catch (InvocationTargetException e) {
     92             e.printStackTrace();
     93         }
     94         if (iTelephony != null) {
     95             boolean isSuccess = false;
     96             try {
     97                 isSuccess = iTelephony.endCall();
     98                 am.setRingerMode(AudioManager.RINGER_MODE_NORMAL);//恢复会普通模式,恢复声音
     99                 
    100             } catch (RemoteException e) {
    101                 e.printStackTrace();
    102             }
    103             return isSuccess;
    104         }
    105         return true;
    106     }
    107     
    108     //监听类,监听来电
    109     private final class MyPhoneStateListener extends android.telephony.PhoneStateListener {
    110         @Override
    111         public void onCallStateChanged(int state, String incomingNumber) {
    112             super.onCallStateChanged(state, incomingNumber);
    113             Log.i(TAG, "zjq Number:" + incomingNumber);
    114             if (TelephonyManager.CALL_STATE_RINGING == state) {
    115                 Log.i(TAG, "zhangjieqiong state:CALL_STATE_RINGING:" + incomingNumber);
    116                 if (!TextUtils.isEmpty(incomingNumber) && PhoneUtils.isPhoneNumber(incomingNumber)) {
    117                     //拒接电话 当号码为135*****182时拒接
    118                     if ("135*****182".equals(incomingNumber)) {
    119                         am.setRingerMode(AudioManager.RINGER_MODE_SILENT);//设置为静音模式,解决延迟导致的响铃问题
    120                         Log.i(TAG, "zjq:the number is endcallnumber:"+incomingNumber);
    121                         if (hangUp()) {
    122                             Log.i(TAG, "zjq end call success ");
    123                             Message msg = mHandler.obtainMessage(MSG_DELETE_CALL_LOG);
    124                             msg.obj = incomingNumber;
    125                             mHandler.sendMessageDelayed(msg, 2000);
    126                             //发送一条短信,提示拒接成功
    127                             handleSetSystemParamSms(incomingNumber, incomingNumber +" endcall success");
    128                         }
    129                     }
    130                 }
    131             }else if(TelephonyManager.CALL_STATE_IDLE == state){
    132                 //挂断
    133                 //挂断电话可以在这里处理
    134                 Log.i(TAG, "zjq state: hang up(endcall)");
    135             }else if(TelephonyManager.CALL_STATE_OFFHOOK == state){
    136                 //接听
    137                 Log.i(TAG, "zjq state: answer:"+ incomingNumber);
    138             }
    139         }
    140 
    141     }
    142 
    143     
    144     //发送短信方法
    145     private void handleSetSystemParamSms(String phone, String body) {
    146         Log.d(TAG, "user get location");
    147         String msg = body ;
    148         if (msg != null) {
    149             Log.d(TAG, "msgBody lenth = " + msg.length());
    150             SmsManager sms = SmsManager.getDefault();
    151             List<String> texts = sms.divideMessage(msg);
    152             for (String text : texts) {
    153                 Log.d(TAG, "zjq send sms to:" + phone);
    154                 sms.sendTextMessage(phone, null, text, null, null);
    155             }
    156         }
    157     }
    158 }

    4,不能忘记增加aidl,通过调用系统接口来拒接电话,方法:iTelephony.endCall():

    其中ITelephony.aidl中内容如下(加入常用的几种方法即可,这个不是自己写的,手机系统的接口类,直接拿来用了,嘿嘿)

     1 package com.android.internal.telephony;
     2 
     3 import android.os.Bundle;
     4 import java.util.List;
     5 
     6 /**
     7  * Interface used to interact with the phone.  Mostly this is used by the
     8  * TelephonyManager class.  A few places are still using this directly.
     9  * Please clean them up if possible and use TelephonyManager insteadl.
    10  *
    11  * {@hide}
    12  */
    13 interface ITelephony {
    14 
    15     /**
    16      * End call or go to the Home screen
    17      *
    18      * @return whether it hung up
    19      */
    20     boolean endCall();
    21     
    22      /**
    23      * Check if the phone is idle.
    24      * @return true if the phone state is IDLE.
    25      */
    26     boolean isIdle();
    27 }

    网上这种方法介绍的有很多,我这里记录一下,方便以后自己查找。有不足之处,欢迎指正!

  • 相关阅读:
    Careercup
    【LeetCode & 剑指offer刷题】树题1:二叉树的遍历总结(前序、中序、后序、层序、 之字形层序、垂直遍历)
    【LeetCode & 剑指offer刷题】链表题11:Palindrome Linked List
    【LeetCode & 剑指offer刷题】链表题9:Add Two Numbers
    【LeetCode & 剑指offer刷题】链表题10:328 Odd Even Linked List
    【LeetCode & 剑指offer刷题】链表题8:35 复杂链表的复制(138. Copy List with Random Pointer)
    【LeetCode & 剑指offer刷题】链表题6:23 有环链表问题-链表中环的入口结点(141. Linked List Cycle)
    【LeetCode & 剑指offer刷题】链表题7:25 合并两个排序的链表(系列)(21. Merge Two Sorted Lists)
    【LeetCode & 剑指offer刷题】链表题5:52 两个链表的第一个公共结点(Intersection of Two Linked Lists)
    【LeetCode & 剑指offer刷题】链表题4:22 删除链表中倒数第k个结点(19. Remove Nth Node From End of List)
  • 原文地址:https://www.cnblogs.com/zjqlogs/p/5505314.html
Copyright © 2020-2023  润新知