我看到很多问题,无法在 Android 中以编程方式结束通话。同时,我在 googleplay 市场上看到很多拨号器应用程序,您可以在其中激活和挂断电话。它们是如何工作的?
编辑:我在某处读到我的应用程序必须是系统应用程序。那么如何使其系统化,系统应用程序和用户应用程序有什么区别?
我看到很多问题,无法在 Android 中以编程方式结束通话。同时,我在 googleplay 市场上看到很多拨号器应用程序,您可以在其中激活和挂断电话。它们是如何工作的?
编辑:我在某处读到我的应用程序必须是系统应用程序。那么如何使其系统化,系统应用程序和用户应用程序有什么区别?
您无需成为系统应用程序。首先,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 起)及更高版本,终于有了 endCall 的正式 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.
}
同时原来的endCall()
方法underTelephonyManager
现在是受MODIFY_PHONE_STATE
权限保护的,非系统App在没有权限的情况下不能再通过反射调用(否则会触发Security Exception)。
供参考。
在某些情况下可能有用。使用该类有一个潜在的解决方法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;
}
除了添加 android 电话接口和广播接收器之外,您还需要添加 android manifest 接收器条目以及android.intent.action.PHONE_STATE
要处理意图的接收器的操作。
如果添加,您将收到编译时错误
uses-permission android:name="android.permission.MODIFY_PHONE_STATE`
在您的清单文件中。但即使我们删除它,它也会自动拒绝来电。
SilenceRinger()
不适用于 android 2.3+ 版本。只需评论它,其他代码将正常工作。希望这对你有用!
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;
}
只是为了添加到@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)