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