App 可以通过调用当前系统的接口, 进行挂断电话,但是需要对应的权限。
根据SDK 版本有不同的方式。
方式1: android skd < 28 , 使用反射调用 Telephony.endCall
(1) 创建一个和系统ITelephony包名一样的包: com.android.internal.telephony,
(2) 创建 ITelephony.aidl 文件
// ITelephony.aidl
package com.android.internal.telephony;
// Declare any non-default types here with import statements
interface ITelephony {
boolean endCall();
}
(3) 通过反射调用
- 获取ServiceManager的类对象 : c = Class.forName("android.os.ServiceManager");
- 获取getService的Method对象: method = c.getMethod("getService", String.class);
- 调用方法获取远程服务即Telephony对应的 IBinder对象 : iBinder = (IBinder) method.invoke(null, TELEPHONY_SERVICE);
- 根据IBinder对象获取服务端接口对象 ITelephony: telephony = ITelephony.Stub.asInterface(iBinder)
- 结束通话调用: telephony.endCall();
完整代码如下:
private void endCallByTelephonyInterface() {
// 通过反射,调用隐藏的api
Class c = null;
Method method = null;
//1. 得到隐藏类的Class对象
try {
c = Class.forName("android.os.ServiceManager");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (c == null) {
return;
}
//2. 得到方法所对用的Method对象
try {
method = c.getMethod("getService", String.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
if (method == null) {
return;
}
IBinder iBinder = null;
//3. 调用方法
try {
iBinder = (IBinder) method.invoke(null, TELEPHONY_SERVICE);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
if (iBinder == null) {
return;
}
//4. 得到接口对象
ITelephony telephony = ITelephony.Stub.asInterface(iBinder);
//5. 结束通话
try {
telephony.endCall();
} catch (RemoteException e) {
e.printStackTrace();
}
}
并且需要以下权限:
<uses-permission android:name="android.permission.CALL_PHONE"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
方式2:android sdk =28 , 使用 TelecomManager.endCall
参考:https://www.codenong.com/cs106716569/
https://developer.android.com/reference/android/telecom/TelecomManager.html#endCall()
private void endCallByTelecomManager() {
log("endCallByTelecomManager");
if (Build.VERSION.SDK_INT < 28) {
log("endCallByTelecomManager return because sdk < 28");
return;
}
if (this.checkSelfPermission(Manifest.permission.ANSWER_PHONE_CALLS) == PackageManager.PERMISSION_GRANTED) {
TelecomManager manager = (TelecomManager) this.getSystemService(TELECOM_SERVICE);
boolean ret = manager.endCall();
log("endCallByTelecomManager endCall ret=" + ret);
} else {
log("endCallByTelecomManager do not grant ANSWER_PHONE_CALLS");
}
}
需要声明权限: <uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
方式3:android sdk >=29, 使用 InCallService
待续...