<receiver android:name=“.PhoneStateReceiver”
android:enabled=“true”
android:process=“:PhoneListenService”>
public class PhoneStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
// 去电,可以用定时挂断
} else {
//来电
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
Log.d(PhoneListenService.TAG, "PhoneStateReceiver onReceive state: " + state);
if (state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING)) {
Log.d(PhoneListenService.TAG, “PhoneStateReceiver onReceive endCall”);
HangUpTelephonyUtil.endCall(context);
}
}
}
}
三. 实战,有什么需要特别注意地方
3.1 双卡双待的手机怎么获取
对于双卡手机,每张卡都对应一个 Service 和一个 PhoneStateListener,需要给每个服务注册自己的 PhoneStateListener,服务的名称还会有点变化,厂商可能会修改
public ArrayList getMultSimCardInfo() {
// 获取双卡的信息,这个也是经验尝试出来的,不知道其他厂商有什么坑
ArrayList phoneServerList = new ArrayList();
for(int i = 1; i < 3; i++) {
try {
String phoneServiceName;
if (MiuiUtils.isMiuiV6()) {
phoneServiceName = “phone.” + String.valueOf(i-1);
} else {
phoneServiceName = “phone” + String.valueOf(i);
}
// 尝试获取服务看是否能获取到
IBinder iBinder = ServiceManager.getService(phoneServiceName);
if(iBinder == null) continue;
ITelephony iTelephony = ITelephony.Stub.asInterface(iBinder);
if(iTelephony == null) continue;
phoneServerList.add(phoneServiceName);
} catch(Exception e) {
e.printStackTrace();
}
}
// 这个是默认的
phoneServerList.add(Context.TELEPHONY_SERVICE);
return phoneServerList;
}
3.2 挂断电话
挂断电话使用系统服务提供的接口去挂断,但是挂断电话是个并不能保证成功的方法,所以会有多种方式挂断同时使用,下面提供
package com.phone.listen;
import android.content.Context;
import android.os.RemoteException;
import android.telephony.TelephonyManager;
import com.android.internal.telephony.ITelephony;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
- 封装挂断电话接口
*/
public class HangUpTelephonyUtil {
public static boolean endCall(Context context) {
boolean callSuccess = false;
ITelephony telephonyService = getTelephonyService(context);
try {
if (telephonyService != null) {
callSuccess = telephonyService.endCall();
}
} catch (RemoteException e) {
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
if (callSuccess == false) {
Executor eS = Executors.newSingleThreadExecutor();
eS.execute(new Runnable() {
@Override
public void run() {
disconnectCall();
}
});
callSuccess = true;
}
return callSuccess;
}
private static ITelephony getTelephonyService(Context context) {
TelephonyManager telephonyManager = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
Class clazz;
try {
clazz = Class.forName(telephonyManager.getClass().getName());
Method method = clazz.getDeclaredMethod(“getITelephony”);
method.setAccessible(true);
return (ITelephony) method.invoke(telephonyManager);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
private static boolean disconnectCall() {
Runtime runtime = Runtime.getRuntime();
try {
runtime.exec(“service call phone 5 \n”);
} catch (Exception exc) {
exc.printStackTrace();
return false;
}
return true;
}
// 使用 endCall 挂断不了,再使用 killCall 反射调用再挂一次
public static boolean killCall(Context context) {
try {
// Get the boring old TelephonyManager
TelephonyManager telephonyManager = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
// Get the getITelephony() method
Class classTelephony = Class.forName(telephonyManager.getClass().getName());
Method methodGetITelephony = classTelephony.getDeclaredMethod(“getITelephony”);
// Ignore that the method is supposed to be private
methodGetITelephony.setAccessible(true);
// Invoke getITelephony() to get the ITelephony interface
Object telephonyInterface = methodGetITelephony.invoke(telephonyManager);
// Get the endCall method from ITelephony
Class telephonyInterfaceClass = Class.forName(telephonyInterface.getClass().getName());
Method methodEndCall = telephonyInterfaceClass.getDeclaredMethod(“endCall”);
// Invoke endCall()
methodEndCall.invoke(telephonyInterface);
} catch (Exception ex) { // Many things can go wrong with reflection calls
return false;
}
return true;
}
}
ITelephony 接口在 layoutlib.jar 包中,需要导入 android sdk 目录\platforms\android-8\data\layoutlib.jar
挂断电话需要权限
3.3 监听来去电状态放到后台服务(独立进程)
<service android:name=“.PhoneListenService”
android:label=“Android 来电监听”
android:process=“:PhoneListenService”/>
来去电监听 Service
package com.phone.listen;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
/**
- 来去电监听服务
*/
public class PhoneListenService extends Service {
public static final String TAG = PhoneListenService.class.getSimpleName();
public static final String ACTION_REGISTER_LISTENER = “action_register_listener”;
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, “onCreate”);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand action: " + intent.getAction() +
" flags: " + flags + " startId: " + startId);
String action = intent.getAction();
if (action.equals(ACTION_REGISTER_LISTENER)) {
registerPhoneStateListener();
}
return super.onStartCommand(intent, flags, startId);
}
private void registerPhoneStateListener() {
CustomPhoneStateListener customPhoneStateListener = new CustomPhoneStateListener(this);
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (telephonyManager != null) {
telephonyManager.listen(customPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
}
}
最后
**要想成为高级安卓工程师,必须掌握许多基础的知识。**在工作中,这些原理可以极大的帮助我们理解技术,在面试中,更是可以帮助我们应对大厂面试官的刁难。
加入社区》https://bbs.youkuaiyun.com/forums/4304bb5a486d4c3ab8389e65ecb71ac0
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (telephonyManager != null) {
telephonyManager.listen(customPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
}
}
最后
**要想成为高级安卓工程师,必须掌握许多基础的知识。**在工作中,这些原理可以极大的帮助我们理解技术,在面试中,更是可以帮助我们应对大厂面试官的刁难。
[外链图片转存中…(img-rS3h40wY-1725661379152)]
[外链图片转存中…(img-Gv7EzqiM-1725661379152)]
加入社区》https://bbs.youkuaiyun.com/forums/4304bb5a486d4c3ab8389e65ecb71ac0