我看到很多问题说在安卓系统中不能编程结束通话。与此同时,我在谷歌应用商店里看到许多拨号应用程序可以激活通话并挂断。它们是如何工作的?
编辑: 我在某个地方读到我的应用程序必须成为系统应用程序。那么如何将其变成系统应用程序,系统应用程序和用户应用程序有什么区别?
我看到很多问题说在安卓系统中不能编程结束通话。与此同时,我在谷歌应用商店里看到许多拨号应用程序可以激活通话并挂断。它们是如何工作的?
编辑: 我在某个地方读到我的应用程序必须成为系统应用程序。那么如何将其变成系统应用程序,系统应用程序和用户应用程序有什么区别?
您不需要成为系统应用程序。首先,在您的项目中创建包com.android.internal.telephony
,并将其放入名为"ITelephony.aidl
"的文件中:
package com.android.internal.telephony;
interface ITelephony {
boolean endCall();
void answerRingingCall();
void silenceRinger();
}
一旦你获得了那个,就可以使用这段代码来结束通话:
TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
Class clazz = Class.forName(telephonyManager.getClass().getName());
Method method = clazz.getDeclaredMethod("getITelephony");
method.setAccessible(true);
ITelephony telephonyService = (ITelephony) method.invoke(telephonyManager);
telephonyService.endCall();
例如,您可以在PhoneStateListener中使用它。为了使其工作,您需要在清单文件中添加权限:
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
编辑:很抱歉格式不好看,我还是搞不清楚如何在这里正确地使用代码块 :/
针对 Android P(Beta 2及以上版本),终于推出了一个正式 API,用于结束通话:
https://developer.android.com/reference/android/telecom/TelecomManager#endCall()
在清单文件中需要声明ANSWER_PHONE_CALLS
权限:
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
在获得权限的情况下,适用于API级别28或更高:
TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
if (tm != null) {
boolean success = tm.endCall();
// success == true if call was terminated.
}
同时原来在TelephonyManager
下的endCall()
方法现在被MODIFY_PHONE_STATE
权限保护,非系统应用程序在没有该权限的情况下无法通过反射调用该方法(否则将触发安全异常)。
关于信息。
在某些情况下可能会有用。使用InCallService
类可以有一个潜在的解决方法。大部分所需信息都在这里。https://developer.android.com/reference/android/telecom/InCallService.html#onCallRemoved(android.telecom.Call)
它需要将您的应用程序设置为默认电话应用程序,并确保授予以下权限。
<uses-permission android:name="android.permission.CALL_PHONE" />
如果你实现自己的类扩展 InCallService
,那么当一个电话开始时,该电话会绑定到你的应用程序上,并通过 onCallAdded()
函数获取呼叫信息。然后你可以简单地调用 call.disconnect()
来结束通话。
削减API 28+的调用
private void cutCall(){
ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.READ_PHONE_STATE }, PHONE_STATE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (requestCode == PHONE_STATE) {
ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.ANSWER_PHONE_CALLS }, ANSWER_CALLS);
} else if (requestCode == ANSWER_CALLS) {
cutTheCall;
}
}
}
//这段代码适用于Android N(Api 28及以上)
private boolean cutTheCall() {
TelecomManager telecomManager = (TelecomManager) getApplicationContext().getSystemService(TELECOM_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED || telecomManager == null) {
return false;
}
if (telecomManager.isInCall()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
callDisconnected = telecomManager.endCall();
}
}
return true;
}
SilenceRinger()
在 Android 2.3+ 版本中不起作用。只需将其注释掉,其他代码将正常工作。
希望这对你有用!
android.intent.action.PHONE_STATE
为要处理意图的接收器添加条目。uses-permission android:name="android.permission.MODIFY_PHONE_STATE`
在您的清单文件中。但即使我们删除它,它也会自动拒绝来电。
只是为了补充@headuck的答案。对于API 28,您还需要添加:
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
然后在您的活动中请求权限。总共我请求了这些权限来使它工作(READ_PHONE_STATE,CALL_PHONE,ANSWER_PHONE_CALLS,READ_CONTACTS,READ_CALL_LOG)
public static boolean isCallActive(Context context){
AudioManager manager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
if(manager.getMode()==AudioManager.MODE_IN_CALL || manager.getMode()==AudioManager.MODE_IN_COMMUNICATION){
return true;
}
return false;
}
您可以使用电信管理器来结束通话。我进行了测试,它可以正常工作。 您需要获得 ANSWER_PHONE_CALLS 权限才能这样做。尽管它提示已接听的通话,但我已经成功地结束了从此手机拨出的通话。而且这适用于现代 Android 手机。
TelecomManager telecomManager = (TelecomManager) getSystemService(Context.TELECOM_SERVICE);
telecomManager.endCall();