Cómo colgar la llamada saliente en Android?
Estoy desarrollando una aplicación donde una de las cosas que necesitamos es controlar la llamada saliente, al menos para poder detenerla desde nuestra aplicación.
He intentado usar Intent.ACTION_CALL
de una actividad existente:
- ¿Hay soporte de API para realizar llamadas de conferencia mediante programación en Android?
- ¿Cómo puedo acceder a las API privadas de Android que no están expuestas en TelephonyManager?
- ¿Qué representan los diferentes estados de llamada en la pila de telefonía de Android?
- Cómo resolver este error "com.android.internal.telephony no se puede resolver a un tipo" en android
- ¿Hay un medio en android para buscar código telefónico de teléfono
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + phoneNumber)); startActivity(callIntent);
Pero detener la llamada parece ser rechazado a través de la API.
¿Puede sugerir alguna solución?
Por ejemplo: ¿habilitar el modo avión durante la llamada? Sólo un ejemplo; Este hack no funcionó para mí.
- Android 4.2 y superiores leen la configuración de APN
- Android Conference and Hold Call Programmatically
- ¿Cómo acceder a la lista de llamadas de Android?
- Cómo saber a callee se contesta la llamada (¿Cuál es el estado del teléfono cuando levanta la llamada)
- Android: obtenga CellID y RSS para la estación base y las celdas Neigboring
Capturar la llamada saliente en un BroadcastReceiver
se ha mencionado y es definitivamente la mejor manera de hacerlo si desea terminar la llamada antes de marcar.
Sin embargo, una vez marcado o en llamada, esa técnica ya no funciona. La única manera de colgar que he encontrado hasta ahora, es hacerlo a través de Java Reflection . Como no forma parte de la API pública, debe tener cuidado de usarla y no confiar en ella . Cualquier cambio en la composición interna de Android romperá eficazmente su aplicación.
El blog de Prasanta Paul demuestra cómo se puede lograr, que he resumido a continuación.
Obtención del objeto ITelephony
:
TelephonyManager tm = (TelephonyManager) context .getSystemService(Context.TELEPHONY_SERVICE); try { // Java reflection to gain access to TelephonyManager's // ITelephony getter Log.v(TAG, "Get getTeleService..."); Class c = Class.forName(tm.getClass().getName()); Method m = c.getDeclaredMethod("getITelephony"); m.setAccessible(true); com.android.internal.telephony.ITelephony telephonyService = (ITelephony) m.invoke(tm); } catch (Exception e) { e.printStackTrace(); Log.e(TAG, "FATAL ERROR: could not connect to telephony subsystem"); Log.e(TAG, "Exception object: " + e); }
Finalización de la llamada:
telephonyService.endCall();
Prueba esto:
(Utilicé Reflection para acceder a características avanzadas de telefonía y modificar algo)
// required permission <uses-permission android:name="android.permission.CALL_PHONE"/> try { //String serviceManagerName = "android.os.IServiceManager"; String serviceManagerName = "android.os.ServiceManager"; String serviceManagerNativeName = "android.os.ServiceManagerNative"; String telephonyName = "com.android.internal.telephony.ITelephony"; Class telephonyClass; Class telephonyStubClass; Class serviceManagerClass; Class serviceManagerStubClass; Class serviceManagerNativeClass; Class serviceManagerNativeStubClass; Method telephonyCall; Method telephonyEndCall; Method telephonyAnswerCall; Method getDefault; Method[] temps; Constructor[] serviceManagerConstructor; // Method getService; Object telephonyObject; Object serviceManagerObject; telephonyClass = Class.forName(telephonyName); telephonyStubClass = telephonyClass.getClasses()[0]; serviceManagerClass = Class.forName(serviceManagerName); serviceManagerNativeClass = Class.forName(serviceManagerNativeName); Method getService = // getDefaults[29]; serviceManagerClass.getMethod("getService", String.class); Method tempInterfaceMethod = serviceManagerNativeClass.getMethod( "asInterface", IBinder.class); Binder tmpBinder = new Binder(); tmpBinder.attachInterface(null, "fake"); serviceManagerObject = tempInterfaceMethod.invoke(null, tmpBinder); IBinder retbinder = (IBinder) getService.invoke(serviceManagerObject, "phone"); Method serviceMethod = telephonyStubClass.getMethod("asInterface", IBinder.class); telephonyObject = serviceMethod.invoke(null, retbinder); //telephonyCall = telephonyClass.getMethod("call", String.class); telephonyEndCall = telephonyClass.getMethod("endCall"); //telephonyAnswerCall = telephonyClass.getMethod("answerRingingCall"); telephonyEndCall.invoke(telephonyObject); } catch (Exception e) { e.printStackTrace(); Log.error(DialerActivity.this, "FATAL ERROR: could not connect to telephony subsystem"); Log.error(DialerActivity.this, "Exception object: " + e); }
- Cree un
BroadcastReceiver
con una prioridad de 0. - En el BC interceptar la intención
ACTION_NEW_OUTGOING_CALL
en su métodoonReceive
- Llamar a
setResultData(null)
en el mismo método
Esto evitará que la llamada se inicie (siempre y cuando su receptor es el último en procesar la intención creo)
Puede intentar activar y desactivar el modo de avión:
android.provider.Settings.System.putInt(getContentResolver(), android.provider.Settings.System.AIRPLANE_MODE_ON, 1); Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); intent.putExtra("state", 1); sendBroadcast(new Intent("android.intent.action.AIRPLANE_MODE")); sendBroadcast(intent); android.provider.Settings.System.putInt(getContentResolver(), android.provider.Settings.System.AIRPLANE_MODE_ON, 0); intent.putExtra("state", 0); sendBroadcast(new Intent("android.intent.action.AIRPLANE_MODE")); sendBroadcast(intent);
Para Ilana:
public class ilanasReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) { if (getResultData()!=null) { String number = "123456"; setResultData(number); } } } }
Además en Manifiesto poner en la sección de paquetes:
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
Eso es todo.
Teniendo en cuenta el potencial de daño maravilloso me sorprendería si esto se permite.
Este hilo dice rotundamente que la API no puede finalizar una llamada . Otros lo han intentado .
Según la documentación de ACTION_NEW_OUTGOING_CALL
El intento tendrá el siguiente valor adicional:
EXTRA_PHONE_NUMBER – el número de teléfono originalmente destinado a ser marcado.
Una vez finalizada la transmisión, se utiliza el resultadoData como el número real a llamar. Si se nula, no se realizará ninguna llamada.