-
[ Android ] 브로드캐스트 수신자Android 2020. 5. 18. 18:57
이 글은 부스트코스 강의를 공부하며 요약한 글입니다.
CatServant
Broadcast Receiver ( 브로드캐스트 수신자 )
- 애플리케이션이 글로벌 이벤트(Global event)를 받아서 처리하려면 Broadcast Receiver로 등록
- Global event : [ "전화가 왔습니다.", "문자 메세지가 도착했습니다" ] 와 같이 Android system 전체에 보내지는 이벤트
- Broadcast Reciever는 Intent filter를 포함하며, Manifest file에 등록함으로써 Intent를 받을 준비를 한다.
- Reciever가 Manifest file에 등록되었다면 따로 시작시키지 않아도 된다.
- Application은 Context class의 registerReceiver 메소드를 이용하면 런타임 시에도 Reciever를 등록할 수 있다.
- Service처럼 Broadcast 수신자도 UI가 없다.
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(); } } } }
실행결과
출처
'Android' 카테고리의 다른 글
[ Android ] Fragment Toolbar에서 back button 동작 안 하는 오류 (0) 2020.05.19 [ Android ] 위험 권한 (0) 2020.05.18 [ Android ] 스플래시 화면 ( 로딩 화면 ) (0) 2020.04.02 [ Android ] ListView (0) 2020.03.31 [ Android ] 페이지 슬라이딩 (0) 2020.03.31