Uso de BroadcastReceiver con funcionalidad de PhoneStateListener
Estoy tratando de hacer una aplicación MissCall que envía un mensaje automáticamente cuando se recibe una llamada perdida. Había completado mi aplicación y funcionó bien!
Aquí está el escenario completo:
Problema:
La aplicación estaba funcionando bien, pero cuando he reiniciado el dispositivo de la aplicación no funcionó! . Sólo funcionó cuando empecé mi aplicación al menos una vez después de que funcionó bien hasta que se apaga.
Aquí está mi código:
package com.example.misscallapp; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.preference.PreferenceActivity; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.widget.Toast; public class Pref_Main extends PreferenceActivity { int checkIt = 0; TelephonyManager tm; CallStateListener callStateListener = new CallStateListener(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.prefs); tm = (TelephonyManager) getBaseContext().getSystemService( Context.TELEPHONY_SERVICE); tm.listen(callStateListener, PhoneStateListener.LISTEN_CALL_STATE); } private class CallStateListener extends PhoneStateListener { @Override public void onCallStateChanged(int state, String incomingNumber) { // Is called whenever there is a change in call state switch (state) { case TelephonyManager.CALL_STATE_RINGING: // called when someone is ringing to this phone Toast.makeText(getBaseContext(), "Incoming: " + incomingNumber, Toast.LENGTH_LONG).show(); checkIt = 1; break; case TelephonyManager.CALL_STATE_OFFHOOK: checkIt = 0; break; case TelephonyManager.CALL_STATE_IDLE: if (checkIt == 1) { Intent i = new Intent(getBaseContext(),MyService.class); i.putExtra("phno", incomingNumber); startService(i); // service that sends the SMS } break; } } } }
Solución:
Descubrí que la solución a esto es utilizar BroadcastReceiver . Así que registré un BroadcastReceiver pero no me dio la funcionalidad de PhoneStateListener
Por ejemplo, traté de usar el código siguiente, pero no funcionó, ya que BroadcastReceivers
sólo se llaman cuando recibe algo en contraste con PhoneStateListener
que llama al método onCallStateChanged siempre que haya un cambio en el estado de la llamada:
- Android - Extraer texto de SMS
- El receptor de difusión no funciona en ICS si la aplicación no se inicia al menos una vez
- Actividad abierta dos veces
- Servicio de Android Cerrar inesperadamente
- Creación de una notificación en un momento determinado mediante el Administrador de alarmas
package com.example.misscallapp; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.telephony.TelephonyManager; import android.widget.Toast; public class CallReceiverBroadcast extends BroadcastReceiver { int checkIt = 0; @Override public void onReceive(Context context, Intent intent) { Bundle extras = intent.getExtras(); if (extras != null) { String state = extras.getString(TelephonyManager.EXTRA_STATE); String incomingNumber = extras.getString(TelephonyManager.EXTRA_INCOMING_NUMBER); if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) { Toast.makeText(context , "Incoming: " + incomingNumber, Toast.LENGTH_LONG).show(); checkIt = 1; } if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) { // Call received checkIt = 0; } if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)) { if (checkIt == 1) { Toast.makeText(context , "This is not shown ", Toast.LENGTH_LONG).show(); Intent i = new Intent(context,MyService.class); i.putExtra("phno", incomingNumber); context.startService(i); } } } } }
También intenté un trabajo alrededor pero demostró resultados negativos como:
package com.example.misscallapp; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.widget.Toast; public class CallReceiverBroadcast extends BroadcastReceiver { int checkIt = 0; Context contextt; TelephonyManager tm; CallStateListener callStateListener = new CallStateListener(); @Override public void onReceive(Context context, Intent intent) { contextt = context; tm = (TelephonyManager) context.getSystemService( Context.TELEPHONY_SERVICE); tm.listen(callStateListener, PhoneStateListener.LISTEN_CALL_STATE); } private class CallStateListener extends PhoneStateListener { @Override public void onCallStateChanged(int state, String incomingNumber) { switch (state) { case TelephonyManager.CALL_STATE_RINGING: // called when someone is ringing to this phone Toast.makeText(contextt, "Incoming: " + incomingNumber, Toast.LENGTH_LONG).show(); checkIt = 1; break; case TelephonyManager.CALL_STATE_OFFHOOK: checkIt = 0; break; case TelephonyManager.CALL_STATE_IDLE: if (checkIt == 1) { //startting the service break; } } } } }
El código anterior cumple todos los requisitos pero envía la progresión en arithematic como si es la primera llamada de falta envía 1 y si es décima, entonces envía 10 mensajes!
Necesito seriamente ayuda en esto, Gracias de antemano.
Editar 1:
El problema es que cada vez que se llama al método onReceive()
instance is created
una nueva instance is created
de TelphoneManager y se registra como un oyente en el estado de Phoone.
Solución:
Hice cada variable de la clase CallReceiverBroadcast
estática ! Y resolvió el problema !! En cierta medida, pero todavía el servicio se llama dos veces cada vez que significa que algunos cómo hay 2 instancia de la clase registrada como un oyente, pero no sé por qué. Aunque puedo trabajar alrededor de él a través de alguna condición pero está causando la sobrecarga innecesaria y cualquier persona que tiene una mejor solución será muy apreciada .
- Registro de Receptor de Difusión en Manifiesto vs. Actividad
- WidgetProvider Los extras de intención enviados con el botón de clic no se encuentran en onReceive
- Fuga de receptor de difusión administrada localmente?
- Notificación de emisión del receptor de difusión
- ¿Dónde debo usar Servicio, AsyncTask y Broadcast Receiver?
- Cómo detectar cuando se pulsa el botón de encendido en la clase Receptor de difusión cuando se activa el permiso Administrador de dispositivos en Android
- Cómo obtener acción que la aplicación android está intentando eliminar / desinstalar desde el dispositivo
- AlarmManager activa alarmas en el pasado inmediatamente antes de que BroadcastReceiver pueda reprogramarlo
Esto se debe a una vez que recibió la llamada de la falta entonces usted está en la etapa de TelephonyManager.CALL_STATE_IDLE
y el mensaje enviará al mensaje apropiado pero su servicio está funcionando modo que es porqué él enviará 10 o sms múltiples.
Intente crear un receptor bootbroadcast, y en su inicio reciba el servicio para detectar llamadas. Esto garantiza que su servicio se active automáticamente después de cada reinicio del dispositivo.
En la primera versión, el oyente no se reinicia automáticamente en arranque (y también podría ser eliminado por el sistema) y es por eso que no funcionó en el arranque. También se olvidó de anular el registro del oyente.
En su segunda versión, onReceive()
debe llamar siempre que haya cambios de estado del teléfono, siempre que su Manifiesto esté configurado correctamente, como
<receiver android:name=".CallReceiverBroadcast" > <intent-filter> <action android:name="android.intent.action.PHONE_STATE" /> </intent-filter> </receiver>
Sin embargo, Android puede reciclar el receptor de difusión entre las llamadas a onReceive()
, lo que significa que su variable checkIt
no se puede conservar entre las llamadas a onReceive()
. Es posible que necesite utilizar una variable estática para que funcione.
En su tercera versión, está creando y registrando una versión múltiple del oyente de estado de llamada cuando se llama onReceive()
. (Tenga en cuenta que tm debe apuntar a la misma instancia de administrador de telefonía), que puede ser la razón por la que se llaman varias veces.
Dependiendo de cómo se convierten las variables en estáticas, el problema puede no ser resuelto ya que todavía puede estar creando / registrar nuevas instancias de CallStateListener
, aunque lo almacena en una variable estática.
Para solucionar estos problemas, debe anular el registro del detector de estado de llamada mediante la onDestroy()
del receptor de difusión
@Override public void onDestroy() { tm.listen(callStateListener, PhoneStateListener.LISTEN_NONE); }
Sin embargo, tenga en cuenta que no hay garantías de que después de onReceive()
devuelve, el proceso que aloja el receptor no se destruye. Su segunda versión que realiza todo el proceso antes de onReceive()
es preferible, si puede arreglarlo.
- Android: mensajes de Handler retrasados al final del hilo de trabajo
- WebView que provoca errores en la segunda actividad