ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ Android ] 브로드캐스트 수신자
    Android 2020. 5. 18. 18:57

     

    이 글은 부스트코스 강의를 공부하며 요약한 글입니다.

     

      CatServant  

     

     Broadcast Receiver ( 브로드캐스트 수신자 )

     

    1. 애플리케이션이 글로벌 이벤트(Global event)를 받아서 처리하려면 Broadcast Receiver로 등록
    2. Global event : [ "전화가 왔습니다.", "문자 메세지가 도착했습니다" ] 와 같이 Android system 전체에 보내지는 이벤트
    3. Broadcast Reciever는 Intent filter를 포함하며, Manifest file에 등록함으로써 Intent를 받을 준비를 한다.
    4. Reciever가 Manifest file에 등록되었다면 따로 시작시키지 않아도 된다.
    5. Application은 Context class의 registerReceiver 메소드를 이용하면 런타임 시에도 Reciever를 등록할 수 있다.
    6. Service처럼 Broadcast 수신자도 UI가 없다.

    SMS 수신 과정 [ 출처 : https://www.edwith.org/boostcourse-android/lecture/17069/ ]

     

    Intent ( 인텐트 ) Broadcast ( 브로드캐스트 )

    Activity를 실행하면 foreground로 실행되어 사용자에게 보여진다.

    Intent를 받으면 onReceive( ) 메소드가 자동으로 호출된다.

    Background로 동작하므로 사용자가 모른다.
    브로드캐스트 전송 방법  
    sendOrderedBroadcast ( Intent, String )

    순차 브로드캐스트

    한 번에 하나의 수진자에만 전달되므로 순서대로 진행된다. 중간에 취소하면 그 다음 수신자는 받지 못한다. 수신자가 실행되는 순서는 인텐트 필터의 속성으로 정할 수 있다. 만약 순서가 같은 경우 임의로 실행된다.

    sendBroadcast ( Intent )

    일반 브로드캐스트

    비동기적으로 실행되며 모든 수신자는 순서없이 실행된다. ( 때로는 동시에 실행된다. ) 효율적이긴 하나, 한 수신자의 처리 결과를 다른 수신자가 이용할 수 없고 중간에 취소가 불가능하다.

    LocalBroadcastManager.sendBroadcast  

     

     Code

    • AndroidManifest.xml

            <receiver
                android:name=".SmsReceiver"
                android:enabled="true"
                android:exported="true">
                <intent-filter>
                    <action android:name="android.provider.Telephony.SMS_RECEIVED" />
                </intent-filter>
            </receiver>
    • SmsActivity.java
    public class SmsActivity extends AppCompatActivity {
        EditText editText;
        EditText editText2;
        EditText editText3;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_sms);
    
            editText = (EditText) findViewById(R.id.editText);
            editText2 = (EditText) findViewById(R.id.editText2);
            editText3 = (EditText) findViewById(R.id.editText3);
    
            Button button = (Button) findViewById(R.id.button);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    finish();
                }
            });
    
            // 전달받은 Intent 확인
            Intent passedIntent = getIntent();
            processCommand(passedIntent);
        }
    
        @Override
        protected void onNewIntent(Intent intent) {
            processCommand(intent);
            super.onNewIntent(intent);
        }
    
        private void processCommand(Intent intent) {
            if (intent != null) {
                String sender = intent.getStringExtra("sender");
                String contents = intent.getStringExtra("contents");
                String receivedDate = intent.getStringExtra("receivedDate");
    
                editText.setText(sender);
                editText2.setText(contents);
                editText3.setText(receivedDate);
            }
        }
    }
    • SmsReceiver.java

    onRecive 메소드의 파라미터로 전달받은 Intent 객체 안에는 SMS를 보낸 사람이나 내용이 들어 있다. 따라서 그 부가데이터를 확인하려면 SMS 정보를 화면에 보여줄 수 있다.

    다만 화면이 없는 BroadcastReceiver로 받았기 때문에 Activity 쪽으로 전달한 후에 화면에 보여주어야 한다. 

    ( SMS를 수신할 때는 권한이 있어야 하며 AndroidManifest.xml 파일 안에 RECEIVE_SMS 권한을 추가하면 수신할 수 있다. -> 위험권한 )

    public class SmsReceiver extends BroadcastReceiver {
        private static final String TAG = "SmsReceiver";
        private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    
        @Override
        public void onReceive(Context context, Intent intent) { // Callback method
            Log.e(TAG, "onReceive() 호출됨.");
    
            Bundle bundle = intent.getExtras();
            SmsMessage[] messages = parseSmsMessage(bundle);
    
            if (messages.length > 0) {
                String sender = messages[0].getOriginatingAddress();
                Log.e(TAG, "sender : "+sender);
    
                String contents = messages[0].getMessageBody().toString();
                Log.e(TAG, "contents : "+contents);
    
                Date receivedDate = new Date(messages[0].getTimestampMillis());
                Log.e(TAG, "received date : "+receivedDate);
    
                sendToAcvitivy(context, sender, contents, receivedDate);
            }
        }
    
        private  void sendToAcvitivy(Context context, String sender, String contents, Date receivedDate) {
            Intent intent = new Intent(context, SmsActivity.class);
    
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                    |Intent.FLAG_ACTIVITY_SINGLE_TOP
                    |Intent.FLAG_ACTIVITY_CLEAR_TOP);
            intent.putExtra("sender", sender);
            intent.putExtra("contents", contents);
            intent.putExtra("receivedDate", format.format(receivedDate));
    
            context.startActivity(intent);
        }
    
        private SmsMessage[] parseSmsMessage(Bundle bundle) {
            Object[] objects = (Object[]) bundle.get("pdus");
            SmsMessage[] messages = new SmsMessage[objects.length];
    
            for (int i=0; i<objects.length; i++) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    // 마시멜로우 이후 버전
                    String format = bundle.getString("format");
                    messages[i] = SmsMessage.createFromPdu((byte[])objects[i], format);
                }
                else {
                    messages[i] = SmsMessage.createFromPdu((byte[])objects[i]);
                }
            }
    
            return messages;
        }
    }
    • MainActivity.java

    아래의 코드는 위험권한을 부여하는 코드이다.

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // 권한이 있는지 체크
            int permissionCheck = ContextCompat.checkSelfPermission(this,
                    Manifest.permission.RECEIVE_SMS);
            if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
                // 권한이 주어져 있으면
                Toast.makeText(this, "SMS 수신 권한 주어져 있음", Toast.LENGTH_LONG).show();
            }
            else {
                Toast.makeText(this, "SMS 수신 권한 없음", Toast.LENGTH_LONG).show();
    
                // 권한을 부여하자
                if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                        Manifest.permission.RECEIVE_SMS)) {
                    Toast.makeText(this, "SMS 권한 설명 필요함", Toast.LENGTH_LONG).show();
                } else {
                    // 시스템에 권한 요청 -> 대화 상자 띄우기
                    ActivityCompat.requestPermissions(this,
                            new String[] {Manifest.permission.RECEIVE_SMS}, 101);
                }
            }
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                               @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            switch (requestCode) {
                case 101:
                    if (grantResults.length > 0) {
                        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                            Toast.makeText(this, "SMS 수신 권한을 사용자가 승인함", Toast.LENGTH_LONG).show();
                        } else if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
                            Toast.makeText(this, "SMS 수신 권한을 사용자가 거부함", Toast.LENGTH_LONG).show();
                        }
                    } else {
                        Toast.makeText(this, "SMS 수신 권한을 부여받지 못함", Toast.LENGTH_LONG).show();
                    }
            }
        }
    }

     

     

     실행결과

    앱 실행 화면

     

     

    출처

     

    [LECTURE] 1) 브로드캐스트 수신자 : edwith

    들어가기 전에 브로드캐스팅(Broadcasting)이란 방송의 의미로 여러 사람에게 동시에 데이터를 전달한다는 뜻입니다. 여러분이 잘 아는 MBC, KBS 그리고 SBS 방송사의 ... - 부스트코스

    www.edwith.org

     

    Do it! 안드로이드 앱 프로그래밍

    7년 연속 안드로이드 분야 1위! 전면 개정 5판(안드로이드 8.0 오레오 버전 · 안드로이드 스튜디오 3.0 반영판)이 나왔다! 『Do it! 안드로이드 앱 프로그래밍』의 다섯 번째 전면 개정판이 나왔다. �

    book.naver.com

     

    브로드캐스트 개요  |  Android 개발자  |  Android Developers

    Android 앱은 Android 시스템 및 기타 Android 앱에서 게시-구독 디자인 패턴과 유사한 브로드캐스트 메시지를 받거나 보낼 수 있습니다. 관심 있는 이벤트가 발생할 때 이러한 브로드캐스트가 전송됩�

    developer.android.com

    댓글

Designed by Tistory.