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:

 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í.

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); } 
  1. Cree un BroadcastReceiver con una prioridad de 0.
  2. En el BC interceptar la intención ACTION_NEW_OUTGOING_CALL en su método onReceive
  3. 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.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.