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 }

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

原文地址:https://www.cnblogs.com/zjqlogs/p/5505314.html