前段时间做了一个简单的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 }
网上这种方法介绍的有很多,我这里记录一下,方便以后自己查找。有不足之处,欢迎指正!