android broadcastreceiver android-service android-broadcastreceiver

android - Cómo mantener vivo mi BroadcastReceiver



android-service android-broadcastreceiver (7)

Aquí está el código Funciona bien para mí:

En Manifiesto usted agrega permiso:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

Los próximos pasos crean un inicio de Service cuando inicie la aplicación (tal vez MainActivity ) llame a este código en el método onCreate of Service

Código

((TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE)).listen(new PhoneStateListener(new PhoneStateListener.PhoneCallListener() { @Override public void PhoneCall() { // Do something } @Override public void PhoneOff() { // Do something } @Override public void MissCall() { // Do something } }), PhoneStateListener.LISTEN_CALL_STATE);

PhoneStateListener.java

import android.telephony.TelephonyManager; /** * PhoneStateListener. * * @author DaoLQ */ public class PhoneStateListener extends android.telephony.PhoneStateListener { public interface PhoneCallListener { void PhoneCall(); void PhoneOff(); void MissCall(); } private PhoneCallListener mPhoneCallListener; private boolean ring = false; private boolean callReceived = false; public PhoneStateListener(PhoneCallListener listener) { mPhoneCallListener = listener; } @Override public void onCallStateChanged(int state, String incomingNumber) { super.onCallStateChanged(state, incomingNumber); switch (state) { case TelephonyManager.CALL_STATE_IDLE: mPhoneCallListener.PhoneOff(); if (ring && !callReceived) { mPhoneCallListener.MissCall(); } break; case TelephonyManager.CALL_STATE_OFFHOOK: // CALL_STATE_OFFHOOK; callReceived = true; mPhoneCallListener.PhoneCall(); break; case TelephonyManager.CALL_STATE_RINGING: ring = true; mPhoneCallListener.PhoneCall(); break; default: break; } } }

Actualmente estoy desarrollando una aplicación de bloqueo de llamadas como Truecaller.

Lo que necesitaba

Quiero detectar las llamadas entrantes, incluso mi aplicación se elimina de la lista de aplicaciones recientes.

Manifest.xml codigo

<receiver android:name=".PhoneStateReceiver"> <intent-filter> <action android:name="android.intent.action.PHONE_STATE" /> </intent-filter> </receiver>

Mi código receptor de emisión

@Override public void onReceive(Context context, Intent intent) { //my call blocking code }

Mi problema

Mi BroadcastReceiver no funcionará en segundo plano como si lo hubiera eliminado de la lista de aplicaciones recientes.

Mi código de manifiesto completo aquí

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ranjith.callblocker"> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.GET_TASKS" /> <application android:allowBackup="true" android:enabled="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <receiver android:name=".PhoneStateReceiver" android:enabled="true" android:exported="true" android:process=":anotherProcess"> <intent-filter android:priority="1000"> <action android:name="android.intent.action.PHONE_STATE" /> </intent-filter> </receiver> <activity android:name=".MainActivity" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>

¿Debo usar el servicio o cualquier otra cosa?

Actualizar:

Con la respuesta de Suraj probé estas etiquetas en mi receptor

android:enabled="true" android:exported="true" android:process=":anotherProcess"

funciona en kitkat ... pero no funciona en paleta ...

Pregunta actualizada:

Si no es posible mantener vivo el receptor de difusión ¿Cómo puedo detectar las llamadas entrantes incluso si mi aplicación está cerrada?

alguien da respuesta detallada ...


Aquí está mi receta, en realidad funciona de 4.4 a 6.0

Manifiesto:

<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" /> <application> <receiver android:name=".utils.PhoneReceiver"> <intent-filter android:priority="999"> <action android:name="android.intent.action.PHONE_STATE" /> <action android:name="android.provider.Telephony.SMS_RECEIVED" /> <action android:name="android.intent.action.NEW_OUTGOING_CALL" /> </intent-filter> </receiver> </application>

Luego en el PhoneReceiver.class

public class PhoneReceiver extends BroadcastReceiver { public void onReceive(Context thecontext, Intent intent) { if ("android.provider.Telephony.SMS_RECEIVED".equals(intent.getAction())) { // handle SMS received } else if ("android.intent.action.NEW_OUTGOING_CALL".equals(intent.getAction())) { // handle outgoing call } else if (intent.getAction().equals("android.intent.action.PHONE_STATE")) { String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); /* from there do your stuff... */ if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER); /* etc. etc. */ } } }


Aquí estamos notificando al receptor del servicio.

Así que haz una clase de servicio como

public class MyService extends Service { @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { new CountDownTimer(100000,4000) { @Override public void onTick(long millisUntilFinished) { sendBroadcast(new Intent("fromservice")); } @Override public void onFinish() { } }.start(); return START_STICKY; } }

Ahora haz un receptor como

public class MyReceiver extends WakefulBroadcastReceiver { @Override public void onReceive(final Context context, Intent intent) { Toast.makeText(context, "inside receiver", Toast.LENGTH_SHORT).show(); } }

Ahora inicia el servicio desde la actividad principal.

public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startService(new Intent(this,MyService.class)); } }

Declarar receptor y servicio en manifiesto como sigue

<receiver android:name=".MyReceiver" android:process=":jk" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="fromservice"/> </intent-filter> </receiver> <service android:name=".MyService" android:process=":ff" android:enabled="true" android:exported="true" />

Agregue el siguiente permiso a su manifiesto. Esto se utiliza para evitar que la CPU se duerma.

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

¿Qué es el temporizador de cuenta regresiva?

El temporizador de cuenta regresiva puede entenderse como una iteración que tiene métodos.

onTick () y onFinish ()

onTick () se llama muchas veces después de un intervalo (duración de tiempo) como se indica en el constructor CountDownTimer.

Al final se llama a onFinish () (solo una vez) cuando longTimeInFuture ha llegado.


Debes agregar permiso de manifiesto,

<uses-permission android:name="android.permission.READ_PHONE_STATE" >

Y el receptor debe tener los siguientes atributos declarados, también siempre trate de usar el nombre completo del paquete cuando declare el nombre.

<receiver android:name="ranjith.callblocker.PhoneStateReceiver" android:enabled="true" android:exported="true" android:permission="android.permission.READ_PHONE_STATE"> <intent-filter> <action android:name="android.intent.action.PHONE_STATE" /> </intent-filter> </receiver>

A continuación, intente poner un registro dentro del bloque receptor,

@Override public void onReceive(Context context, Intent intent) { Log.i("TAG", "Receiver is called but might not block call for other reason!"); }

Asegúrese de no cancelar el registro del receptor por nombre de ninguno de ustedes en los métodos OnPause, onStop, onDestroy


Necesita crear un Service y registrarlo en el manifiesto. Después de ello, debe registrar su BroadcastReceiver dentro del servicio en lugar del manifiesto.

Un Service no se detiene cuando se elimina la aplicación de los últimos momentos, por lo que su receptor también continuará funcionando. Incluso recibirá una devolución de llamada a través del Service#onTaskRemoved cuando la aplicación se elimine de los últimos.

Aunque también necesitará manejar algunos otros casos, cuando se puede detener un Service .

Un caso es cuando Android puede detener su servicio cuando el sistema tiene poca memoria, puede corregirlo devolviendo START_STICKY desde su método onStartCommand .

Otro caso es cuando el dispositivo se reinicia, deberá registrar un receptor de difusión para ACTION_BOOT_COMPLETED en mnifest para solucionar este problema. Puede reiniciar su servicio en su método onReceive .

Espero debajo del código de ejemplo ayuda-

private BroadcastReceiver mReceiver; @Override public int onStartCommand(Intent intent, int flags, int startId) { mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.v(LOG_TAG, "worked"); } }; registerReceiver(mReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); return START_STICKY; } @Override public void onDestroy() { unregisterReceiver(mReceiver); super.onDestroy() }


Puede intentar registrar Broadcast Receiver en onCreate () de la actividad.


<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.phonestatelistener"> <uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name="com.android.receiver.PhoneStateListener" android:exported="true" > <intent-filter > <action android:name="android.intent.action.PHONE_STATE"/> <action android:name="android.intent.action.NEW_OUTGOING_CALL"/> <action android:name="android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> </receiver> </application>

public class PhoneStateListener extends BroadcastReceiver { public static String TAG="PhoneStateListener"; public static String ACTION_PHONE_STATE = "android.intent.action.PHONE_STATE"; public static String ACTION_OUTGOING_CALL = "android.intent.action.NEW_OUTGOING_CALL"; public static String ACTION_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED"; @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(ACTION_PHONE_STATE)) { String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) { Toast.makeText(context, "Incoming call", Toast.LENGTH_SHORT).show(); Log.d(TAG, "Incoming call"); } } else if (intent.getAction().equals(ACTION_OUTGOING_CALL)) { Toast.makeText(context, "Outgoing call", Toast.LENGTH_SHORT).show(); Log.d(TAG, "Outgoing call"); } else if (intent.getAction().equals(ACTION_SMS_RECEIVED)) { Toast.makeText(context, "Incoming message", Toast.LENGTH_SHORT).show(); Log.d(TAG, "Incoming message"); } }

}

Prueba esto . Funcionará hasta forzar el cierre de la aplicación.