wake-up-neo.net

Warum funktioniert BroadcastReceiver auch, wenn sich die App im Hintergrund befindet?

Ich überprüfe die Internetverbindung in meiner App mithilfe von BroadcastReceiver und zeige ein Warnungsdialogfeld an, wenn die Verbindung unterbrochen wird. Es funktioniert gut. Mein Problem ist jedoch, dass BroadcastReceiver auch dann funktioniert, wenn sich meine App im Hintergrund befindet. Das Dialogfeld wird geöffnet, wenn die Internetverbindung unterbrochen wird, auch wenn sich der Benutzer in einer anderen App befindet. Dies ruiniert meine App total. 

Hat jemand eine Idee, wie man den Broadcast-Empfänger nur in der App einschränken kann? 

Hier ist mein 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();
        }
    }
  }
}

Und die Aktivität ist:

 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;
       }
   }
   }

So habe ich Empfänger und Aktivität in Manifest erklärt:

  <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" />

Ich habe gelesen, dass wir BroadcastReceiver auf die Arbeit innerhalb der App einschränken können, indem Sie es nicht im Manifest deklarieren. Aber ich weiß nicht, wie der Empfänger funktioniert. Bitte hilf mir. Ich bin schlecht dran. Danke im Voraus.

18
Yogesh Somani

A BroadcastReceiver funktioniert, wenn sich die App im Hintergrund befindet, da das Ereignis, das der Empfänger abholt, global gesendet wird und jede App registriert ist, um diese anzuhören, unabhängig davon, ob sie ausgeführt wird.

Um dies zu umgehen, überprüfen Sie im BroadcastReceiver-Code Ihrer onReceive, ob sich Ihre App im Vordergrund befindet.

Es gibt eine - und nur eine, die ich kenne - eine konsequent wirksame Methode, um dies zu tun. Sie müssen Ihre Pausen-/Wiederaufnahmeaktionen für Ihre Anwendung nachverfolgen. Stellen Sie sicher, dass Sie dies in der Aktivität every überprüfen.

Es gibt einige Beispielcodes in dieser Antwort (Lösung # 1). In Ihrem Fall möchten Sie MyApplication.isActivityVisible() == true als Validierung prüfen, bevor Sie etwas von Ihrer BroadcastReceiver aus tun.

37
Eric

Haben Sie versucht, den Intent-Filter aus dem Manifest zu entfernen und ihn in der Aktivität zu registrieren/die Registrierung aufzuheben? Sie können also versuchen, den Intent-Filter in onStart () zu registrieren und die Registrierung für onStop () - Methoden aufzuheben. Der Code sieht so aus:

static final String ACTION = "Android.net.conn.CONNECTIVITY_CHANGE";


IntentFilter filter = new IntentFilter(ACTION);
this.registerReceiver(ConnectivityChangedReceiver, filter);


unregisterReceiver(ConnectivityChangedReceiver);

Sie sollten auch etwas über den Aktivitätslebenszyklus erfahren, wenn er noch nicht vertraut ist.

17
soreal

Sie sollten Ihre BroadcastReceiver in onPause() und onResume() für jede Aktivität registrieren bzw. die Registrierung aufheben. Dann wissen Sie, dass der Receiver nur "hört", wenn sich Ihre App im Vordergrund befindet. Sie können dies ganz einfach tun, indem Sie ein eigenes BaseActivity erstellen, das Activity erweitert und onPause() und onResume() überschreibt und Ihren Empfänger registriert/deaktiviert. Lassen Sie einfach alle Ihre Aktivitäten BaseActivity erweitern und rufen Sie wie üblich super.onResume() und super.onPause() auf. Hier ein Beispielcode:

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);
    }
}

Alle Ihre Aktivitäten sollten BaseActivity umfassen. Wenn Sie etwas Besonderes in onResume() oder onPause() tun müssen, rufen Sie einfach super.onXXXXX() wie folgt auf:

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
        ...
    }
}

Ich habe den Code nicht durch einen Compiler ausgeführt, also entschuldige ich mich, wenn ein Tippfehler vorliegt oder ich etwas verpasst habe. 

13
David Wasser

Ich denke, Sie müssen sicherstellen, dass Sie den Empfänger nicht verwenden, wenn sich die App im Hintergrund befindet. Dafür müssen Sie alle Aktivitäten der Methoden onPause () und onResume () verwenden.

4

Um einen Broadcast Receiver zu erstellen, der/die nur ausgelöst wird, wenn die App ausgeführt wird, folgen Sie dem Code unten.

1. Erstellen Sie Ihren Broadcast-Empfänger wie folgt:


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. Erstellen Sie eine Aktivität oder ein Fragment, in der der Broadcast-Empfänger wie folgt funktionieren soll:


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();
    }

Hinweis: So verwenden Sie den Rundfunkempfänger bildschirmspezifisch. Nur die Bildschirmanzeige empfängt auf diese Weise Sendungen. Wenn Sie Broadcast mit einer Manifestdatei registrieren, werden sie sogar empfangen, wenn die App geschlossen wird

3

Soweit ich weiß, wenn der Broadcast-Empfänger in manifest.xml registriert ist, ist der Broadcast-Empfänger vorhanden, solange die Anwendung vorhanden ist. Dynamisch registrierte Empfänger (d. H. Ihren BroadcastReceiver programmatisch registrieren) werden im UI-Thread aufgerufen. Dies bedeutet, dass Ihr Receiver alle UI-Aktionen blockiert. Daher sollte die onReceive()-Methode so schnell wie möglich sein. 

Ich werde jedoch versuchen, Informationen zu Broadcast Receiver zu besprechen. Aber zuerst sollten einige Informationen bekannt sein. Erstens ist der Broadcast-Empfänger eine eigenständige Anwendungskomponente, dh er wird auch dann ausgeführt, wenn andere Anwendungskomponenten nicht ausgeführt werden. Deshalb wird die Registrierung des Broadcast-Empfängers in onPause für die Aktivität deaktiviert. Der Entwickler sollte dies auch in der Activity.onResume()-Implementierung registrieren. 

Zweitens sollte der Entwickler die Registrierung in Activity.onSaveInstanceState() nicht aufheben, da dies nicht aufgerufen wird, wenn der Benutzer sich wieder im Verlaufsstapel befindet. Ich habe diese Informationen aus der BroadcastReceiver-Dokumentation übernommen.

Ein weiterer Punkt ist, dass ein BroadcastReceiver-Objekt nur für die Dauer des Aufrufs von onReceive () gültig ist. Sobald die onReceive () -Methode abgeschlossen ist, wird Ihr BroadcastReceiver beendet.

So registrieren Sie Ihren Empfänger programmgesteuert:

public abstract Intent registerReceiver (BroadcastReceiver receiver, IntentFilter filter)

Hier wird der BroadcastReceiver-Receiver angerufen, wenn ein Broadcast-Intent mit dem Filter übereinstimmt.
Und IntentFilter Intent legt fest, welches Ereignis Ihr Receiver hören soll.

Registrieren:

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);

Senden Sie Ihre Broadcast-Informationen:

Intent intent = new Intent();
intent.putExtra("Message", "Your connectivity info has Changed!!"); 
this.sendBroadcast(intent);

Empfänger:

Jetzt müssen Sie die Sendung empfangen. Android ruft die onReceive () -Methode bei allen registrierten Rundfunkempfängern auf, wenn das Ereignis eintritt. Angenommen, Sie möchten benachrichtigt werden, wenn die Verbindung geändert wird.

public class YourConnectionListener extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent){
         // your Code
    }
}   

onReceive() hat zwei Argumente:

  • context: Das Context-Objekt, mit dem Sie auf zusätzliche Informationen zugreifen oder Dienste oder Aktivitäten starten können.
  • absicht: Absicht, mit der der Empfänger registriert wird. Dieses Objekt enthält zusätzliche Informationen, die Sie in Ihrer Implementierung verwenden können.
    Darüber hinaus sollte der Entwickler alle lang andauernden Aufgaben in Ihrem BroadcastReceiver vermeiden. Daher sollte der Entwickler bei statisch und dynamisch registrierten Empfängern kleinere Aufgaben im Empfänger selbst erledigen. Für längere Aufgaben sollten Sie einen Dienst in Ihrem Empfänger starten. 
3
Ratna Halder

So funktionieren Rundfunkempfänger in Android. Wenn Sie sich für eine Übertragung im Manifest registrieren und Ihre App nicht ausgeführt wird, startet Android einen neuen Prozess für die Übertragung der Übertragung. Es ist im Allgemeinen eine schlechte Idee, eine Benutzeroberfläche direkt von einem Rundfunkempfänger anzuzeigen, da dies andere Apps unterbrechen kann. Ich bin auch nicht überzeugt, dass ein universeller Dialog, der die Verbindung unterbrochen hat, auch eine gute Idee ist. Dies sollte wahrscheinlich von jeder Aktivität behandelt werden, die Netzwerkzugriff verwendet. 

Für die ursprüngliche Frage müssen Sie Ihren Empfänger deaktivieren, wenn Ihre Aktivität im Hintergrund erfolgt (onPause() usw.), und aktivieren, wenn Sie in den Vordergrund kommen (onResume() usw.). Fügen Sie enabled=false in Ihr Manifest ein und verwenden Sie dann etwas Ähnliches in Ihrem Code, um es nach Bedarf umzuschalten: 

   public static void toggle(Context context, boolean enable) {
        int flag = enable ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
                : PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
        ComponentName receiver = new ComponentName(context,
                ConnectivityMonitor.class);

        context.getPackageManager().setComponentEnabledSetting(receiver, flag,
                PackageManager.DONT_KILL_APP);
   }
1
Nikolay Elenkov

Eine einfache Methode, um herauszufinden, ob sich die App im Vordergrund befindet oder nicht 

if((mContext.getPackageName().equalsIgnoreCase(
                ((ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE))
                        .getRunningTasks(1).get(0).topActivity.getPackageName())))
{
//app is in foreground;
}
0
Naren

Ich empfehle Ihnen, die Interneteinstellungen in der Anwendung zu überprüfen, wenn sie von jemandem geöffnet werden.

public static boolean isNetworkConnected(Context ctx) {  
        ConnectivityManager cm = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);  
        NetworkInfo ni = cm.getActiveNetworkInfo();  
        if (ni == null) {  
            return false; // There are no active networks.  
        } else  
            return true;  
    }
0
yubaraj poudel