studio phone permission llamada intent example android android-intent telephony

llamada - permission call phone android



Cómo detectar cuando el teléfono es respondido o rechazado (4)

La respuesta anterior es completamente incorrecta en el caso de llamadas salientes. En Android no hay manera de que uno pueda detectar si la llamada fue realmente respondida (en el caso de llamadas salientes). En el momento en que marca un número, se off_hook estado off_hook . Este es uno de los inconvenientes de la programación de Android.

Logré preparar una actividad cuando el teléfono está sonando. Ahora necesito saber cómo cancelar esta actividad cuando responda el teléfono o rechazo la llamada. ¿Llamo a EXTRA_STATE_IDLE? EXTRA_STATE_OFFHOOK?

¿Algunas ideas?

<receiver android:name=".IncomingBroadcastReceiver"> <intent-filter> <action android:name="android.intent.action.PHONE_STATE"/> </intent-filter> </receiver> public class IncomingBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); // If an incoming call arrives if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) { //Did my work }


Los siguientes son los estados que atraviesa en diferentes escenarios:

1) Contestar la llamada recibida

CALL_STATE_RINGING => CALL_STATE_OFFHOOK (After Answering call) => CALL_STATE_IDLE (After End call)

2) Rechazar / No contestar (Perdido) Llamada recibida

CALL_STATE_RINGING => CALL_STATE_IDLE (After End call)

3) Llamada de marcado

CALL_STATE_OFFHOOK (After dialing) => CALL_STATE_IDLE (After End call)

Código

int prev_state=0; public class CustomPhoneStateListener extends PhoneStateListener { private static final String TAG = "CustomPhoneStateListener"; @Override public void onCallStateChanged(int state, String incomingNumber){ if(incomingNumber!=null&&incomingNumber.length()>0) incoming_nr=incomingNumber; switch(state){ case TelephonyManager.CALL_STATE_RINGING: Log.d(TAG, "CALL_STATE_RINGING"); prev_state=state; break; case TelephonyManager.CALL_STATE_OFFHOOK: Log.d(TAG, "CALL_STATE_OFFHOOK"); prev_state=state; break; case TelephonyManager.CALL_STATE_IDLE: Log.d(TAG, "CALL_STATE_IDLE==>"+incoming_nr); NumberDatabase database=new NumberDatabase(mContext); if((prev_state==TelephonyManager.CALL_STATE_OFFHOOK)){ prev_state=state; //Answered Call which is ended } if((prev_state==TelephonyManager.CALL_STATE_RINGING)){ prev_state=state; //Rejected or Missed call } break; } } }

En tu receptor

onReceive(Context context, Intent intent) { TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); //TelephonyManager object CustomPhoneStateListener customPhoneListener = new CustomPhoneStateListener(); telephony.listen(customPhoneListener, PhoneStateListener.LISTEN_CALL_STATE); //Register our listener with TelephonyManager Bundle bundle = intent.getExtras(); String phoneNr= bundle.getString("incoming_number"); mContext=context; }


a continuación se muestra un código de detección de llamadas salientes por eventos de accesibilidad:

Agregue una clase que amplíe AccessibilityService en sus proyectos:

public class CallDetection extends AccessibilityService { @Override public void onAccessibilityEvent(AccessibilityEvent event) { acquireLock(this); Log.d("myaccess","after lock"); if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) { Log.d("myaccess","in window changed"); AccessibilityNodeInfo info = event.getSource(); if (info != null && info.getText() != null) { String duration = info.getText().toString(); String zeroSeconds = String.format("%02d:%02d", new Object[]{Integer.valueOf(0), Integer.valueOf(0)}); String firstSecond = String.format("%02d:%02d", new Object[]{Integer.valueOf(0), Integer.valueOf(1)}); Log.d("myaccess","after calculation - "+ zeroSeconds + " --- "+ firstSecond + " --- " + duration); if (zeroSeconds.equals(duration) || firstSecond.equals(duration)) { Toast.makeText(getApplicationContext(),"Call answered",Toast.LENGTH_SHORT).show(); // Your Code goes here } info.recycle(); } } } @Override protected void onServiceConnected() { super.onServiceConnected(); Toast.makeText(this,"Service connected",Toast.LENGTH_SHORT).show(); AccessibilityServiceInfo info = new AccessibilityServiceInfo(); info.eventTypes = AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED; info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC; info.notificationTimeout = 0; info.packageNames = null; setServiceInfo(info); } @Override public void onInterrupt() { } }

Pero para que la función event.getSource() funcione, debe especificar parte de la configuración del servicio a través de xml, por lo tanto, cree una carpeta xml en su proyecto y agregue un archivo xml llamado serviceconfig.xml (puede dar el nombre que desee).

El contenido de serviceconfig está debajo -

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/callDetection" android:accessibilityEventTypes="typeWindowContentChanged" android:notificationTimeout="100" android:canRetrieveWindowContent="true" />

Puede encontrar más información sobre serviceconfig en Here

Ahora agregue su servicio en su archivo Manifiesto como este -

<service android:name=".CallDetection" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" android:label="@string/callDetection"> <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService" /> </intent-filter> <meta-data android:name="android.accessibilityservice" android:resource="@xml/serviceconfig" /> </service>

Y listo, simplemente ejecute la aplicación y vaya a Configuración de accesibilidad en su teléfono, encontrará una opción llamada detección ( o el nombre que haya dado como descripción del servicio ), actívela para otorgar permisos de accesibilidad para su aplicación.

Ahora verá un brindis cuando se responda la llamada.

puede codificar cualquier código que desee allí, también puede llamar a una función de devolución de llamada en su actividad

Lo más importante : no llame a su ventana de llamada (ventana del marcador de Android) hasta que se responda la llamada; de lo contrario, esto no funcionará.

Nota : como Android no proporciona ninguna solución para detectar si la llamada se responde o no, esta es la mejor alternativa que he hecho, espero que funcione para usted.


en su onReceive:

PhoneStateChangeListener pscl = new PhoneStateChangeListener; TelephonyManager tm = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE); tm.listen(pscl, PhoneStateListener.LISTEN_CALL_STATE);

clase separada:

private class PhoneStateChangeListener extends PhoneStateListener { public static boolean wasRinging; @Override public void onCallStateChanged(int state, String incomingNumber) { switch(state){ case TelephonyManager.CALL_STATE_RINGING: Log.i(LOG_TAG, "RINGING"); wasRinging = true; break; case TelephonyManager.CALL_STATE_OFFHOOK: Log.i(LOG_TAG, "OFFHOOK"); if (!wasRinging) { // Start your new activity } else { // Cancel your old activity } // this should be the last piece of code before the break wasRinging = true; break; case TelephonyManager.CALL_STATE_IDLE: Log.i(LOG_TAG, "IDLE"); // this should be the last piece of code before the break wasRinging = false; break; } } }

Todo lo que necesita hacer es escribir un código para verificar si el estado anterior fue ''sonando''. Si el estado actual está inactivo y el estado anterior estaba sonando, cancelaron la llamada. Si el estado actual es "offhook" y el estado anterior estaba sonando, respondieron la llamada.