Завершить вызов в android программно
Я вижу много вопросов, которые невозможно завершить программным способом в Android.
В то же время, я вижу множество приложений для набора номера на рынке googleplay, где вы можете активировать вызов и отбросить его. Как они работают?
Изменить. Я где-то читал, что мое приложение должно быть системным приложением. Затем, как сделать его системой, и в чем разница между системными и пользовательскими приложениями?
Ответы
Ответ 1
Вам не нужно быть системным приложением. Сначала создайте пакет 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" />
Редактировать: извинения за ужасное форматирование, я до сих пор не могу понять, как правильно делать блоки кода здесь:/
Ответ 2
Для Android P (начиная с бета-версии 2) и выше, наконец, существует формальный API для endCall:
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
и больше не может вызываться несистемными приложениями путем отражения без разрешения (в противном случае будет вызвано исключение безопасности).
Ответ 3
Наряду с добавлением интерфейса телефонии android и широковещательного приемника вам также потребуется добавить запись приемника манифеста android с действием android.intent.action.PHONE_STATE
для приемника, с которым вы хотите справиться с намерением.
Вы получите ошибку времени компиляции, если вы добавите
uses-permission android:name="android.permission.MODIFY_PHONE_STATE`
в файле манифеста. Но даже если мы удалим это, он автоматически отклонит входящие вызовы.
Ответ 4
Для информации.
Может быть полезным в некоторых ситуациях. Существует потенциальный обходной путь с использованием класса 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()
и вызов закончится.
Ответ 5
SilenceRinger()
не работает для версий Android 2.3+. Просто прокомментируйте это, другой код будет работать нормально.
Надеюсь, это сработает для вас!
Ответ 6
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
To end call in older version then 9.0
use this:
TelephonyManager tm = (TelephonyManager)context.getSystemService(TELEPHONY_SERVICE);
Method m1 = null;
try {
m1 = tm.getClass().getDeclaredMethod("getITelephony");
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
m1.setAccessible(true);
Object iTelephony = null;
try {
iTelephony = m1.invoke(tm);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
Method m3 = null;
try {
m3 = iTelephony.getClass().getDeclaredMethod("endCall");
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
m3.invoke(iTelephony);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
& for pie
TelecomManager telecomManager = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
if (telecomManager != null) {
return telecomManager.endCall();
}
Make sure your compile SDK version is 28
Ответ 8
Просто чтобы добавить в ответ @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)