我看到很多问题,在Android中以编程方式结束调用是不可能的。 与此同时,我在googleplay市场上看到很多拨号应用,你可以在其中激活呼叫并将其丢弃。他们是如何运作的?
编辑:我在某处读过我的应用必须是系统应用。那么如何制作系统,以及系统和用户应用程序之间有什么区别?
答案 0 :(得分:44)
您不需要是系统应用程序。首先,在项目中创建包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" />
编辑:为可怕的格式化道歉,我仍然无法弄清楚如何在这里正确执行代码块:/
答案 1 :(得分:9)
对于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()
下的原始TelephonyManager
方法现在受MODIFY_PHONE_STATE
权限保护,未经许可不得再通过反映由非系统应用调用(否则将触发安全例外。)
答案 2 :(得分:1)
除了添加Android电话接口和广播接收器之外,您还需要为要处理意图的接收者添加动作android.intent.action.PHONE_STATE
的android清单接收器条目。
如果添加
,将出现编译时错误uses-permission android:name="android.permission.MODIFY_PHONE_STATE`
清单文件中的。但即使我们删除它,它也会自动拒绝来电。
答案 3 :(得分:1)
有关信息。
在某些情况下可能有用。使用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()
,通话就会结束。
答案 4 :(得分:1)
切断对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;
}
答案 5 :(得分:0)
SilenceRinger()
不适用于Android 2.3+版本。只需评论它,其他代码将正常工作。
希望这对你有用!
答案 6 :(得分:0)
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;
}
答案 7 :(得分:0)
只需添加到@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)