브로드캐스트 리시버

cluelin·2021년 12월 13일

참조
https://developer.android.com/guide/components/broadcasts

1. 브로드캐스트 수신 방법

  1. sendOrderedBroadcast(Intent, String)
    한번에 하나씩 전달.
  2. sendBroadcast(Intent)
    일반적인 형태. 순서없이 전달.
    Intent().also { intent ->
        intent.setAction("com.example.broadcast.MY_NOTIFICATION")
        intent.putExtra("data", "Notice me senpai!")
        sendBroadcast(intent)
    }
  1. LocalBroadcastManager.sendBroadcast
    동일한 앱에 전달.

2. 브로드캐스트 등록 방법

1.manifest에 선언된 수신자

<application>
   ...
	<receiver android:name=".MyBroadcastReceiver"  android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <action android:name="android.intent.action.INPUT_METHOD_CHANGED" />
            </intent-filter>
	</receiver>
</application>

manifest에서 application 하위 항목으로 receiver를 넣고
수신할 action을 등록해준다.

    private const val TAG = "MyBroadcastReceiver"

    class MyBroadcastReceiver : BroadcastReceiver() {

        override fun onReceive(context: Context, intent: Intent) {
            StringBuilder().apply {
                append("Action: ${intent.action}\n")
                append("URI: ${intent.toUri(Intent.URI_INTENT_SCHEME)}\n")
                toString().also { log ->
                    Log.d(TAG, log)
                    Toast.makeText(context, log, Toast.LENGTH_LONG).show()
                }
            }
        }
    }

위와같이 manifest를 통한 브로드캐스트 리시버의 등록은 앱의 진입점으로 사용되기때문에 중요하다.

즉, 앱이 실행되고있지않은 상황에서 인탠트를 통해 앱을 실행시킬수있다.

다만 onReceiver메서드가 반환되는 순간 시스템은 이 컴포넌트가 더이상 활성화 되어있지않다고 판단한다.
즉 언제든 종료시킬수있다.

또한, API26 이상에서는 몇가지 예외를 제외하고는 manifest를 사용하여 암시적 브로드캐스트 선언 불가능하다.

예외 목록
https://developer.android.com/guide/components/broadcast-exceptions

2.컨텍스트에 등록된 수신자

     val br: BroadcastReceiver = MyBroadcastReceiver()
     val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION).apply {
        addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED)
    }
    registerReceiver(br, filter)

브로드캐스트는 activity, application 등에 등록할수있고
등록한 context가 유효한 동안 브로드 캐스트를 수신한다.
context가 유효하지 않게되면 등록취소를 해야한다.

주의사항
1. onCreate에서 등록했으면, onDestroy에서 등록취소 해야한다.
2. onResume에서 등록했으면, onPause에서 등록취소해야한다. 여러번 등록되지않도록 하기 위함.
3. onSaveInstanceState에서 등록취소를 하면 안된다.

3. 오래 걸리는 작업의 경우

Broadcast캐스트를 받았을때 (즉, Receiver의 onReceive메소드에서) 오래걸리는 작업을 해야할때 단순히 백그라운드 쓰레드를 생성해서 작업하면 안된다.

    private const val TAG = "MyBroadcastReceiver"

    class MyBroadcastReceiver : BroadcastReceiver() {

        override fun onReceive(context: Context, intent: Intent) {
            val pendingResult: PendingResult = goAsync()
            val asyncTask = Task(pendingResult, intent)
            asyncTask.execute()
        }

        private class Task(
                private val pendingResult: PendingResult,
                private val intent: Intent
        ) : AsyncTask<String, Int, String>() {

            override fun doInBackground(vararg params: String?): String {
                val sb = StringBuilder()
                sb.append("Action: ${intent.action}\n")
                sb.append("URI: ${intent.toUri(Intent.URI_INTENT_SCHEME)}\n")
                return toString().also { log ->
                    Log.d(TAG, log)
                }
            }

            override fun onPostExecute(result: String?) {
                super.onPostExecute(result)
                // Must call finish() so the BroadcastReceiver can be recycled.
                pendingResult.finish()
            }
        }
    }

4. 권한을 사용한 송/수신

송신

sendBroadcast(Intent("com.example.NOTIFY"), Manifest.permission.SEND_SMS)

수신

    <receiver android:name=".MyBroadcastReceiver"
              android:permission="android.permission.SEND_SMS">
        <intent-filter>
            <action android:name="android.intent.action.AIRPLANE_MODE"/>
        </intent-filter>
    </receiver>
    var filter = IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)
    registerReceiver(receiver, filter, Manifest.permission.SEND_SMS, null )

0개의 댓글