Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


¿Cómo se puede contestar las llamadas entrantes mediante programación en Android 5.0 (Lollipop)?

Como estoy intentando crear una pantalla de encargo para las llamadas entrantes estoy intentando programar contestar una llamada entrante. Estoy utilizando el siguiente código, pero no funciona en Android 5.0.

// Simulate a press of the headset button to pick up the call Intent buttonDown = new Intent(Intent.ACTION_MEDIA_BUTTON); buttonDown.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK)); context.sendOrderedBroadcast(buttonDown, "android.permission.CALL_PRIVILEGED"); // froyo and beyond trigger on buttonUp instead of buttonDown Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON); buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK)); context.sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED"); 

  • ¿Cómo imitar el estilo de diseño de material levantado estilo de botón, incluso para pre-Lollipop (menos los efectos especiales)?
  • RecyclerView notifyItemInserted IllegalStateException
  • Cómo implementar elementos expandibles con LinearLayoutManager (introducido con Android L)
  • Uso de RecyclerView con tarjeta
  • Cómo obtener la posición en onCreateViewHolder
  • Android: barra de herramientas y barra de estado como objetos compartidos con cambios de contenido
  • AppBarLayout transparente y CollapsingToolbarLayout
  • Mejores Prácticas para el Manejo de la Búsqueda
  • En seguridad de facturación de aplicaciones
  • NullPointerException en SharedPreferences Android
  • Cómo habilitar / deshabilitar el servicio de accesibilidad mediante programación en Android
  • ¿Cuándo debo llamar a close () en SQLiteOpenHelper utilizado por ContentProvider
  • 9 Solutions collect form web for “¿Cómo se puede contestar las llamadas entrantes mediante programación en Android 5.0 (Lollipop)?”

    Actualización para Android O

    A pesar de que la pregunta fue originalmente pidió Android L de apoyo, la gente todavía parece estar golpeando esta pregunta y respuesta, por lo que vale la pena describir las últimas mejoras en Android O. Los métodos compatibles hacia atrás se describen a continuación.

    ¿Qué cambió?

    A partir de Android O , el grupo de permisos PHONE también contiene el permiso ANSWER_PHONE_CALLS . Como sugiere el nombre del permiso, mantenerlo permite que la aplicación acepte mediante programación las llamadas entrantes a través de una llamada apropiada a la API sin ningún tipo de piratería alrededor del sistema mediante la reflexión o la simulación del usuario.

    ¿Cómo utilizamos este cambio?

    Debe comprobar la versión del sistema en tiempo de ejecución si está soportando versiones anteriores de Android para poder encapsular esta nueva llamada de API mientras mantiene el soporte para las versiones anteriores de Android. Debe seguir solicitando permisos en tiempo de ejecución para obtener ese nuevo permiso durante la ejecución, como es habitual en las versiones más recientes de Android.

    Después de haber obtenido el permiso, su aplicación simplemente tiene que simplemente llamar al método answerRingingCall del TelephonyManager . Una invocación básica se ve así:

     TelephonyManager tm = (TelephonyManager) mContext .getSystemService(Context.TELEPHONY_SERVICE); if (tm == null) { // whether you want to handle this is up to you really throw new NullPointerException("tm == null"); } tm.answerRingingCall();` 

    Método 1: TelephonyManager.answerRingingCall ()

    Para cuando tienes control ilimitado sobre el dispositivo.

    ¿Que es esto?

    Hay TelephonyManager.answerRingingCall () que es un método interno oculto. Funciona como un puente para ITelephony.answerRingingCall () que ha sido discutido en las interwebs y parece prometedor al principio. No está disponible en 4.4.2_r1 ya que fue introducido solamente en commit 83da75d para Android 4.4 KitKat ( línea 1537 en 4.4.3_r1 ) y más tarde "reintroducido" en commit f1e1e77 para Lollipop ( línea 3138 en 5.0.0_r1 ) debido a cómo El árbol de Git fue estructurado. Esto significa que a menos que sólo soporte dispositivos con Lollipop, que es probablemente una mala decisión basada en la pequeña cuota de mercado de la misma en este momento, todavía necesita proporcionar métodos de fallback si va por esta ruta.

    ¿Cómo usaríamos esto?

    Como el método en cuestión está oculto del uso de las aplicaciones SDK, debe utilizar la reflexión para examinar dinámicamente y utilizar el método durante el tiempo de ejecución. Si no está familiarizado con la reflexión, puede leer rápidamente ¿Qué es la reflexión, y por qué es útil? . También puede profundizar en los detalles de Trail: The Reflection API si está interesado en hacerlo.

    ¿Y cómo se ve eso en el código?

     // set the logging tag constant; you probably want to change this final String LOG_TAG = "TelephonyAnswer"; TelephonyManager tm = (TelephonyManager) mContext .getSystemService(Context.TELEPHONY_SERVICE); try { if (tm == null) { // this will be easier for debugging later on throw new NullPointerException("tm == null"); } // do reflection magic tm.getClass().getMethod("answerRingingCall").invoke(tm); } catch (Exception e) { // we catch it all as the following things could happen: // NoSuchMethodException, if the answerRingingCall() is missing // SecurityException, if the security manager is not happy // IllegalAccessException, if the method is not accessible // IllegalArgumentException, if the method expected other arguments // InvocationTargetException, if the method threw itself // NullPointerException, if something was a null value along the way // ExceptionInInitializerError, if initialization failed // something more crazy, if anything else breaks // TODO decide how to handle this state // you probably want to set some failure state/go to fallback Log.e(LOG_TAG, "Unable to use the Telephony Manager directly.", e); } 

    ¡Esto es demasiado bueno para ser verdad!

    En realidad, hay un pequeño problema. Este método debe ser completamente funcional, pero el administrador de seguridad quiere que los llamantes mantengan android.permission.MODIFY_PHONE_STATE . Este permiso está en el reino de las características sólo parcialmente documentadas del sistema, ya que no se espera que terceros lo toquen (como se puede ver en la documentación para ello). Puedes intentar agregar un <uses-permission> pero no funcionará porque el nivel de protección para este permiso es el sistema de firma ( vea la línea 1201 de core / AndroidManifest en 5.0.0_r1 ).

    Puede leer el número 34785: Actualización de la documentación android: protectionLevel que se creó en 2012 para ver que nos faltan detalles sobre la "sintaxis de tubería" específica, pero de la experimentación alrededor, parece que debe funcionar como un 'AND' que significa todos los Las banderas especificadas tienen que ser satisfechas para el permiso concedido. Trabajando bajo esa suposición, significaría que usted debe tener su aplicación:

    1. Instalado como una aplicación del sistema.

      Esto debería estar bien y podría lograrse pidiendo a los usuarios que instalen utilizando un ZIP en recuperación, como al arraigar o instalar aplicaciones de Google en ROMs personalizadas que no las tienen ya empaquetadas.

    2. Firmado con la misma firma que frameworks / base aka el sistema, aka el ROM.

      Aquí es donde los problemas aparecen. Para hacer esto, usted necesita tener sus manos en las llaves usadas para firmar marcos / base. No solo tendrás que acceder a las claves de Google para las imágenes de fábrica de Nexus, sino que también tendrás que tener acceso a las llaves de los desarrolladores de otros OEM y ROM. Esto no parece plausible, por lo que puede tener su aplicación firmada con las claves del sistema, ya sea haciendo una ROM personalizada y pidiendo a los usuarios cambiar a ella (que podría ser difícil) o mediante la búsqueda de un exploit con el que el nivel de protección de permiso puede ser anulado (Que puede ser difícil también).

    Además, este comportamiento parece estar relacionado con el problema 34792: Android Jelly Bean / 4.1: android.permission.READ_LOGS ya no funciona que utiliza el mismo nivel de protección junto con un indicador de desarrollo indocumentado también.

    Trabajar con TelephonyManager suena bien, pero no funcionará a menos que obtenga el permiso apropiado, que no es tan fácil de hacer en la práctica.

    ¿Qué pasa con TelephonyManager de otras maneras?

    Lamentablemente, parece que requiere que mantenga el android.permission.MODIFY_PHONE_STATE para utilizar las herramientas frescas que a su vez significa que va a tener dificultades para obtener acceso a esos métodos.


    Método 2: llamada de servicio CÓDIGO DE SERVICIO

    Para cuándo puede probar que la compilación que se ejecuta en el dispositivo funcionará con el código especificado.

    Sin poder interactuar con el TelephonyManager, también existe la posibilidad de interactuar con el servicio a través del service ejecutable.

    ¿Como funciona esto?

    Es bastante simple, pero hay incluso menos documentación sobre esta ruta que otros. Estamos seguros de que el ejecutable tiene dos argumentos: el nombre del servicio y el código.

    • El nombre del servicio que queremos utilizar es el teléfono .

      Esto se puede ver ejecutando la service list .

    • El código que queremos utilizar parece haber sido 6, pero parece ser ahora 5 .

      Parece que se ha basado en IBinder.FIRST_CALL_TRANSACTION + 5 para muchas versiones ahora (desde 1.5_r4 a 4.4.4_r1 ), pero durante las pruebas locales el código 5 funcionó para responder a una llamada entrante. Como Lollipo es una actualización masiva en todo, es comprensible internals cambiado aquí también.

    Esto resulta con un comando del service call phone 5 de service call phone 5 .

    ¿Cómo lo utilizamos mediante programación?

    Java

    El siguiente código es una implementación aproximada hecha para funcionar como una prueba de concepto. Si realmente desea seguir adelante y utilizar este método, probablemente desee consultar las directrices para el uso sin problemas de su y, posiblemente, cambiar a la libsuperuser más completamente desarrollado por Chainfire .

     try { Process proc = Runtime.getRuntime().exec("su"); DataOutputStream os = new DataOutputStream(proc.getOutputStream()); os.writeBytes("service call phone 5\n"); os.flush(); os.writeBytes("exit\n"); os.flush(); if (proc.waitFor() == 255) { // TODO handle being declined root access // 255 is the standard code for being declined root for SU } } catch (IOException e) { // TODO handle I/O going wrong // this probably means that the device isn't rooted } catch (InterruptedException e) { // don't swallow interruptions Thread.currentThread().interrupt(); } 

    Manifiesto

     <!-- Inform the user we want them root accesses. --> <uses-permission android:name="android.permission.ACCESS_SUPERUSER"/> 

    ¿Realmente esto requiere acceso root?

    Lamentablemente, parece que sí. Puede intentar usar Runtime.exec en él, pero no pude conseguir ninguna suerte con esa ruta.

    ¿Qué tan estable es esto?

    Me alegra que hayas preguntado. Debido a que no se documenta, esto puede romperse entre varias versiones, como se ilustra por la aparente diferencia de código anterior. El nombre del servicio probablemente debería permanecer en el teléfono a través de varias compilaciones, pero por lo que sabemos, el valor del código puede cambiar a través de varias versiones de la misma versión (modificaciones internas, digamos, de la piel del OEM). Por lo tanto, vale la pena mencionar la prueba se llevó a cabo en un Nexus 4 (mako / occam). Yo personalmente le aconsejo contra el uso de este método, pero como no soy capaz de encontrar un método más estable, creo que este es el mejor disparo.


    Método original: Intenciones de clave de auriculares

    Para las épocas en que usted tiene que colocar.

    La siguiente sección fue fuertemente influenciada por esta respuesta de Riley C.

    El método de intención de auricular simulado publicado en la pregunta original parece ser difundido tal como se esperaría, pero no parece lograr el objetivo de responder a la llamada. Aunque parece que hay un código en el lugar que debe manejar esas intenciones, simplemente no están siendo cuidados, lo que tiene que significar que debe haber algún tipo de nuevas contramedidas en lugar de este método. El registro no muestra nada de interés tampoco y yo personalmente no creo cavar a través de la fuente de Android para esto será la pena sólo debido a la posibilidad de Google introducir un ligero cambio que rompe fácilmente el método utilizado de todos modos.

    ¿Hay algo que podamos hacer ahora mismo?

    El comportamiento se puede reproducir de forma consistente utilizando el ejecutable de entrada. Requiere un argumento keycode, para el cual simplemente pasamos KeyEvent.KEYCODE_HEADSETHOOK . El método ni siquiera requiere acceso root, lo que lo hace adecuado para los casos de uso común en el público en general, pero hay un pequeño inconveniente en el método – el evento botón de auriculares de prensa no se puede especificar para requerir un permiso, lo que significa que funciona como un real Presionar el botón y burbujas a través de toda la cadena, lo que a su vez significa que usted tiene que ser cauteloso acerca de cuándo simular la pulsación del botón como podría, por ejemplo, activar el reproductor de música para iniciar la reproducción si nadie más de mayor prioridad está listo para manejar el evento.

    ¿Código?

     new Thread(new Runnable() { @Override public void run() { try { Runtime.getRuntime().exec("input keyevent " + Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK)); } catch (IOException e) { // Runtime.exec(String) had an I/O problem, try to fall back String enforcedPerm = "android.permission.CALL_PRIVILEGED"; Intent btnDown = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra( Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK)); Intent btnUp = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra( Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK)); mContext.sendOrderedBroadcast(btnDown, enforcedPerm); mContext.sendOrderedBroadcast(btnUp, enforcedPerm); } } }).start(); 

    Tl; dr, antes de Android O

    • No hay API pública.
    • Las API internas están fuera de los límites o simplemente sin documentación.
    • Debe proceder con precaución.

    La solución totalmente funcional se basa en el código @Valter Strods.

    Para que funcione, debe mostrar una actividad (invisible) en la pantalla de bloqueo donde se ejecuta el código.

    AndroidManifest.xml

     <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.DISABLE_KEYGUARD" /> <activity android:name="com.mysms.android.lib.activity.AcceptCallActivity" android:launchMode="singleTop" android:excludeFromRecents="true" android:taskAffinity="" android:configChanges="orientation|keyboardHidden|screenSize" android:theme="@style/Mysms.Invisible"> </activity> 

    Actividad de aceptación de llamada

     package com.mysms.android.lib.activity; import android.app.Activity; import android.app.KeyguardManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; import android.os.Build; import android.os.Bundle; import android.telephony.TelephonyManager; import android.view.KeyEvent; import android.view.WindowManager; import org.apache.log4j.Logger; import java.io.IOException; public class AcceptCallActivity extends Activity { private static Logger logger = Logger.getLogger(AcceptCallActivity.class); private static final String MANUFACTURER_HTC = "HTC"; private KeyguardManager keyguardManager; private AudioManager audioManager; private CallStateReceiver callStateReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); } @Override protected void onResume() { super.onResume(); registerCallStateReceiver(); updateWindowFlags(); acceptCall(); } @Override protected void onPause() { super.onPause(); if (callStateReceiver != null) { unregisterReceiver(callStateReceiver); callStateReceiver = null; } } private void registerCallStateReceiver() { callStateReceiver = new CallStateReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); registerReceiver(callStateReceiver, intentFilter); } private void updateWindowFlags() { if (keyguardManager.inKeyguardRestrictedInputMode()) { getWindow().addFlags( WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); } else { getWindow().clearFlags( WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); } } private void acceptCall() { // for HTC devices we need to broadcast a connected headset boolean broadcastConnected = MANUFACTURER_HTC.equalsIgnoreCase(Build.MANUFACTURER) && !audioManager.isWiredHeadsetOn(); if (broadcastConnected) { broadcastHeadsetConnected(false); } try { try { logger.debug("execute input keycode headset hook"); Runtime.getRuntime().exec("input keyevent " + Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK)); } catch (IOException e) { // Runtime.exec(String) had an I/O problem, try to fall back logger.debug("send keycode headset hook intents"); String enforcedPerm = "android.permission.CALL_PRIVILEGED"; Intent btnDown = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra( Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK)); Intent btnUp = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra( Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK)); sendOrderedBroadcast(btnDown, enforcedPerm); sendOrderedBroadcast(btnUp, enforcedPerm); } } finally { if (broadcastConnected) { broadcastHeadsetConnected(false); } } } private void broadcastHeadsetConnected(boolean connected) { Intent i = new Intent(Intent.ACTION_HEADSET_PLUG); i.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); i.putExtra("state", connected ? 1 : 0); i.putExtra("name", "mysms"); try { sendOrderedBroadcast(i, null); } catch (Exception e) { } } private class CallStateReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { finish(); } } } 

    Estilo

     <style name="Mysms.Invisible"> <item name="android:windowFrame">@null</item> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowNoTitle">true</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowAnimationStyle">@null</item> </style> 

    ¡Finalmente llama a la magia!

     Intent intent = new Intent(context, AcceptCallActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); context.startActivity(intent); 

    Para elaborar un pequeño fragmento de la respuesta de @Muzikant, y modificarlo un poco para que funcione un poco más limpio en mi dispositivo, pruebe la input keyevent 79 , la constante de KeyEvent.KEYCODE_HEADSETHOOK . Muy rudamente:

      new Thread(new Runnable() { @Override public void run() { try { Runtime.getRuntime().exec( "input keyevent " + KeyEvent.KEYCODE_HEADSETHOOK ); } catch (Throwable t) { // do something proper here. } } }).start(); 

    Perdonar las convenciones bastante malas de la codificación, no soy muy versada en llamadas de Runtime.exec (). Ten en cuenta que mi dispositivo no está enraizado, ni estoy solicitando privilegios de root.

    El problema con este enfoque es que sólo funciona bajo ciertas condiciones (para mí). Es decir, si ejecuto el hilo anterior desde una opción de menú que el usuario selecciona mientras está sonando una llamada, la llamada responde bien. Si lo ejecuto desde un receptor que supervisa el estado de la llamada entrante, se ignora totalmente.

    Así que en mi Nexus 5 funciona bien para contestar por el usuario y debe adaptarse a un propósito de la pantalla de llamada personalizada. Simplemente no funcionará para ningún tipo de aplicaciones automatizadas de control de llamadas.

    También hay que tener en cuenta todas las posibles advertencias, incluyendo que esto, también, probablemente dejará de funcionar en una actualización o dos.

    El siguiente es un enfoque alternativo que funcionó para mí. Envía el evento clave al servidor de telecomunicaciones directamente usando la API de MediaController. Esto requiere que la aplicación tenga el permiso BIND_NOTIFICATION_LISTENER_SERVICE y se le conceda una concesión explícita del acceso de notificación desde el usuario:

     @TargetApi(Build.VERSION_CODES.LOLLIPOP) void sendHeadsetHookLollipop() { MediaSessionManager mediaSessionManager = (MediaSessionManager) getApplicationContext().getSystemService(Context.MEDIA_SESSION_SERVICE); try { List<MediaController> mediaControllerList = mediaSessionManager.getActiveSessions (new ComponentName(getApplicationContext(), NotificationReceiverService.class)); for (MediaController m : mediaControllerList) { if ("com.android.server.telecom".equals(m.getPackageName())) { m.dispatchMediaButtonEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK)); log.info("HEADSETHOOK sent to telecom server"); break; } } } catch (SecurityException e) { log.error("Permission error. Access to notification not granted to the app."); } } 

    NotificationReceiverService.class en el código anterior podría ser sólo una clase vacía.

     import android.service.notification.NotificationListenerService; public class NotificationReceiverService extends NotificationListenerService{ public NotificationReceiverService() { } } 

    Con la sección correspondiente en el manifiesto:

      <service android:name=".NotificationReceiverService" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.service.notification.NotificationListenerService" /> </intent-filter> 

    Dado que el objetivo del evento es explícito, esto probablemente debería evitar cualquier efecto secundario de activar el reproductor multimedia.

    Nota: es posible que el servidor de telecomunicaciones no esté inmediatamente activo después del suceso de llamada. Para que esto funcione de forma fiable, puede ser útil para la aplicación implementar MediaSessionManager.OnActiveSessionsChangedListener para supervisar cuando el servidor de telecomunicaciones se active, antes de enviar el evento.

    Gracias @ notz la respuesta de está trabajando para mí en el Lolillop. Para mantener este código funcionando con el SDK androide antiguo, puede hacer este código:

     if (Build.VERSION.SDK_INT >= 21) { Intent answerCalintent = new Intent(context, AcceptCallActivity.class); answerCalintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); context.startActivity(answerCalintent); } else { if (telephonyService != null) { try { telephonyService.answerRingingCall(); } catch (Exception e) { answerPhoneHeadsethook(); } } } 

    Cómo activar el teléfono con altavoz después de contestar automáticamente las llamadas.

    He resuelto mi problema anterior con setSpeakerphoneOn. Creo que vale la pena publicar aquí, ya que el caso de uso para responder automáticamente a una llamada telefónica a menudo también requieren altavoz para ser útil. Gracias de nuevo a todos en este hilo, lo que un trabajo impresionante.

    Esto funciona para mí en Android 5.1.1 en mi Nexus 4 sin ROOT. 😉

    Permiso requerido:

     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/> 

    Código Java:

     // this means the phone has answered if(state==TelephonyManager.CALL_STATE_OFFHOOK) { // try and turn on speaker phone final Handler mHandler = new Handler(); mHandler.postDelayed(new Runnable() { @Override public void run() { AudioManager audioManager = (AudioManager) localContext.getSystemService(Context.AUDIO_SERVICE); // this doesnt work without android.permission.MODIFY_PHONE_STATE // audioManager.setMode(AudioManager.MODE_IN_CALL); // weirdly this works audioManager.setMode(AudioManager.MODE_NORMAL); // this is important audioManager.setSpeakerphoneOn(true); // note the phone interface won't show speaker phone is enabled // but the phone speaker will be on // remember to turn it back off when your done ;) } }, 500); // half a second delay is important or it might fail } 

    A través de los comandos adb Cómo recoger una llamada por adb

    Tenga en cuenta que Android es Linux con una masiva JVM en la parte delantera. Usted puede descargar una aplicación de línea de comandos y la raíz del teléfono y ahora usted tiene una computadora normal de Linux y la línea de comandos que hace todas las cosas normales. Ejecutar secuencias de comandos, incluso se puede ssh a él (OpenVPN truco)

    Ejecute el siguiente comando como root:

     input keyevent 5 

    Más detalles sobre la simulación de keyevents aquí .

    Puede usar esta clase base que creé para ejecutar comandos como root desde su aplicación.

    Prueba esto: en primer lugar agregar los permisos a continuación, utilizar killCall () para interrumpir use answerCall () para responder a la llamada

     <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"></uses-permission> public void killCall() { try { TelephonyManager telephonyManager = (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE); Class classTelephony = Class.forName(telephonyManager.getClass().getName()); Method methodGetITelephony = classTelephony.getDeclaredMethod("getITelephony"); methodGetITelephony.setAccessible(true); Object telephonyInterface = methodGetITelephony.invoke(telephonyManager); Class telephonyInterfaceClass = Class.forName(telephonyInterface.getClass().getName()); Method methodEndCall = telephonyInterfaceClass.getDeclaredMethod("endCall"); methodEndCall.invoke(telephonyInterface); } catch (Exception ex) { Log.d(TAG, "PhoneStateReceiver **" + ex.toString()); } } public void answerCall() { try { Runtime.getRuntime().exec("input keyevent " + Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK)); } catch (IOException e) { answerRingingCallWithIntent(); } } public void answerRingingCallWithIntent() { try { Intent localIntent1 = new Intent(Intent.ACTION_HEADSET_PLUG); localIntent1.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); localIntent1.putExtra("state", 1); localIntent1.putExtra("microphone", 1); localIntent1.putExtra("name", "Headset"); getContext().sendOrderedBroadcast(localIntent1, "android.permission.CALL_PRIVILEGED"); Intent localIntent2 = new Intent(Intent.ACTION_MEDIA_BUTTON); KeyEvent localKeyEvent1 = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK); localIntent2.putExtra(Intent.EXTRA_KEY_EVENT, localKeyEvent1); getContext().sendOrderedBroadcast(localIntent2, "android.permission.CALL_PRIVILEGED"); Intent localIntent3 = new Intent(Intent.ACTION_MEDIA_BUTTON); KeyEvent localKeyEvent2 = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK); localIntent3.putExtra(Intent.EXTRA_KEY_EVENT, localKeyEvent2); getContext().sendOrderedBroadcast(localIntent3, "android.permission.CALL_PRIVILEGED"); Intent localIntent4 = new Intent(Intent.ACTION_HEADSET_PLUG); localIntent4.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); localIntent4.putExtra("state", 0); localIntent4.putExtra("microphone", 1); localIntent4.putExtra("name", "Headset"); getContext().sendOrderedBroadcast(localIntent4, "android.permission.CALL_PRIVILEGED"); } catch (Exception e2) { e2.printStackTrace(); } } 
    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.