Zarejestruj programowo odbiornik transmisji


149

Chciałbym wiedzieć, jaka jest najlepsza praktyka / sposób programowego zarejestrowania odbiornika. Chcę zarejestrować określone odbiorniki zgodnie z wyborem użytkownika.

Ponieważ rejestracja odbywa się za pośrednictwem pliku manifestu, zastanawiam się, czy istnieje właściwy sposób na osiągnięcie tego w kodzie.


2
CoderzPassion Broadcast Reciever najlepszy szczegółowy samouczek w historii
karanatwal.github.io

Proszę odnieść się do tego łącza stackoverflow.com/questions/15698790/ ...

Odpowiedzi:


64

Wygląda na to, że chcesz kontrolować, czy komponenty opublikowane w Twoim manifeście są aktywne, a nie dynamicznie rejestrować odbiornik (przez Context.registerReceiver ()) podczas działania.

Jeśli tak, możesz użyć PackageManager.setComponentEnabledSetting (), aby kontrolować, czy te składniki są aktywne:

http://developer.android.com/reference/android/content/pm/PackageManager.html#setComponentEnabledSetting(android.content.ComponentName, int, int)

Zauważ, że jeśli jesteś zainteresowany otrzymywaniem transmisji tylko podczas biegu, lepiej jest użyć registerReceiver (). Komponent odbiornika jest przydatny przede wszystkim wtedy, gdy musisz mieć pewność, że aplikacja jest uruchamiana za każdym razem, gdy wysyłana jest transmisja.


1
Sprytny ! Masz mnie prosto. Dziękuję bardzo
CoolStraw

Fajny - nie miałem pojęcia, że ​​możesz to zrobić :)
Chris Noldus


1
@hackbod Jak dodać znacznik metadanych w odbiorniku niestandardowym? Masz jakiś pomysł !! Muszę dodać tag metadanych, którego używamy w androidmanifest.xml.
Zala Janaksinh

1
Najlepszy samouczek do daty coderzpassion.com/implement-broadcastreceiver-android iw prostym języku
Jagjit Singh

269

W swojej onCreatemetodzie możesz zarejestrować odbiornik w następujący sposób:

private BroadcastReceiver receiver;

@Override
public void onCreate(Bundle savedInstanceState){

  // your oncreate code should be

  IntentFilter filter = new IntentFilter();
  filter.addAction("SOME_ACTION");
  filter.addAction("SOME_OTHER_ACTION");

  receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
      //do something based on the intent's action
    }
  };
     registerReceiver(receiver, filter);
}

Pamiętaj, aby uruchomić to w onDestroymetodzie:

 @Override
 protected void onDestroy() {
  if (receiver != null) {
   unregisterReceiver(receiver);
   receiver = null;
  }
  super.onDestroy();
 }

19
Dzięki, to działało świetnie. Aby wysłać transmisję, użyłem kodu Intent i = new Intent („SOME_ACTION”); sendBroadcast (i);
Ben Clayton,

7
dlaczego nie w wznowieniu i na starcie?
Syed Raza Mehdi

Co się stanie, jeśli nie wyrejestruję odbiornika? Czy pozostawiłby odbiornik telewizyjny zarejestrowany, nawet po ponownym uruchomieniu?
Jaydev

5
Nie ma gwarancji, że onDestroy()zostanie wywołana, co spowoduje potencjalny wyciek pamięci. Lepiej się zarejestrować / wyrejestrować onStart()/ onStop().
Neria Nachum

Czy to oznacza, że ​​nie muszę tworzyć klasy odbiorników transmisji? Mógłbym po prostu umieścić tutaj cały mój kod onReceive () i zadziałałoby?
Taslim Oseni

70

Jedną z ważnych kwestii, o których ludzie zapominają, jest czas życia Broadcast Receiver. Różnica między rejestracją programową a rejestracją w AndroidManifest.xml polega na tym. W pliku manifestu nie zależy to od czasu życia aplikacji. Podczas rejestracji programowej zależy to od czasu życia aplikacji. Oznacza to, że jeśli zarejestrujesz się w AndroidManifest.xml , możesz złapać transmitowane intencje nawet wtedy, gdy Twoja aplikacja nie jest uruchomiona.

Edycja: wspomniana uwaga nie jest już prawdą od wersji Android 3.1, system Android domyślnie wyklucza wszystkie odbiorniki z odbierania intencji, jeśli odpowiednia aplikacja nigdy nie została uruchomiona przez użytkownika lub jeśli użytkownik jawnie zatrzymał aplikację za pomocą menu systemu Android (w Zarządzaj → Aplikacja). https://developer.android.com/about/versions/android-3.1.html

Jest to dodatkowa funkcja bezpieczeństwa, ponieważ użytkownik może być pewien, że tylko te aplikacje, które uruchomił, będą odbierać intencje transmisji.

Można więc rozumieć, że odbiorniki zarejestrowane programowo w Aplikacji onCreate()miałyby taki sam efekt jak te zadeklarowane w AndroidManifest.xml z systemu Android 3.1 powyżej.


1
To dobra notatka. Właśnie patrzę na książkę, którą czytam o Androidzie i zastanawiam się, dlaczego obie metody wdrażania transmisji zostały wykonane. Wydaje mi się, że jest to zgodne z poprzednimi wersjami. Ale nie jestem pewien.
Neon Warge

Cóż, czy naprawdę uważasz, że zmiana jest prawdziwa? Mam na myśli ostatnie zdanie. System Android najprawdopodobniej zabije Twoją aplikację w dowolnym momencie, co spowoduje, że zarejestrowane programowo odbiorniki przestaną działać, ale zarejestrowany manifest nadal będzie działał.
JacksOnF1re

40

Zdefiniuj odbiornik transmisji w dowolnym miejscu w Aktywności / fragmencie w następujący sposób:

mReceiver = new BroadcastReceiver() {
 @Override
 public void onReceive(Context context, Intent intent) {
     Log.d(TAG," onRecieve"); //do something with intent
   }
 };

Zdefiniuj IntentFilter w onCreate()

mIntentFilter=new IntentFilter("action_name");

Teraz zarejestruj BroadcastReciever w onResume()i wyrejestruj go w onPause()[ponieważ rozgłaszanie nie jest używane, jeśli aktywność jest wstrzymana].

@Override
protected void onResume() {
     super.onResume();
     registerReceiver(mReceiver, mIntentFilter);
}

@Override
protected void onPause() {
    if(mReceiver != null) {
            unregisterReceiver(mReceiver);
            mReceiver = null;
    }
    super.onPause();
}

Aby uzyskać szczegółowy samouczek, spójrz na odbiornik transmisji - dwa sposoby implementacji .


najlepszy przykład, jaki do tej pory znalazłem! Dzięki!
Ayush Goyal

1
@SohailAziz Link zapewnia dobrą odpowiedź. Czy możesz umieścić kontekst linku w swojej odpowiedzi, tak aby w przypadku zerwania linku Twoja odpowiedź pozostała aktualna?
iRuth

moim zdaniem transmisja powinna być rejestrowana w trybie onResume i onPause, tak jak sugerowałeś, ale niektórzy ludzie twierdzą, że musi to być onCreate i onDestroy, czy możesz wyjaśnić zalety i wady obu?
Syed Raza Mehdi

2
@SyedRazaMehdi jeśli broadcast jest używane do aktualizacji UI [co jest w większości przypadków], powinieneś zarejestrować go w onResume i wyrejestrować w onPause, ponieważ broadcast będzie bezużyteczne w innym przypadku.
SohailAziz

Dzięki. To najlepsza odpowiedź.
Saeid Z

4
package com.example.broadcastreceiver;


import android.app.Activity;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {

   UserDefinedBroadcastReceiver broadCastReceiver = new UserDefinedBroadcastReceiver();

   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
   }

   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      getMenuInflater().inflate(R.menu.main, menu);
      return true;
   }

   /**
    * This method enables the Broadcast receiver for
    * "android.intent.action.TIME_TICK" intent. This intent get
    * broadcasted every minute.
    *
    * @param view
    */
   public void registerBroadcastReceiver(View view) {

      this.registerReceiver(broadCastReceiver, new IntentFilter(
            "android.intent.action.TIME_TICK"));
      Toast.makeText(this, "Registered broadcast receiver", Toast.LENGTH_SHORT)
            .show();
   }

   /**
    * This method disables the Broadcast receiver
    *
    * @param view
    */
   public void unregisterBroadcastReceiver(View view) {

      this.unregisterReceiver(broadCastReceiver);

      Toast.makeText(this, "unregistered broadcst receiver", Toast.LENGTH_SHORT)
            .show();
   }
}

1
Czy możesz wyjaśnić OP, dlaczego jest to najlepsza praktyka?
Martin Prikryl

1
Nie wyjaśniają, „oni” zawsze wysyłają kod, bo o wiele lepiej go znasz. -sarkazm
Neon Warge,

2

Według nasłuchiwania i nadawania globalnych wiadomości oraz ustawiania alarmów w typowych zadaniach i jak je wykonywać w systemie Android :

Jeśli klasa odbierająca nie jest zarejestrowana przy użyciu w swoim manifeście, możesz dynamicznie utworzyć instancję i zarejestrować odbiornik, wywołując Context.registerReceiver () .

Spójrz na registerReceiver (odbiornik BroadcastReceiver, filtr IntentFilter), aby uzyskać więcej informacji.


1
próbowałem zadzwonić, context.registerReceiverale nie mogę zadzwonić, proszę, spójrz na to pytanie stackoverflow.com/questions/13238600/ ...
Hunt

2

Najlepiej jest zawsze podawać pozwolenie podczas rejestracji odbiorcy, w przeciwnym razie otrzymasz je dla każdej aplikacji, która wysyła pasującą intencję. Może to pozwolić złośliwym aplikacjom na nadawanie do odbiornika.


1

dla LocalBroadcastManager

   Intent intent = new Intent("any.action.string");
   LocalBroadcastManager.getInstance(context).
                                sendBroadcast(intent);

i zarejestruj się onResume

LocalBroadcastManager.getInstance(
                    ActivityName.this).registerReceiver(chatCountBroadcastReceiver, filter);

i wyrejestruj to onStop

LocalBroadcastManager.getInstance(
                ActivityName.this).unregisterReceiver(chatCountBroadcastReceiver);

i odbierz…

mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.e("mBroadcastReceiver", "onReceive");
        }
    };

gdzie jest IntentFilter

 new IntentFilter("any.action.string")

1

Dwie możliwości

1) Jeśli chcesz czytać transmisję tylko wtedy, gdy działanie jest widoczne,

registerReceiver(...) W onStart()i unregisterReceiver(...)wonStop()

2) Jeśli chcesz czytać Transmisję, nawet jeśli Aktywność jest w tle,

registerReceiver(...)w onCreate(...)iunregisterReceiver(...) wonDestroy()

Premia:

Jeśli jesteś leniwy

Jeśli nie chcesz pisać zwykłego kodu do rejestrowania i wyrejestrowywania BroadcastReceiver w każdym działaniu, to

  1. Utwórz abstrakcyjne działanie
  2. Napisz standardowy kod w działaniu
  3. Pozostaw implementację jako metody abstrakcyjne

Oto fragment kodu:

Aktywność abstrakcyjna

public abstract class BasicActivity extends AppCompatActivity {

    private BroadcastReceiver broadcastReceiver;
    private IntentFilter filter;
    private static final String TAG = "BasicActivity";

    /**********************************************************************
    *                   Boilerplate code
    **********************************************************************/

    @Override
    public void onCreate(Bundle sis){
        super.onCreate(sis);
        broadcastReceiver = getBroadcastReceiver();
        filter = getFilter();
    }

    @Override
    public void onStart(){
        super.onStart();
        register();
    }

    @Override
    public void onStop(){
        super.onStop();
        unregister();
    }

    private void register(){
        registerReceiver(broadcastReceiver,filter);
    }

    private void unregister(){
        unregisterReceiver(broadcastReceiver);
    }

    /**********************************************************************
    *                   Abstract methods
    **********************************************************************/

    public abstract BroadcastReceiver getBroadcastReceiver();

    public abstract IntentFilter getFilter();

}

Korzystając z tego podejścia, możesz napisać bardziej standardowy kod, taki jak pisanie typowych animacji, powiązanie z usługą itp.

Zobacz pełny kod:

TUTAJ


0

Utwórz odbiornik transmisji

[BroadcastReceiver (Enabled = true, Exported = false)]

public class BCReceiver : BroadcastReceiver
{

    BCReceiver receiver;

    public override void OnReceive(Context context, Intent intent)
    {
        //Do something here
    }
}

Ze swojej aktywności dodaj ten kod:

LocalBroadcastManager.getInstance(ApplicationContext)
    .registerReceiver(receiver, filter);
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.