Android - 오더드 브로드캐스트 & 스티키 브로드캐스트

woga·2022년 10월 15일
0

Android 공부

목록 보기
39/49
post-thumbnail

브로드 캐스트는 브로드 캐스트만 있는게 아닌 다양한 종류가 있다.

오더드 브로드캐스트

sendOrderedBroadcast(Intent intent, String receiverPermission) 메서드는 등록된 브로드캐스트 리시버 가운데 priority 값이 높은 순으로 전달한다.

prority는 AndroidManifest.xml에서 intent-filter에서 android:priority를 쓸 수도 있고, IntentFilter에 setPriority(int priority) 메서드로 정할 수도 있다.
(이 때 우선순위가 동일하면 랜덤으로 실행된다)

오더드 브로드캐스트는 여러 브로드캐스트 리시버를 순서대로 진행하면서 브로드캐스트 리시버 간에 결과를 넘겨줄 수도 있고, 브로드캐스트를 도중에 중지시킬 수도 있다.
오더드 브로드캐스트가 발생하면 여러 브로드캐스트 리시버가 협력할 수 있다는 것에 주의하자.

브로드캐스트 리시버는 프로세스 간 통신이 필요하므로 가벼운 작업은 아니다. 오더드 브로드캐스트는 여러 브로드캐스트 리시버 간에 결과를 넘겨가면서 계속 진행하는 용도보다는, 결과를 넘기다가 적정 시점이 되면 나머지 브로드캐스트 리시버를 스킵하는 용도에 적합하다.

예시) 모바일 오피스 군

여러 앱 간의 협력을 예로 들어보자. 한 그룹의 앱인 모바일 오피스 그룹에서 어떤 파일이 추가 되었다는 이벤트가 발생하면 이를 그 가운데 하나의 앱에서 액티비티로 보여주려고 한다.

1) 문서 앱이 파일 읽기를 시도
2) 문서 앱에서 읽을 수 있는 파일이 아니면 스프레드시트 앱에서 읽기를 시도
3) 이도 안되면 프리젠테이션 앱으로 읽기를 시도한다.

이 때 사용 가능한 방식이 오더드 브로드캐스트를 발생시키는 것이다. 각각의 앱에서 우선순위가 다른 브로드캐스트 리시버가 있으면 된다. 우선순위가 높은 브로드캐스트 리시버에서 정상적으로 처리될 때 abortBroadcast()호출하면 된다. 이 때 다음 브로드캐스트 리시버에는 브로드캐스트가 전달되지 않는다.

우선순위가 높은 브로드캐스트 리시버에서 setResultXxx()시리지의 메서드로, 다음 브로드캐스트 리시버에 변경된 값이나 추가된 값을 전달할 수도 있다.

ex) http 스킴이 없는 uri에 'http://' 를 붙인다

전달 받는 곳에서는 getResultXxx() 시리즈의 메서드로 값을 가져올 수 있다.

스티키 브로드캐스트

sendStickyBroadcast()는 Intent를 시스템에 등록해놓고, 해당 Intent를 받을 수 있는 브로드캐스트 리시버가 새로 등록되면 이 시점에 BroadcastReceiver의 onReceive()가 호출된다.

즉, 이벤트를 먼저 발생시키더라도 이벤트 상태를 알고자 하는 브로드캐스트 리시버가 등록되면 이벤트를 받는다.

시스템에서 보내는 스티키 브로드캐스트

시스템에서 보내는 스티키(sticky) 브로드캐스트는 Intent API 문서에서 'sticky broadcast'로 검색하면 확인할 수 있다.

  • ACTION_BATTERY_CHANGED
  • ACTION_DEVICE_STRING_LOW
  • ACTION_DOCK_EVENT

이 액션들에 대해서 브로드캐스트 리시버를 등록하면 배터리 상태나 저장소 부족 여부, 그리고 도킹 상태를 알 수 있다.

배터리 레벨 변경 스티키 브로드캐스트 처리

@Override
protected void onResume() {
	super.onResume();
    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_BATTERY_CHANGED);
    registerReceiver(receiver, filter);
 }
 
 private BroadcastReceiver receiver = new BroadcastReceiver() {
 	
    @Override
    public void onReceive(Context context, Intent intent) {
    	String action = intent.getAction();
        if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
        	Bundle bundle = intent.getExtras();
            int level = bundle.getInt();
            ...
         }
    }
};

@Override
protected void onPause() {
	unregisterReceiver(receiver);
    super.onPause();
}

registerReciever()가 호출되면 배터리 최신 정보가 바로 전달되고, BroadcastReciever의 onReceive 는 resume 이후에 실행되는 것을 볼 수 있다.

앱에서는 스티키 브로드캐스트를 권장하지 않음

앱에서는 sendStickyBroadcast() 메서드 호출이 권장되지 않는다. 롤리팝에서는 이 메서드의 지원을 중단하기도 했다.

따라서 앱에서 이벤트 보내는 용도로 스티키 브로드캐스트를 쓰지 말고, 브로드캐스트 리시버에서 스티키 브로드캐스트를 받아서 처리하는 데만 사용하자.

스티키 브로드캐스트의 보안 문제

스티키 브로드캐스트는 시스템 메모리에 정보가 계속 남아 있다. 그래서 어디선가 정보를 알고 싶을 때 언제든지 빼낼 수가 있기 때문에 보안 문제를 초래할 수 있다.

ex) 만약 SSO(single sign-on) 기능을 구현한다 해보자

한 앱에서 로그인하면 같은 아이디로 다른 앱에서도 자동 로그인되고, 명시적으로 로그아웃하면 다른 앱에서도 자동 로그아웃되는 게 SSO의 기본 기능이다. SSO를 구현하기 위해 Intent에 로그인 여부와 로그인 아이디 등을 스티키 브로드캐스트로 전달하면 어떨까?

onResume()에서 registerReceiver()를 실행한다면, 앱이 포그라운드로 올 때마다 최신 정보를 알 수 있고 그에 맞게 처리할 수 있다.
그런데 이 정보는 다른 앱에서도 읽을 수 있고, Intent 정보를 다른 것으로 바꿔치기 하고서 다시 sendStickyBroadcast()를 할 수도 있다. 쓰기에 따라서 유용할 것 같지만 이런 보안 문제 때문에 앱에서는 sendSticityBroadcast()를 쓰지 않는게 좋다.

profile
와니와니와니와니 당근당근

0개의 댓글