[Android] 안드로이드 4대 컴포넌트 - Broadcast Receiver

4대 컴포넌트

- Activity
- Service
- Broadcast Receiver
- Content Provider

각 컴포넌트는 하나의 독립된 형태로 존재하며, 정해진 역할을 수행한다.
컴포넌트 간에 Intent라는 일종의 메시지 객체를 사용하여 상호 통신을한다.
가장 많이 사용하는 컴포넌트는 액티비티이며 나머지 컴포넌트도 매우 중요하므로 어떠한 기능을 담당하는지 파악해두어야 한다.

이미지1 안드로이드 4대 컴포넌트와 인텐트 


Broadcast Receiver

안드로이드에서 다양한 이벤트와 정보를 받아 반응하는 컴포넌트이다. Broadcast는 메시지를 여러 객체에게 전달하는 방법을 의미하는데 이렇게 전달되는 Broadcast 메시지를 Broadcast Receiver라는 어플리케이션 구성요소를 이용해 받을 수 있다.

*방송의 특징과 흡사하다. 방송은 불특정 다수에게 송신하고 필요한 사람만 수신하는 구조이다. 경우에 따라 특정 사람에게만 송신되는 경우도 있다.(유료채널)
이러한 방송에 귀 기울이고 있는 수신자가 Broadcast Receiver 이다.
수신만 가능한 것이 아니라 필요에 의해 방송도 가능하다.
이때 방송에서 채널에 해당하는 것이 action이다.
ex) 베터리 상태확인 action -> ACTION_BATTERY_CHANGED

*방송은 항상 송신되고 있지만 가입한 상품에 따라 수신할 수 있는 채널의 종류가 다르듯이 수많은 브로드캐스트 중에서 어떤 것을 수신할 것인지 등록하는 과정이 필요하다.

action 중 원하는 action을 IntentFilter를 통해 지정할 수 있다.
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
방송으로 따지면 2개의 채널이 있는 것인데 이중 채널을 선택하는 방법은 무엇일까?

브로드캐스트 리시버의 onReceive()를 통해 선택한다.
@Overridepublic void onReceive(Context context, Intent intent) {
    if(intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)){
        Toast.makeText(context, "Battery status is changed", Toast.LENGTH_SHORT).show();
    }else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)){
        Toast.makeText(context, "Screen ON", Toast.LENGTH_SHORT).show();
    }
}
BroadcastReceiver 를 상속받은 클래스에서 오버라이딩 하여 생성한다.
BroadcastReceiver로 감지된 내용이 최종적으로 onReceiver()로 들어오는 것이다.
onReceiver 내부에 원하는 action에 대한 처리를 하면 된다.

위 내용은 안드로이드 매니패스트에서 바로 적용할 수 있다.
<receiver android:name=".MyReceiver">
    <intent-filter>
        <action android:name="example.test.broadcast"></action>
    </intent-filter>
</receiver>
코드로 작성하는 것이 아닌 매니페스트에서 브로드캐스트 리시버를 사용하는 것의 차이는 filter의 등록방법 차이다. 브로드캐스트 리스트를 상속받은 클래스는 receiver가 되어 filter.addAction() 을 통해 수신할 action을 지정한 것을 매니페스트에 바로 적용할 수 있다.


특징
- 디바이스에서 발생하는 일 중 앱이 알아야 하는 상황이 발생하면 알림
- Receiver를 이용해 디바이스의 상황을 감지하고 적절한 작업을 수행
- 대부분 UI가 존재하지 않음


예제

// 안드로이드에 저장되어 있는 action을 활용해서 만들어보자
*베터리 상태 변화와 화면 켜짐에 대한 정보를 수신
*변화 감지시 토스트 메시지를 보여줌
*액티비티 내부에 BroadcastReceiver 객체를 생성해서 구현

1.MainActivity

BroadcastReceiver 객체 생성
BroadcastReceiver br = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)){
            Toast.makeText(context, "Battery status is changed", Toast.LENGTH_SHORT).show();
        }else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)){
            Toast.makeText(context, "Screen ON", Toast.LENGTH_SHORT).show();
        }
    }
};
위처럼 액티비티 내부에 객체를 생성하면 자동으로 onReceive()가 생성된다.
BroadcastReceiver로 감지되는 내용이 최종적으로 onReceive 안으로 들어온다.
ACTION_BATTERY_CHANGED - 베터리의 변화감지
ACTION_SCREEN_ON - 화면 켜짐 감지
안드로이드에서 지원하는 두가지 기능을 선택하였다.
변화가 감지되면 각각 변화에 맞게 토스트 메세지를 뿌린다.
이제 두가지 변화가 감지 되었을때 onReceive 로 들어올수 있도록 해보자.

onResume()안에다 다음과같이 설정한다.
@Override
protected void onResume() {
    super.onResume();
    Log.e("onResume","Resume!");
    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_BATTERY_CHANGED);
    filter.addAction(Intent.ACTION_SCREEN_ON);
    registerReceiver(br,filter);
}
onResume은 사용자가 해당 액티비티를 사용하고 있는 상태이다.
그전에 안드로이드 매니페스트안에 셋팅한 것을 기억해보자.
<receiver> 안에 <IntentFilter> 안에 <action> 을 셋탕했었다.
*위 예제를보면 IntentFilter를 생성하고 그안에 액션을 추가한다.
매니페스트 파일안에 action을 기입해 넣는 행위를 코드로 하고 있는 것이다.
마지막으로 registerReceiver(브로드캐스트리시버객체, 인텐트필터객체) 를 입력하면 2가지의 액션에 반응하는 브로드캐스트 리시버가 완성된다.

* 이제 onResume 상태일 때 베터리가 변화하거나 스마트폰화면을 껐다가 켜면 위에서 만들었던 onReceive() 로 들어가 해당 변화에 따른 토스트 메세지를 띄우게 된다.




// 나만의 action을 커스텀 해서 구현해보자 
*버튼을 누르면 지정 action으로 브로드캐스트를 하고 토스트메시지 보여줌

1. 인텐트 선언 후 나만의 action 생성
여기서 오레오 이전버전과 이후 버전으로 나뉜다 !! 대환장 삽질 .. 
오레오 이후 버전으로 먼저 가보자

MyReceiver 생성
앱 -> new -> other - > Broadcast Receiver를 생성하면
MyReceiver.java 가 생성되고 매니패스트 파일도 자동으로 추가된다.

매니패스트파일 
<receiver android:name=".MyReceiver"
    android:enabled="true"
    android:exported="true"
    >
</receiver>

MyReceiver.java
public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {      
        if(intent.getAction().equals("action.test.BROADCAST_TEST")){
            Toast.makeText(context, "Custom Broadcast", Toast.LENGTH_SHORT).show();
        }
    }
}
BroadcastReceiver를 상속받는 클래스이다.
첫번째 예제의 브로드캐스트 리시버 객체와 모양이 거의 비슷하다.
action.test.BROADCAST_TEST - 임의로 만들어놓은 action이다
String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";
베터리를 감지하는 액션도 사실 위와같은 스트링 형태이다.

나만의 커스텀 action을 간단하게 만들었으니 이제 MyReceiver의 onReceive 로 들어와서 토스트를 띄워보도록 하자.

MainActivity.java 

우선 MyReceiver 객체를 선언해두고
private MyReceiver myReceiver;

onResume
@Override
protected void onResume() {
    super.onResume();
    Log.e("onResume","Resume!");
    myReceiver = new MyReceiver();
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("action.test.BROADCAST_TEST");
    registerReceiver(myReceiver,intentFilter);
}
첫번째 예제와 동일하다.
사용자가 해당 액티비티를 사용하고있는 상태가 될 때 위에서 임의로 정한 action.test.BROADCAST_TEST를 인텐트 필터에 액션으로 추가한 후에 registerReceiver()메소드로 브로드캐스트 리시버 객체를 완성한다.

임의로 만든 액션은 안드로이드에서 제공하는 것처럼 따로 쓰레드로 검사하면서 감지하는 기능은 없기 때문에 간단하게 버튼을 눌러서 onReceive() 로 들어가 토스트메세지를 띄워보도록 하자.


Button send = findViewById(R.id.button_send_broadcast);
send.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {

        Intent intent = new Intent("action.test.BROADCAST_TEST");
        sendBroadcast(intent);
    }
});
다음처럼 인텐트를 생성하고 생성자 입력값으로 임의로 만든 액션을 입력한다.
sendBroadcast() 안에 인텐트객체를 넣고 버튼을 누르고 실행하면 MyReceiver로 들어가 임의의 액션을 거쳐 토스트 메세지를 띄우게 된다.



* 오레오 이전 버전으로 설명해보겠다.
간단하다.

먼저 onResume에서 MyReceiver에관한 내용을 지운다.

매니패스트파일 변경
<receiver android:name=".MyReceiver">
    <intent-filter>
        <action android:name="action.test.BROADCAST_TEST"></action>
    </intent-filter>
</receiver>
다음과같이 변경하고 실행



문제없이 동작한다.  끝 ...............



정리 - 

브로드캐스트리시버란 이름에 맞게 방송과 비교해서 설명하는게 좋을 것 같다. 
*방송의 특징이 불특정 다수에게 송신하고 필요한 사람만 수신하는 구조이다.
*유료채널처럼 특정 사용자에게만 송신되는 경우가 있다.
*이 모든것들을 채털로 구분한다. 

안드로이드에는 여러가지 기능이 있는데 베터리 변화를 감지하거나 화면의 켜짐 꺼짐등을 감지하는 것이다. 
*해당 기능은 불특정 다수에게 제공(송신)되고 필요한 경우에만 수신한다.
*특정 사용자 혹은 특정 상황에만 제공(송신)될 수 있다.
*이 모든것들을 action으로 구분한다. 

브로드캐스트 리시버는 위의 내용들을 제어하고 관리한다. 
1. 브로드캐스트 리시버가 생성되면 매니페스트파일에 등록된다.
2. 등록된 리시버 내부에 인텐트 필터가 생성되야하고 그 필터로 사용할 액션들을 설정할 수 있다. 
3. 최종적으로 onReceiver를 통해 액션에 따른 상황들을 설정한다. 
4. 안드로이드에서 제공하는 액션을 사용할 수도 있고 직접 커스텀해서 사용도 가능하다. 



참고
https://junghun0.github.io/2019/05/21/android-broadcastreceiver/
https://developer.android.com/guide/components/broadcasts?hl=ko
https://coding-factory.tistory.com/205
https://brunch.co.kr/@mystoryg/48

댓글

이 블로그의 인기 게시물

[Unity] GPGS(Google Play Games Services) 1.연동

[Unity] GPGS(Google Play Games Services) 2. 로그인

[JAVA] Array DataStructure & ArrayList와 LinkedList의 차이점