一、首先在manifest.xml文件中获取监听电话权限,注册监听电话的Activity
1 <receiver android:name=".PhoneReceiver"> 2 <intent-filter android:priority="1000"> 3 <action android:name="android.intent.action.PHONE_STATE"/> 4 <action android:name="android.intent.action.NEW_OUTGOING_CALL" /> 5 </intent-filter> 6 </receiver>
1 1 <!-- 添加访问手机电话状态的权限 --> 2 2 <uses-permission android:name="android.permission.READ_PHONE_STATE" />
二、实现过程中主要问题为接口ITelephony,是Android系统Phone类中TelephonyManager提供给上层应用程序用户与telephony进行操作交互的接口。,必须通过AIDL(Android Interface Definition Language,即Android接口定义语言)。
具体操作就是在src文件在新建一个包,包名为:com.android.internal.telephony,在这个包里面新建一个名为ITelephony.aidl ,本文主要通过接口获得endCall()函数来拦截电话。最后rebuild project一下,在android studio 本工程的packets同目录下自动生成ITelephony.java文件
1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.internal.telephony; 17 import android.os.Bundle; 18 import java.util.List; 19 import android.telephony.NeighboringCellInfo; 20 /** 21 * Interface used to interact with the phone. Mostly this is used by the 22 * TelephonyManager class. A few places are still using this directly. 23 * Please clean them up if possible and use TelephonyManager insteadl. 24 * 25 * {@hide} 26 */ 27 interface ITelephony { 28 /** 29 * Dial a number. This doesn't place the call. It displays 30 * the Dialer screen. 31 * @param number the number to be dialed. If null, this 32 * would display the Dialer screen with no number pre-filled. 33 */ 34 void dial(String number); 35 /** 36 * Place a call to the specified number. 37 * @param number the number to be called. 38 */ 39 void call(String number); 40 /** 41 * If there is currently a call in progress, show the call screen. 42 * The DTMF dialpad may or may not be visible initially, depending on 43 * whether it was up when the user last exited the InCallScreen. 44 * 45 * @return true if the call screen was shown. 46 */ 47 boolean showCallScreen(); 48 /** 49 * Variation of showCallScreen() that also specifies whether the 50 * DTMF dialpad should be initially visible when the InCallScreen 51 * comes up. 52 * 53 * @param showDialpad if true, make the dialpad visible initially, 54 * otherwise hide the dialpad initially. 55 * @return true if the call screen was shown. 56 * 57 * @see showCallScreen 58 */ 59 boolean showCallScreenWithDialpad(boolean showDialpad); 60 /** 61 * End call or go to the Home screen 62 * 63 * @return whether it hung up 64 */ 65 boolean endCall(); 66 /** 67 * Answer the currently-ringing call. 68 * 69 * If there's already a current active call, that call will be 70 * automatically put on hold. If both lines are currently in use, the 71 * current active call will be ended. 72 * 73 * TODO: provide a flag to let the caller specify what policy to use 74 * if both lines are in use. (The current behavior is hardwired to 75 * "answer incoming, end ongoing", which is how the CALL button 76 * is specced to behave.) 77 * 78 * TODO: this should be a oneway call (especially since it's called 79 * directly from the key queue thread). 80 */ 81 void answerRingingCall(); 82 /** 83 * Silence the ringer if an incoming call is currently ringing. 84 * (If vibrating, stop the vibrator also.) 85 * 86 * It's safe to call this if the ringer has already been silenced, or 87 * even if there's no incoming call. (If so, this method will do nothing.) 88 * 89 * TODO: this should be a oneway call too (see above). 90 * (Actually *all* the methods here that return void can 91 * probably be oneway.) 92 */ 93 void silenceRinger(); 94 /** 95 * Check if we are in either an active or holding call 96 * @return true if the phone state is OFFHOOK. 97 */ 98 boolean isOffhook(); 99 /** 100 * Check if an incoming phone call is ringing or call waiting. 101 * @return true if the phone state is RINGING. 102 */ 103 boolean isRinging(); 104 /** 105 * Check if the phone is idle. 106 * @return true if the phone state is IDLE. 107 */ 108 boolean isIdle(); 109 /** 110 * Check to see if the radio is on or not. 111 * @return returns true if the radio is on. 112 */ 113 boolean isRadioOn(); 114 /** 115 * Check if the SIM pin lock is enabled. 116 * @return true if the SIM pin lock is enabled. 117 */ 118 boolean isSimPinEnabled(); 119 /** 120 * Cancels the missed calls notification. 121 */ 122 void cancelMissedCallsNotification(); 123 /** 124 * Supply a pin to unlock the SIM. Blocks until a result is determined. 125 * @param pin The pin to check. 126 * @return whether the operation was a success. 127 */ 128 boolean supplyPin(String pin); 129 /** 130 * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated 131 * without SEND (so <code>dial</code> is not appropriate). 132 * 133 * @param dialString the MMI command to be executed. 134 * @return true if MMI command is executed. 135 */ 136 boolean handlePinMmi(String dialString); 137 /** 138 * Toggles the radio on or off. 139 */ 140 void toggleRadioOnOff(); 141 /** 142 * Set the radio to on or off 143 */ 144 boolean setRadio(boolean turnOn); 145 /** 146 * Request to update location information in service state 147 */ 148 void updateServiceLocation(); 149 /** 150 * Enable location update notifications. 151 */ 152 void enableLocationUpdates(); 153 /** 154 * Disable location update notifications. 155 */ 156 void disableLocationUpdates(); 157 /** 158 * Enable a specific APN type. 159 */ 160 int enableApnType(String type); 161 /** 162 * Disable a specific APN type. 163 */ 164 int disableApnType(String type); 165 /** 166 * Allow mobile data connections. 167 */ 168 boolean enableDataConnectivity(); 169 /** 170 * Disallow mobile data connections. 171 */ 172 boolean disableDataConnectivity(); 173 /** 174 * Report whether data connectivity is possible. 175 */ 176 boolean isDataConnectivityPossible(); 177 Bundle getCellLocation(); 178 /** 179 * Returns the neighboring cell information of the device. 180 */ 181 List<NeighboringCellInfo> getNeighboringCellInfo(); 182 int getCallState(); 183 int getDataActivity(); 184 int getDataState(); 185 }
三、主要实现代码
在Activity中import com.android.internal.telephony.ITelephony;就可以使用ITelephony接口
1 package com.example.administrator.locker2; 2 3 import java.lang.reflect.Method; 4 5 import android.app.Service; 6 import android.content.BroadcastReceiver; 7 import android.content.Context; 8 import android.content.Intent; 9 import android.os.IBinder; 10 import android.telephony.PhoneStateListener; 11 import android.telephony.TelephonyManager; 12 import android.util.Log; 13 14 import com.android.internal.telephony.ITelephony; 15 16 public class PhoneReceiver extends BroadcastReceiver { 17 String TAG = "PhoneReceiver"; 18 19 @Override 20 public void onReceive(Context context, Intent intent) { 21 if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) { 22 // 如果是去电(拨出) 23 } else { 24 TelephonyManager tm = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE); 25 // 设置一个监听器 26 tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE); 27 } 28 } 29 30 PhoneStateListener listener = new PhoneStateListener() { 31 32 @Override 33 public void onCallStateChanged(int state, String incomingNumber) { 34 // state 当前状态 incomingNumber,貌似没有去电的API 35 super.onCallStateChanged(state, incomingNumber); 36 switch (state) { 37 //手机空闲了 38 case TelephonyManager.CALL_STATE_IDLE: 39 break; 40 //电话被挂起 41 case TelephonyManager.CALL_STATE_OFFHOOK: 42 break; 43 // 当电话呼入时 44 case TelephonyManager.CALL_STATE_RINGING: 45 Log.e(TAG, "来电号码是:"+ incomingNumber); 46 // 如果该号码属于黑名单 47 if (incomingNumber.equals("*********")) { 48 // TODO:如果是黑名单,就进行屏蔽 49 stopCall(); 50 } 51 break; 52 } 53 } 54 }; 55 56 public void stopCall() { 57 58 try { 59 Method method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class); 60 // 获取远程TELEPHONY_SERVICE的IBinder对象的代理 61 IBinder binder = (IBinder) method.invoke(null, new Object[] { "phone" }); 62 // 将IBinder对象的代理转换为ITelephony对象 63 ITelephony telephony = ITelephony.Stub.asInterface(binder); 64 // 挂断电话 65 telephony.endCall(); 66 //telephony.cancelMissedCallsNotification(); 67 68 } catch (Exception e) { 69 } 70 71 } 72 73 }
四、真机测试,当本机开启该应用时,拦截号码拨号方显示您所拨打的电话正在通话中