본문 바로가기
안드로이드

브로드캐스트 수신자

by 희안 2021. 4. 26.

안드로이드 앱은 액티비티, 서비스, 브로드캐스트수신자, 내용제공자 이렇게 4가지로 크게 구성되어 있다.

 

그 중 서비스는 오래 실행되는 작업을 위한 것으로 화면 뒷단에서 실행된다. 화면이 없으니 액티비티와 동작하는 방식도 다르다. 브로드캐스트 수신자는 앱 간이나 구성 요소 간에 메시지를 주고받을 수 있도록 한 것으로 서비스와 마찬가지로 화면이 없는 상태에서 인텐트에 포함된 메세지를 주고받을 때 사용된다.

 

그 중에서도, 안드로이드에서 브로드캐스팅이란 메세지를 여러 객체에 전달하는 것을 말한다. 이런 메세지 전달 방식은 단말 전체에 적용되는 메세지로 '글로벌 이벤트'라고 불린다. 만든 어플에서 브로드캐스팅 메세지를 받고 싶다면 브로드캐스트 수신자를 만들어 앱에 등록하면 된다. 브로드 캐스트 수신자도 앱의 구성요소여서 새로운 브로드캐스트 수신자를 만들면 역시 메니패스트 파일에 등록해주어야 한다. 그치만 브로드캐스트 수신자는 매니페스트 등록방식이 아닌 소스코드에서 registerReceiver()를 사용해 시스템에 등록해줄 수 있다. 이렇게 소스코드를 이용해서 등록하면 액티비티 안에서 브로드캐스트 메시지를 전달받아서 바로 다른 작업을 수행하도록 만들 수 있는 장점이 있다.

 

브로드캐스트 수신자 등록하기

브로드캐스트 수신자에는 onReceiver()를 정의해야한다. 이 메서드는 원하는 브로드캐스트 메시지가 도착하면 자동으로 호출이 된다. 하지만 시스템의 모든 메시지를 받을 순 없다. 만약 원하는 메세지만 받으려면 모든 메시지는 인텐트 안에 넣어져 전달되므로 원하는 메세지를 인텐트 필터를 사용해 시스템에 등록하면 된다!

<intent-filter>
      <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>

 

이제 SMS 메세지를 받으면 onReceive()가 자동으로 호출된다. 호출되었는지 알기위해 Log를 띄웠다. 아래 parseSmsMessage에선 Bundle객체에 있는 부가데이터 중 pdus를 가져왔다. (SmsMessage를 사용하려면 android.Telephony 클래스를 import해주기) 아래에 Build.Version.SDK_INT는 단말의 OS버전을 확인할 때 사용한다. Build.VERSION_CODES에는 안드로이드 OS버전별로 상수가 정의되어있다. 발신자 번호를 확인하려면 getOriginatingAddress()를 호출하고 문자 내용을 확인하려면 getMessageBody()를 사용한다. 그리고 이 앱에서 SMS 수신하기 위해선 RECEIVE_SMS권한이 있어야 한다. android.permission.RECEIVE_SMS를 Manifest에 추가해주었다!

public class SmsReceiver extends BroadcastReceiver {
    public static final String TAG = "SmsReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO: This method is called when the BroadcastReceiver is receiving
        // an Intent broadcast.
        Log.i(TAG, "onReceive called");
        
        Bundle bundle = intent.getExtras();
        SmsMessage[] messages = parseSmsMessage(bundle);
        
        if(messages != null && messages.length>0){
            String sender = messages[0].getOriginatingAddress();
            Log.i(TAG, "Sender: "+sender);
            
            String body = messages[0].getMessageBody();
            Log.i(TAG,"Body: "+body);
            
            Date receivedData = new Date(messages[0].getTimestampMillis());
            Log.i(TAG,"Date: "+receivedData.toString());
        }
    }
    
    private SmsMessage[] parseSmsMessage(Bundle bundle){
        Object[] objs = (Object[]) bundle.get("pdus");
        SmsMessage[] messages = new SmsMessage[objs.length];
        
        int smsCount = objs.length;
        for(int i=0;i<smsCount;i++){
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
                String format = bundle.getString("format");
                messages[i]=SmsMessage.createFromPdu((byte[])objs[i],format);
            }else{
                messages[i]=SmsMessage.createFromPdu((byte[])objs[i]);
            }
        }
        
        return messages;
    }
}

 

애뮬레이터 extended controls를 사용해서 문자를 보내봤더니 아래처럼 잘 로그에 찍힌다!

 

브로드캐스트 수신자로 받은 내용을 화면에 나타내고 싶다면 우선 액티비티로 화면을 만들고 이 화면을 띄워야한다. 브로드 캐스트 수신자에서 인텐트 객체를 만들고 startActivity()를 사용해 액티비티 쪽으로 인텐트 객체를 전달해줘야 하는 것!

 

만약 아까 말했듯이 매니페스트 파일안에 <receiver>로 추가안하고 소스파일에서 registerReceiver()를 사용해 등록하면 화면이 사용자에게 보일 때만 브로드캐스트 수신자에서 메세지를 받도록 설정할 수 있다. 다른앱에 메세지를 보내고 싶다면 만든 앱에서 sendBroadCast()를 사용해서 인텐트에 메세지를 넣어 보내야 한다. 이때는 받을 앱이 수신자를 설정해놓아야 한다.

 

단말의 입장에서는 다른사람으로부터 문자를 받았을때 텔레포니 모듈이 처리하고 처리된 정보가 인텐트에 담겨 브로드캐스팅 방식으로 다른 앱들에 전달된다. 브로드캐스트 수신자를 사용할때 주의할 점은 앱1번이 실행되어 있지않아도 앱1이 기다리는 메세지가 도착하면 앱2를 실행하고있는 와중에도 앱1이 실행될 수 있다는 점이다. 그리고 브로드캐스트 수신자를 포함하고 있는 앱의 메인 액티비티가 한번이라도 실행되어야 수신자가 메세지를 받을 수 있다!

 

 

 

'안드로이드' 카테고리의 다른 글

서버에 데이터 요청 후 응답받기 - 소켓  (0) 2021.04.28
스레드와 핸들러  (1) 2021.04.26
위험 권한 부여  (0) 2021.04.23
서비스 Service  (0) 2021.04.23
리소스, 메니페스트, 그래들  (0) 2021.04.23

댓글