Deperecated/Android_강의

안드로이드 - BroadCastReceiver

누알라리 2020. 2. 19. 02:57
1. BroadCastReceiver란?

- 안드로이드OS가 특정 이름을 가진 브로드캐스트를 송출하면 단말기의 모든 APP들에서 특정 이름을 가진 BroadCastReceiver가 동작하는것.

- 특정 이벤트(문자수신, 부팅완료, 배터리부족 등)를 처리하기 위해 잘 사용된다.

Ex) 문자메세지를 수신했다는걸 안드로이드OS가 알리면, RECEIVE_SMS라는 이름을 갖는 BraodCastReceiver를 찾아서 동작하게 한다.

 

2. 명시적 인텐트

- 안드로이드의 4대 구성요소 중 하나를 동작시키기 위해 동작 시키고자 하는 구성 요소의 클래스명을 직접 기술하여 동작시키는것을 의미한다.

- 한번에 하나만 실행이 가능하다.

 

3. BroadCastReceiver 만들기

- app -> NEW -> Other -> BroadCastReceiver 생성

class TestReceiver : BroadcastReceiver() {

    // 2.
    // 자동으로 호출됨
    // BR은 화면을 처리하는게 아니기때문에 토스트메세지나 노티피케이션을 이용해 메세지를 띄워줘야한다.
    override fun onReceive(context: Context, intent: Intent) {

        var t1 = Toast.makeText(context, "리시버 동작", Toast.LENGTH_SHORT)
        t1.show()
    }
}

 

4. 예제- 명시적 인텐트를 사용해서 APP2에서 APP1의 BroadCastReceiver 동작시키기

1. APP1의 BroadCastReceiver을 호출하기 위해 APP1의 Package명을 AndroidManifest.xml에서 알아온다.

<AndroidManifest.xml>

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.hyunndy_03">

2. APP2에서 Intent에 부르고싶은 (패키지명, BroadCastReciver의 Class명)을 세팅해준다.

        button.setOnClickListener { view ->

            var intent = Intent()
            intent.setClassName("com.example.hyunndy_01", "com.example.hyunndy_01.TestReceiver")
            sendBroadcast(intent)
        }

3. BroadCastReceiver는 sendBroadcast() 메서드를 통해 호출할 수 있다.

 

5. 명시적 인텐트를 사용해 데이터 주고받기.

- 인텐트를 사용했기 때문에 송출-리시버 간 데이터 주고받기도 할 수 있다.

- APP1에서 putExtra()로 넣어서 보내고, BroadCastReceiver에서 getInExtra()로 추출하면 된다.

 

6. 암시적 인텐트

- 안드로이드 4대 구성요소 중 원하는 구성요소를 실행하기 위해 Intent Filter를 통해 설정한 이름을 이용한 것을 의미한다.

- 동일명의 이름이 여러 개 있을 경우에는 Activity의 경우에는 선택, 그 외의 경우에는 모두 실행된다.

- 클래스명이 모두 다르더라도 필터로 이름만 같으면 됨.

 <AndroidManifest.xml>
 
        <receiver>
            android:name=".TestReceiver"
            android:enabled="true"
            android:exported="true">

            <intent-filter>
                <action android:name="com.test.brapp1"/>
            </intent-filter>

        </receiver>
 <Second App>
 
     override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        button.setOnClickListener { view ->

           // var intent = Intent()

            // 명시적 인텐트
           // intent.setClassName("com.example.hyunndy_01", "com.example.hyunndy_01.TestReceiver")

            var intent = Intent("com.test.brapp1")
            sendBroadcast(intent)
        }

 

7. 암시적 인텐트의 안드로이드 8.0 이후 제약사항

- 안드로이드는 백그라운드 실행이 자유롭다는 점에서 개발의 자율성을 가지지만 높은 하드웨어 사양을 요구한다는 단점을 갖는다. (백그라운드 프로세싱과 CPU, 램을 많이 이용)

- 이에 안드로이드 8.0 이후에는 일부를 제외한 모든 BroadCastReceiver는 암시적 인텐트로 실행이 불가해졌다.

 

- 해당 리시버를 갖고있는 어플이 실행중일 때만 암시적 인텐트를 사용할 수 있다.

 

<Main App>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
		
        // APP이 실행중일 때 Receiver 등록.
        addReceiver()

        // 3. Intent를 이용해 BR가동.
        button.setOnClickListener { view ->

            var intent = Intent(this, TestReceiver::class.java)
            sendBroadcast(intent)
        }
    }

    // 안드로이드 8.0 이상에서의 암시적 인텐트는 해당 리시버를 갖고있는 어플이 작동중일 때만 가능하기 때문에
    // 코드상으로 끄고, 키고를 관리해줘야한다.
    fun addReceiver()
    {
        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
        {
            return
        }

        brapp1 = TestReceiver()
        
        // intent-filter에 적용되어있는 이름 등록
        var filter = IntentFilter("com.test.brapp1")
        registerReceiver(brapp1, filter)
    }
    
       //어플이 종료되면 리시버 null.
        override fun onDestroy() {
        super.onDestroy()

        if(brapp1 != null)
        {
            unregisterReceiver(brapp1)
            brapp1 = null
        }
    }