Receiver가 Android에 등록되어 있는지 확인하는 방법


답변:


68

이 스레드 를 고려하면 API가 API를 직접 제공하는지 잘 모르겠습니다 .

나는 같은 것을 궁금해했다.
내 경우 에는 수신 의도를 처리 한 후 인수로 자신을 전달 BroadcastReceiver하는 호출 Context#unregisterReceiver(BroadcastReceiver)을 구현합니다 .
수신기의있는 작은 기회가있다 onReceive(Context, Intent)가 여러에 등록되어 있기 때문에 방법은, 한 번 이상이라고 IntentFilters에 대한 가능성 생성 IllegalArgumentException에서 던진 존재는 Context#unregisterReceiver(BroadcastReceiver).

필자의 경우을 호출하기 전에 확인할 비공개 동기화 멤버를 저장할 수 Context#unregisterReceiver(BroadcastReceiver)있지만 API가 체크 메소드를 제공하면 훨씬 깨끗합니다.


313

수신자가 등록되었는지 확인하는 API 기능이 없습니다. 해결 방법은 코드를try catch block as done below.

try {

 //Register or UnRegister your broadcast receiver here

} catch(IllegalArgumentException e) {

    e.printStackTrace();
}

83
... :(
Sander Versluys

4
재미있는 점은 registerReceiver (mReceiver, filter1)에 대한 BroadcastReceiver에 대한이 호출의 오류를 포착하지 않는다는 것입니다.
JPM

1
@JPM 그렇습니다. 수신자의 인스턴스를 저장하고 등록되지 않은 경우 등록 해제를 확인하려고했습니다 null. 그러나 당신이 지적했듯이, 나는 가고 있습니다 try catch. 어리석은.

9
API를 작성하지 않아 Android로 다운 보트. 작업 솔루션을 제공해 주신 +1 :)
Vitali Denys

1
더 나은 게 뭐야? 이것을 사용하거나 부울 변수를 플래그로 사용합니까?
DAVIDBALAS1 1

34

가장 간단한 솔루션

수신기에서 :

public class MyReceiver extends BroadcastReceiver {   
    public boolean isRegistered;

    /**
    * register receiver
    * @param context - Context
    * @param filter - Intent Filter
    * @return see Context.registerReceiver(BroadcastReceiver,IntentFilter)
    */
    public Intent register(Context context, IntentFilter filter) {
        try {
              // ceph3us note:
              // here I propose to create 
              // a isRegistered(Contex) method 
              // as you can register receiver on different context  
              // so you need to match against the same one :) 
              // example  by storing a list of weak references  
              // see LoadedApk.class - receiver dispatcher 
              // its and ArrayMap there for example 
              return !isRegistered 
                     ? context.registerReceiver(this, filter) 
                     : null;
            } finally {
               isRegistered = true;
            }
    }

    /**
     * unregister received
     * @param context - context
     * @return true if was registered else false
     */
     public boolean unregister(Context context) {
         // additional work match on context before unregister
         // eg store weak ref in register then compare in unregister 
         // if match same instance
         return isRegistered 
                    && unregisterInternal(context);
     }

     private boolean unregisterInternal(Context context) {
         context.unregisterReceiver(this); 
         isRegistered = false;
         return true;
     }

    // rest implementation  here 
    // or make this an abstract class as template :)
    ...
}

코드에서 :

MyReceiver myReceiver = new MyReceiver();
myReceiver.register(Context, IntentFilter); // register 
myReceiver.unregister(Context); // unregister 

광고 1

-- 에 회신하여:

등록한 후 isRegistered 플래그를 설정해야한다는 점을 기억해야하기 때문에 실제로 그렇게 우아하지는 않습니다. – 스텔스 랍비

- "더 우아한"방식으로 수신기에 메소드를 추가하여 플래그를 등록 및 설정

기기를 다시 시작하거나 앱이 OS에 의해 종료 된 경우 작동하지 않습니다. – amin 6 시간 전

@amin-코드의 수명을 참조하십시오 (매니페스트 항목으로 시스템이 등록되지 않음) 등록 수신자 :)


2
이것은 정말 우아한 솔루션입니다. FWIW, Android Studio에서 BroadcastReceiver를 확장하려고 할 때 불평하고 onReceive를 재정의하려고합니다. 다행히도 필자의 경우 ceph3us가 설명하는 방식대로 작동하는 ScreenReceiver를 확장해야했습니다.
MarkJoel60

등록 후 isRegistered 플래그를 설정해야한다는 점을 기억해야하기 때문에 실제로 그렇게 우아하지는 않습니다.
Stealth Rabbi

예, "코드 내"섹션에서이 줄을 제거 할 수 있습니다. myReceiver.isRegistered = true;
Stealth Rabbi

이 클래스는 추상 클래스가 아니어야합니까? BroadcastReceiver를 확장하려면 onReceive 메소드를 구현해야합니다.
York Yang

@YorkYang 하단에 수업에 정보를 추가
ceph3us

27

이 솔루션을 사용하고 있습니다

public class ReceiverManager {

    private static List<BroadcastReceiver> receivers = new ArrayList<BroadcastReceiver>();  
    private static ReceiverManager ref;
    private Context context;

    private ReceiverManager(Context context){
        this.context = context;
    }

    public static synchronized ReceiverManager init(Context context) {      
        if (ref == null) ref = new ReceiverManager(context);
        return ref;
    }

    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter intentFilter){
        receivers.add(receiver);
        Intent intent = context.registerReceiver(receiver, intentFilter);
        Log.i(getClass().getSimpleName(), "registered receiver: "+receiver+"  with filter: "+intentFilter);
        Log.i(getClass().getSimpleName(), "receiver Intent: "+intent);
        return intent;
    }

    public boolean isReceiverRegistered(BroadcastReceiver receiver){
        boolean registered = receivers.contains(receiver);
        Log.i(getClass().getSimpleName(), "is receiver "+receiver+" registered? "+registered);
        return registered;
    }

    public void unregisterReceiver(BroadcastReceiver receiver){
        if (isReceiverRegistered(receiver)){
            receivers.remove(receiver);
            context.unregisterReceiver(receiver);
            Log.i(getClass().getSimpleName(), "unregistered receiver: "+receiver);
        }
    }
}

2
하하, 나는 그들이 편리하다고 생각합니다 :) 형식과 물건이 시작하고 끝나는 곳에 대한 더 빠른 개요 :) 각자 자신에게
slinden77

1
흠, 당신의 의견에 따라 그것을보고, 좋아 보인다! 당연히 내 이클립스 작업 공간을 망쳐하지만 그만큼 :)에 필요하지
slinden77

2
아, IntelliJ로 전환하면 일단 익숙해지면 Eclipse는 정말 오래되었다고 생각합니다. 집에서 바로 느끼게하십시오.
Martin Marconcini

2
@ MartínMarconcini 마침내 마침내 IntelliJ로 전환해야했습니다. 나는 그것을 매우 좋아하지만 동시에 2 개의 프로젝트에서 작업하는 것이 불가능하다는 사실을 경멸합니다.
slinden77

1
어두운면에 오신 것을 환영합니다.) 3 개의 다른 프로젝트로 3 개의 Android Studio를 열었습니다 ... 여러 프로젝트 문제가 무엇인지 확실하지 않지만 여러 프로젝트에서 작동한다는 것을 확신 할 수 있습니다. :)
Martin Marconcini

22

몇 가지 옵션이 있습니다

  1. 수업이나 활동에 깃발을 넣을 수 있습니다. 부울 변수를 클래스에 넣고이 플래그를보고 수신자가 등록되어 있는지 확인하십시오.

  2. 수신자를 확장하는 클래스를 작성하면 다음을 사용할 수 있습니다.

    1. 프로젝트에서이 클래스의 인스턴스가 하나만있는 싱글 톤 패턴.

    2. 수신자가 등록되어 있는지 알 수있는 방법을 구현하십시오.


1
나는 똑같이했지만 내 수신기는 AppWidgetProvider이며 SCREEN_ON_OFF 메시지를 받고 싶습니다. 그러나 unregisterReceiver (this); -예외가 발생합니다.
hB0

수신기 클래스의 플래그 인 결합 된 첫 번째 및 두 번째 옵션
Gaeburider

당신은 나에게 정확히 무슨 짓을하지 않는 메신저로 코드 예제를 줄 수 있습니까 ... @ chemalarrea 큰 도움이 될 것입니다
TapanHP

11

try / catch를 사용해야합니다.

try {
    if (receiver!=null) {
        Activity.this.unregisterReceiver(receiver);
    }
} catch (IllegalArgumentException e) {
    e.printStackTrace();
}

7

당신은 쉽게 할 수 있습니다 ....

1) 부울 변수 생성 ...

private boolean bolBroacastRegistred;

2) 방송 수신기를 등록 할 때 TRUE로 설정하십시오.

...
bolBroacastRegistred = true;
this.registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
....

3) onPause ()에서 ...

if (bolBroacastRegistred) {
    this.unregisterReceiver(mReceiver);
    bolBroacastRegistred = false
}

그냥 이제는 onPause ()에 더 많은 예외 오류 메시지가 표시되지 않습니다.

팁 1 : 항상 onDestroy ()가 아닌 onPause ()에서 unregisterReceiver ()를 사용하십시오. 팁 2 : unregisterReceive ()를 실행할 때 bolBroadcastRegistred 변수를 FALSE로 설정하는 것을 잊지 마십시오

성공!


6

이것을 onDestroy 또는 onStop 메소드에 넣는 경우. 활동이 다시 작성되면 MessageReciver가 작성되지 않은 것 같습니다.

@Override 
public void onDestroy (){
    super.onDestroy();
LocalBroadcastManager.getInstance(context).unregisterReceiver(mMessageReceiver);

}

3

브로드 캐스트 수신자에게 기본 활동 스레드의 핸들러 인스턴스에 대해 알리고 메시지를 기본 활동에 전달하는 데 메시지를 사용했습니다.

브로드 캐스트 수신기가 이미 등록되어 있는지 확인하기 위해 이러한 메커니즘을 사용했습니다. 브로드 캐스트 리시버를 동적으로 등록하고 브로드 캐스트 리시버가 실행중인 경우 브로드 캐스트 리시버를 두 번 만들거나 사용자에게 표시하지 않을 때 필요할 때가 있습니다.

주요 활동:

public class Example extends Activity {

private BroadCastReceiver_example br_exemple;

final Messenger mMessenger = new Messenger(new IncomingHandler());

private boolean running = false;

static class IncomingHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        running = false;    
        switch (msg.what) {
        case BroadCastReceiver_example.ALIVE:
    running = true;
            ....
            break;
        default:

            super.handleMessage(msg);
        }

    }
    }

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    IntentFilter filter = new IntentFilter();
        filter.addAction("pl.example.CHECK_RECEIVER");

        br_exemple = new BroadCastReceiver_example();
        getApplicationContext().registerReceiver(br_exemple , filter); //register the Receiver
    }

// call it whenever you want to check if Broadcast Receiver is running.

private void check_broadcastRunning() {    
        /**
        * checkBroadcastHandler - the handler will start runnable which will check if Broadcast Receiver is running
        */
        Handler checkBroadcastHandler = null;

        /**
        * checkBroadcastRunnable - the runnable which will check if Broadcast Receiver is running
        */
        Runnable checkBroadcastRunnable = null;

        Intent checkBroadCastState = new Intent();
        checkBroadCastState .setAction("pl.example.CHECK_RECEIVER");
        checkBroadCastState .putExtra("mainView", mMessenger);
        this.sendBroadcast(checkBroadCastState );
        Log.d(TAG,"check if broadcast is running");

        checkBroadcastHandler = new Handler();
        checkBroadcastRunnable = new Runnable(){    

            public void run(){
                if (running == true) {
                    Log.d(TAG,"broadcast is running");
                }
                else {
                    Log.d(TAG,"broadcast is not running");
                }
            }
        };
        checkBroadcastHandler.postDelayed(checkBroadcastRunnable,100);
        return;
    }

.............
}

방송 수신기 :

public class BroadCastReceiver_example extends BroadcastReceiver {


public static final int ALIVE = 1;
@Override
public void onReceive(Context context, Intent intent) {
    // TODO Auto-generated method stub
    Bundle extras = intent.getExtras();
    String action = intent.getAction();
    if (action.equals("pl.example.CHECK_RECEIVER")) {
        Log.d(TAG, "Received broadcast live checker");
        Messenger mainAppMessanger = (Messenger) extras.get("mainView");
        try {
            mainAppMessanger.send(Message.obtain(null, ALIVE));
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    .........

}

}

3

개인적으로 unregisterReceiver를 호출하고 예외가 발생하면 삼키는 방법을 사용합니다. 나는 이것이 추악하지만 현재 제공되는 가장 좋은 방법이라는 데 동의합니다.

수신자가 Android API에 추가되어 등록되어 있는지 확인하기 위해 부울 메소드를 얻는 기능 요청을 제기했습니다. https://code.google.com/p/android/issues/detail?id=73718 추가 된 것을 보려면 여기에서 지원 하십시오


2

귀하의 문제를 겪습니다. 신청서에 동일한 문제가 있습니다. 응용 프로그램 내에서 registerReceiver ()를 여러 번 호출했습니다.

이 문제에 대한 간단한 해결책은 사용자 지정 응용 프로그램 클래스에서 registerReceiver ()를 호출하는 것입니다. 이렇게하면 전체 응용 프로그램 수명주기 동안 브로드 캐스트 수신기가 하나만 호출됩니다.

public class YourApplication extends Application
{
    @Override
    public void onCreate()
    {
        super.onCreate();

        //register your Broadcast receiver here
        IntentFilter intentFilter = new IntentFilter("MANUAL_BROADCAST_RECIEVER");
        registerReceiver(new BroadcastReciever(), intentFilter);

    }
}

1

이것은 내가 한 방법입니다. ceph3us가 제공하고 slinden77이 편집 한 답변의 수정 된 버전입니다 (필요하지 않은 메소드의 반환 값을 제거 한 다른 것들 중에서도).

public class MyBroadcastReceiver extends BroadcastReceiver{
    private boolean isRegistered; 

    public void register(final Context context) {
        if (!isRegistered){
            Log.d(this.toString(), " going to register this broadcast receiver");
            context.registerReceiver(this, new IntentFilter("MY_ACTION"));
            isRegistered = true;
        }
    }
    public void unregister(final Context context) {
        if (isRegistered) {            
            Log.d(this.toString(), " going to unregister this broadcast receiver");
            context.unregisterReceiver(this);
            isRegistered = false;
        }
    }
    @Override
    public void onReceive(final Context context, final Intent intent) {        
        switch (getResultCode()){
        //DO STUFF
        }        
    }        
}

그런 다음 Activity 클래스에서

public class MyFragmentActivity extends SingleFragmentActivity{
    MyBroadcastReceiver myBroadcastReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        registerBroacastReceiver();       
    }

    @Override
    protected Fragment createFragment(){
        return new MyFragment();
    }

    //This method is called by the fragment which is started by this activity, 
    //when the Fragment is done, we also register the receiver here (if required)
    @Override
    public void receiveDataFromFragment(MyData data) {
        registerBroacastReceiver();
        //Do some stuff                
    }

    @Override
    protected void onStop(){        
        unregisterBroacastReceiver();
        super.onStop();
    }

    void registerBroacastReceiver(){
        if (myBroadcastReceiver == null)
            myBroadcastReceiver = new MyBroadcastReceiver();
        myBroadcastReceiver.register(this.getApplicationContext());
    }

    void unregisterReceiver(){
        if (MyBroadcastReceiver != null)
            myBroadcastReceiver.unregister(this.getApplicationContext());
    }
}

1

이 코드를 부모 활동에 넣었습니다.

registeredReceivers 목록 = new ArrayList <> ();

@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
    registeredReceivers.add(System.identityHashCode(receiver));
    return super.registerReceiver(receiver, filter);
}

@Override
public void unregisterReceiver(BroadcastReceiver receiver) {
    if(registeredReceivers.contains(System.identityHashCode(receiver)))
    super.unregisterReceiver(receiver);
}

1

나를 위해 다음이 효과가있었습니다.

if (receiver.isOrderedBroadcast()) {
       requireContext().unregisterReceiver(receiver);
}

0

응용 프로그램을 닫아도 브로드 캐스터가 이미 등록되어 있는지 확인하기 위해 수행 한 작업은 다음과 같습니다 (finish ()).

응용 프로그램을 실행하는 Firstime은 먼저 브로드 캐스트를 보냅니다. 브로드 캐스터가 여전히 실행 중인지 여부에 따라 true / false를 반환합니다.

내 방송사

public class NotificationReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent.getExtras() != null && intent.getStringExtra("test") != null){
            Log.d("onReceive","test");
            return;
        }
    }
}

내 주요 활동

// init Broadcaster
private NotificationReceiver nr = new NotificationReceiver();


Intent msgrcv = new Intent("Msg");
msgrcv.putExtra("test", "testing");
boolean isRegistered = LocalBroadcastManager.getInstance(this).sendBroadcast(msgrcv);

if(!isRegistered){
    Toast.makeText(this,"Starting Notification Receiver...",Toast.LENGTH_LONG).show();
    LocalBroadcastManager.getInstance(this).registerReceiver(nr,new IntentFilter("Msg"));
}

0

Dagger 를 사용하여 해당 수신자의 참조를 작성할 수 있습니다 .

먼저 다음을 제공하십시오.

@Provides
@YourScope
fun providesReceiver(): NotificationReceiver{
    return NotificationReceiver()
}

그런 다음 필요한 곳에 주입하십시오 (using constructor또는 field injection)

간단히 전달하십시오 registerReceiver.

또한 try/catch블록에 넣 습니다.


-3
if( receiver.isOrderedBroadcast() ){
     // receiver object is registered
}
else{
     // receiver object is not registered
}

1
방송은 완전히 다른 일이 한 번 봐 가지고있다 주문 이 링크
비벡 Barai

-7

NullPointerException을 확인하십시오. 수신자가 존재하지 않으면 ...

try{
    Intent i = new Intent();
    i.setAction("ir.sss.smsREC");
    context.sendBroadcast(i);
    Log.i("...","broadcast sent");
}
catch (NullPointerException e)
{
    e.getMessage();
}

1
NPE는 어떻게 / 어디서 발생합니까?
DustinB

실제로 실패하면 오류가 발생하지 않습니다. 슬프게도
domenukk

2
실제로, 그것은 IllegalArgumentException을 발생시킵니다
Portfoliobuilder
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.