공부용 블로그

Broadcast Receiver란? / 리시버로 인텐트 받기 본문

Android

Broadcast Receiver란? / 리시버로 인텐트 받기

tomato212 2020. 8. 2. 05:33

Broadcast 는 말 그대로 '방송하다' 라는 의미이다. 

그렇다면 Broadcast Receiver는 '방송을 수신하는 사람'이라는 것을 쉽게 유추할 수 있다. 

안드로이드에서도 같은 맥락으로 쓰인다.

 

안드로이드 시스템에서 어떤 이벤트가 발생했을때 시스템은 "system broadcast" 라는 메세지를 보낸다. 

이때 특정 이벤트가 발생한 것을 내 앱에서 알고 싶을때 Broadcast Receiver 를 통해 메세지를 받을 수 있다. 

 

예를들어 안드로이드 시스템을 학교의 방송반 이라고 해보자.

 

방송반은 어떤 이벤트가 발생했을때 모든 학급(불특정 다수)이 들을 수 있도록 방송을 내보낼 것이다. 

(방송을 내보내는 것 = 안드로이드 시스템이 system broadcast 라는 메세지를 보내는 것)

 

방송반은 방송을 내보낼때 정해진 규칙에 따라 이벤트를 구분한다.

 system broadcast(feat.이벤트1), system broadcast(feat.이벤트2) 이런식으로..

 

그런데 우리반은 다른 이벤트는 알고 싶지 않고, 오직 점심시간이 시작되는 방송만 듣고 싶다.

방송반에 우리반은  system broadcast(feat.점심시간 시작) 일때만 듣겠다고 알려준다.

이제 방송이 오면 우리는 system broadcast(feat.점심시간 시작) 이라는 방송만 들을 수 있다.

 

======================================================================================================

 

설명은 여기서 줄이고 Broadcast Receiver를 직접 사용해보자. (전체 코드는 맨 아래 있음)

 

적용해볼 예제는

기기에 충전기를 꽂으면 "Power Connected", 충전기를 뽑으면 "Power Disconnected" 라는 토스트를 띄우는 간단한 프로그램이다. 

아래 순서대로 따라해보자.

 

1. 안드로이드 스튜디오에서 프로젝트를 만든다.

프로젝트명 : PowerReceiver (Empty Activity 선택)

 

2. Broadcast Receiver 를 만들기 위해 File > New > Other > Broadcast Receiver 를 선택한다.

Class Name은 CustomReceiver, Exported와 Enabled 모두 체크

*Exported : 내 앱의 Broadcast Receiver가 외부 앱의 Broadcast를 수신할 수 있음

*Enabled : 시스템이 리시버의 인스턴스를 만들 수 있음

 

finish를 하고나면 BroadcastReceiver를 상속받는 CustomReceiver.java 이 자동으로 생성되어 있는 것을 확인할 수 있다.

AndroidManifest.xml 에도 리시버가 등록된다.

 

3. CustomReceiver를 멤버 변수로 만들고 초기화한다. 

MainActivity.java 에 CustomReceiver를 멤버 변수로 만들고 초기화한다.

* system broadcast 에 대한 부연설명 

초반에 언급했듯이 안드로이드 시스템은 특정 이벤트가 발생했을때 system broadcast 라는 메세지를 보낸다.

이 때 이 메세지는 인텐트로 감싸져 보내지게 된다.

리시버는 이 인텐트를 받는 것이고, 어떤 인텐트인지 인텐트 필터를 통해 구분하여 원하는 것만 받을 수 있다.

 

브로드캐스트 리시버는 어디에 등록하냐에 따라 두 가지로 분류할 수 있다.

(1) 매니페스트 작성(=Static receivers or manifest-declared receivers)

(2) 코드 작성 (=Dynamic receivers or ontext-registered receivers)

 

우리는 이 예제에서 두 가지 system broadcast 만 받을 것이다.

바로 ACTION_POWER_CONNECTED 와 ACTION_POWER_DISCONNECTED 이다.

안드로이드 시스템에서 기기의 파워가 연결되거나 해제될때 이 broadcasts들을 보낼 것이다.

 

참고로 안드로이드 8.0(API lever 26 혹은 그 이상) 에서는 정적 리시버를 사용할 수 없으므로

동적 리시버를 사용한다. minifest 파일에 작성된 <receiver> 요소는 삭제한다.

 

4. 인텐트 필터에 액션을 추가하여 리시버를 등록한다 .

(1) MainActivity.java 의 onCreate() 에 IntentFilter의 인스턴스를 만든다.

시스템이 인텐트(system broadcast)를 보내려고 할때 인텐트 필터에 등록되어 있는 action을 기준으로 broadcast receiver를 찾는다.

(2) MainActivity.java 의 onCreate() 끝에 다음의 action을 filter 객체에 추가한다.

(3) MainActivity.java 의 onCreate() 끝에 MainActivity의 context를 사용하여 리시버를 등록한다.

this.registerReceiver(mReceiver, filter); // 바로 위의 이미지 참조

5. 리시버를 해제한다. 

(2) system resource와 leaks을 줄이기 위해 등록한 리시버를 해지한다.
동적 리시버는 더이상 필요하지 않거나 해당 액티비티나 앱이 destroy 되기전에 등록을 해지해야 한다.

6. CustomReceiver 클래스에서 onReceive() 를 구현한다.

브로드캐스트 리시버가 인텐트를 받을때 onReceive()로 전달된다.

 

(1) 기존에 작성되어 있던 onReceive() 안의 내용을 모두 삭제하고, 아래의 코드를 작성한다.

(2) intentAction 값을 식별하기위한 switch case문을 작성한다.

 

 

7. 앱 실행 및 테스트 

시스템의 파워 연결 여부에 따라 토스트 메세지가 띄워지게 된다. 

단, MainActivity.java의 onDestroy() 에서 등록했던 리시버를 해제하기 때문에 앱을 종료시키면(Destroy되면

더 이상 방송을 수신하지 않으므로 토스트 메세지도 띄워지지 않는다.

 

======================================================================================================

(전체 코드)

MainActivity.java

package com.example.powerreceiver;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

private CustomReceiver mReceiver = new CustomReceiver();


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

IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
filter.addAction(Intent.ACTION_POWER_CONNECTED);


this.registerReceiver(mReceiver, filter);
}

@Override
protected void onDestroy() {
this.unregisterReceiver(mReceiver);
super.onDestroy();
}
}

 

CustomReceiver.java

 

package com.example.powerreceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class CustomReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
String intentAction = intent.getAction();

if (intentAction != null) {
String toastMessage = "unknown intent action";
switch (intentAction){
case Intent.ACTION_POWER_CONNECTED:
toastMessage = "Power connected!";
break;
case Intent.ACTION_POWER_DISCONNECTED:
toastMessage = "Power disconnected!";
break;
}

Toast.makeText(context, toastMessage, Toast.LENGTH_SHORT).show();
}
}
}