Pourquoi BroadcastReceiver fonctionne même lorsque l'application est en arrière-plan?
je vérifie la connectivité Internet de mon application en utilisant BroadcastReceiver et j'affiche un dialogue d'alerte si la connexion est perdue. Il fonctionne très bien. Mais mon problème est que BroadcastReceiver fonctionne même si mon application est en fond. Sorte de dialogue s'affiche lorsque la connexion internet est perdue, même si l'utilisateur est dans une autre application. C'est totalement ruiner mon application.
quiconque A une idée de comment restreindre récepteur de Radiodiffusion dans l'application?
Voici mon BroadcastReceiver :
public class ConnectivityChangedReceiver extends BroadcastReceiver{
@Override
public void onReceive( Context context, Intent intent )
{
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService( Context.CONNECTIVITY_SERVICE );
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
} else {
try{
Intent i=new Intent(context, InternetDialogActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
} catch(Exception e){
e.printStackTrace();
}
}
}
}
Et l'activité est:
public class InternetDialogActivity extends Activity implements OnClickListener{
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.internet_dialog_box);
getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
Button retryButton = (Button) findViewById(R.id.retryInternetButton);
retryButton.setOnClickListener(this);
}
public boolean checkConnectivity(){
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo!=null && networkInfo.isConnected()) {
finish();
return true;
} else {
Intent intent = getIntent();
finish();
startActivity(intent);
return false;
}
}
@Override
public void onClick(View view) {
switch(view.getId()){
case R.id.retryInternetButton:
try{
checkConnectivity();
} catch(Exception e){
e.printStackTrace();
}
break;
}
}
}
Voici comment j'ai déclaré le récepteur et l'activité dans le manifeste:
<receiver android:name="com.lisnx.service.ConnectivityChangedReceiver"
android:label="NetworkConnection">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
<activity android:name="com.lisnx.activity.InternetDialogActivity"
android:configChanges="orientation|keyboardHidden"
android:theme="@android:style/Theme.Dialog" />
j'ai lu que nous pouvons restreindre BroadcastReceiver à travailler dans l'application en ne le déclarant pas dans le manifeste. Mais je ne sais pas comment le récepteur fonctionne alors? S'il vous plaît aider moi. Je suis coincé à mal. Merci à l'avance.
9 réponses
BroadcastReceiver
fonctionne lorsque l'application est à l'arrière-plan parce que l'événement que le récepteur capte sont envoyés globalement, et chaque application est enregistrée pour écouter sur ceux-ci, indépendamment du fait qu'elle soit ou non en cours d'exécution.
Pour faire face à cela, dans votre BroadcastReceiver
onReceive
code, vérifiez si votre application est au premier plan.
il y a une--et une seule que je connais--méthode toujours efficace pour faire ceci. Vous devez garder une trace de vos actions de pause / reprise pour votre application. S'assurer que vous vérifiez ce dans tous les activité.
Il y a un exemple de code dans cette réponse (solution n ° 1). Dans votre cas, vous pouvez vérifier les MyApplication.isActivityVisible() == true
comme une validation avant de faire quoi que ce soit de votre BroadcastReceiver
.
Avez-vous essayé de supprimer le filtre d'Intention du manifeste et s'inscrire/se désinscrire il en activité? Vous pouvez donc essayer d'enregistrer le filtre D'intention dans les méthodes onStart() et de le désactiver sur onStop (). Le code va somethink comme ceci:
static final String ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
IntentFilter filter = new IntentFilter(ACTION);
this.registerReceiver(ConnectivityChangedReceiver, filter);
unregisterReceiver(ConnectivityChangedReceiver);
Vous devez aussi apprendre à propos de Cycle De Vie Des Activités, si elle n'est pas encore familière.
vous devez enregistrer / désinscrire votre BroadcastReceiver
onPause()
et onResume()
de chaque activité. Alors vous savez que le récepteur ne "écoute" que lorsque votre application est au premier plan. Vous pouvez facilement le faire en créant votre propre BaseActivity
qui s'étend Activity
et remplace onPause()
et onResume()
et enregistre / désinscrire votre récepteur. Faites étendre toutes vos activités!--5--> et par super.onResume()
et super.onPause()
comme d'habitude. Voici l'exemple code:
public class BaseActivity extends Activity {
// Create an IntentFilter to listen for connectivity change events
static IntentFilter filter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
// Create an instance of our BroadcastReceiver
static ConnectivityChangedReceiver receiver = new ConnectivityChangedReceiver();
@Override
protected void onPause() {
super.onPause();
// Stop listening for connectivity change events
unregisterReceiver(receiver);
}
@Override
protected void onResume() {
super.onResume();
// Listen for connectivity change events
registerReceiver(receiver, filter);
}
}
toutes vos activités devraient s'étendre BaseActivity
et si ils ont besoin de faire quelque chose de spécial dans onResume()
ou onPause()
n'oubliez pas d'appeler jusqu'à super.onXXXXX()
comme ceci:
public MyActivity extends BaseActivity {
@Override
protected void onResume() {
super.onResume();
// Here you do whatever you need to do in onResume() of your activity
...
}
@Override
protected void onPause() {
super.onPause();
// Here you do whatever you need to do in onPause() of your activity
...
}
}
Je n'ai pas passé le code dans un compilateur alors je m'excuse s'il y a une faute de frappe ou si j'ai manqué quelque chose.
je pense que vous devez vous assurer que vous n'utilisez pas le récepteur lorsque l'application est en arrière-plan. Pour cela, vous devrez utiliser toutes les méthodes onPause() et onResume ().
Pour Récepteur De Radiodiffusion qui ne démarre que lorsque votre application est en cours d'exécution, suivez le code ci-dessous.
1. Créer votre Récepteur de Radiodiffusion comme ceci:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class InternetStatusNotifier extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//Recieve notification here
}
}
2. Faire une activité ou d'un fragment de l'endroit où vous souhaitez que le Récepteur de Radiodiffusion à travailler comme ça:
import android.app.Activity;
import android.content.IntentFilter;
import android.os.Bundle;
public class MainActivity extends Activity {
private InternetStatusNotifier mInternetStatusNotifier;
@Override
protected void onCreate(Bundle savedInstanceState) {
mInternetStatusNotifier = new InternetStatusNotifier();
super.onCreate(savedInstanceState);
}
@Override
protected void onResume() {
registerReceiver(mInternetStatusNotifier, new IntentFilter(
"android.net.conn.CONNECTIVITY_CHANGE"));
super.onResume();
}
@Override
protected void onPause() {
unregisterReceiver(mInternetStatusNotifier);
super.onPause();
}
Remarque: C'est ainsi que vous utilisez le récepteur de radiodiffusion d'une manière spécifique à l'écran. Seulement l'écran Display recevra des émissions de cette façon. Lorsque vous enregistrez la diffusion en utilisant le fichier manifest, ils sont même reçus lorsque l'application est fermée
autant que je sache, si le récepteur de radiodiffusion est inscrit dans le manifeste.xml puis récepteur de radiodiffusion existe aussi longtemps que l'application existe. En outre, les récepteurs dynamiquement enregistrés (C'est-à-dire, enregistrez votre BroadcastReceiver programmatically) sont appelés sur le thread de L'interface utilisateur. Cela signifie que vos récepteurs bloquent toute manipulation de L'interface utilisateur et donc le onReceive()
méthode devrait être aussi rapide que possible.
cependant, je vais essayer de discuter des informations sur le récepteur de radiodiffusion. Mais, d'abord devrait connaissance de certaines informations. Premièrement, le récepteur de radiodiffusion est un composant d'application autonome, ce qui signifie qu'il continuera à fonctionner même si d'autres composants d'application ne fonctionnent pas. C'est pourquoi nous désinscrivons récepteur de diffusion dans onPause sur l'activité. De plus, le développeur doit enregistrer ceci dans Activity.onResume()
mise en œuvre.
deuxièmement, le développeur ne doit pas se désinscrire dans Activity.onSaveInstanceState()
, parce que cela ne sera pas appelé si l'utilisateur revient dans la pile d'historique. J'ai mis que des informations de documentation de diffusion.
un autre point est qu'un objet BroadcastReceiver n'est valide que pour la durée de l'appel à onReceive(). Dès que la méthode onReceive() est terminée, votre BroadcastReceiver se termine.
Maintenant, comment enregistrer votre récepteur du programme:
public abstract Intent registerReceiver (BroadcastReceiver receiver, IntentFilter filter)
ici, le récepteur-récepteur de radiodiffusion sera appelé quand l'intention de diffusion correspond avec le filtre.
Et IntentFilter - Intent spécifie l'événement de votre récepteur doit écouter.
inscrire:
YourConnectionListener receiver;
this.reciever = new YourConnectionListener();
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(this.reciever, filter);
send your Broadcast Info:
Intent intent = new Intent();
intent.putExtra("Message", "Your connectivity info has Changed!!");
this.sendBroadcast(intent);
Récepteur:
maintenant, besoin de recevoir l'émission. Android appelle la méthode onReceive () sur tous les récepteurs de diffusion enregistrés chaque fois que l'événement se produit. Dites que vous voulez être informé chaque fois que la connexion est changée.
public class YourConnectionListener extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent){
// your Code
}
}
onReceive()
a deux arguments:
- contexte: Le Contexte objet que vous pouvez utiliser pour accéder à des informations supplémentaires ou pour démarrer des services ou activités.
- intention: intention utilisée pour enregistrer votre récepteur. Cet objet contient des informations supplémentaires que vous pouvez utiliser dans votre application.
de plus, le développeur doit éviter toute tâche de longue durée dans votre BroadcastReceiver. Ainsi, dans les récepteurs statiquement et dynamiquement enregistrés, le développeur devrait faire des tâches mineures dans le récepteur lui-même.Pour les tâches plus longues, vous devriez commencer un service à partir de votre récepteur.
C'est la façon dont les récepteurs de diffusion fonctionnent sur Android. Si vous vous inscrivez pour une diffusion dans le manifeste et votre application n'est pas en cours d'exécution, Android va commencer un nouveau processus pour gérer la diffusion. C'est généralement une mauvaise idée de montrer directement un UI d'un récepteur de diffusion, car cela peut interrompre d'autres applications. Je ne suis pas non plus convaincu qu'un dialogue universel 'connexion perdue' soit une bonne idée. Cela devrait probablement être traitée par chaque activité qui utilise le réseau d'accès.
Comme pour la question originale, vous devez désactiver votre récepteur lorsque votre activité passe à l'arrière-plan (onPause()
, etc.) et l'activer lorsque vous arrivez au premier plan (