[Android] 안드로이드 4대 컴포넌트

mingsso·2023년 3월 18일

Android

목록 보기
1/12

안드로이드는 4가지 컴포넌트(액티비티, 서비스, 브로드캐스터, 콘텐츠 제공자)가 있으며, 이들은 안드로이드 앱의 필수적인 구성 요소임

  • 각 컴포넌트는 고유의 기능을 가지고 있고, 독립적인 형태로 존재함
  • 각 컴포넌트는 독립적인 생명주기에 의해서 실행됨
  • 각 컴포넌트는 인텐트를 통해 서로 상호작용할 수 있음

1️⃣ 액티비티(Activity)

사용자가 앱과 상호작용하는 하나의 화면

  • 안드로이드 앱은 하나 이상의 액티비티를 포함하고 있음
  • 인텐트를 통해 다른 액티비티를 호출할 수 있음
  • 액티비티 내부에는 하나 이상의 View 또는 ViewGroup을 포함하고 있어야 함
    • View 예시: TextView, ImageView, EditText 등
    • ViewGroup 예시: LinearLayout, ConstraintLayout 등



2️⃣ 서비스(Service)

UI를 제공하지 않으며, 백그라운드에서 어떠한 작업(파일 다운로드 등)을 처리하기 위해 사용됨

  • 서비스는 메인 스레드에서 동작한다!
  • 네트워크와 연동이 가능함
  • 애플리케이션이 종료되어도 이미 시작된 서비스는 백그라운드에서 계속 동작함
  • 서비스는 단일 인스턴스로 실행되므로, 일부러 싱글톤으로 만들 필요 없음


서비스는 시작 방식에 따라 스타티드 서비스와 바운드 서비스로 나눌 수 있음

  • 스타티드 서비스(Started Service/Unbound Service)
    • 액티비티와 상관없이 독립적으로 동작할 때 사용함
  • 바운드 서비스(Bound Service)
    • 서비스에서 제공하는 메소드를 다른 컴포넌트에서 호출할 수 있도록 한 것

개념이 어려워서 나중에 읽어보고 추가하겠음
https://full-stack.tistory.com/entry/%EC%84%9C%EB%B9%84%EC%8A%A4Service-3-%EB%B0%94%EC%9A%B4%EB%93%9C-%EC%84%9C%EB%B9%84%EB%93%9CBound-Service-%EB%A1%9C%EC%BB%AC-%EB%B0%94%EC%9D%B8%EB%94%A9



3️⃣ 브로드캐스트 리시버(BroadCast Receiver)

안드로이드 시스템 및 기타 안드로이드 앱에서 발생하는 각종 이벤트(기기 충전 시작, 비행기 모드 전환 등)의 정보를 받아와 핸들링함

  • 특정한 상황을 제외하고 대다수의 브로드캐스트는 안드로이드 시스템에서 발생함
  • 안드로이드 앱은 특정 브로드캐스트를 수신하도록 등록할 수 있으며, 브로드캐스트가 전송되면 시스템은 특정 유형의 브로드캐스트를 수신하도록 신청한 앱에 브로드캐스트를 자동으로 라우팅함
  • 브로드캐스트 자체도 앱을 시작할 수 있는 진입점 중 하나이기 때문에, 현재 실행되고 있지 않은 앱에도 시스템이 브로드캐스트를 전달할 수 있음

브로드캐스트 수신 방법

  • manifest에 broadcast receiver 선언
    • 인텐트 필터에 수신자가 구독할 브로드캐스트 작업을 지정함
<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>
  • broadcast receiver를 컨텍스트에 등록할 수도 있음
val br: BroadcastReceiver = MyBroadcastReceiver()
val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION).apply {
	addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED)
}

registerReceiver(br, filter)

브로드캐스트 전송 방법

안드로이드 앱에서 브로드캐스트를 전송할 수도 있음

  • sendOrderedBroadcast(Intent, String)
    • 한 번에 하나의 수신자에게 브로드캐스트를 전송함
  • sendBroadcast(Intent)
    • 정의되지 않은 순서로 모든 수신자에게 브로드캐스트를 전송함
  • LocalBroadcastManager.sendBroadcast
    • 발신자와 동일한 앱에 있는 수신자에게 브로드캐스트를 전송함
    • 앱 간 브로드캐스트를 전송할 필요가 없다면 로컬 브로드캐스트를 사용하는 것이 좋음(구현 효율적, 보안 안전)

브로드캐스트 리시버 사용 예시

  1. 애플리케이션이 기기 부팅 후 특정 액티비티를 실행하도록 설정
    • 매니페스트 파일에서 시작 액티비티 설정
    • BroadcastReceiver를 통해 부팅 완료 이벤트 수신 후 특정 액티비티 실행
class BootCompletedReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
    
        if(intent?.action == Intent.ACTION_BOOT_COMPLETED) {
            Toast.makeText(context, "부팅되었습니다.", Toast.LENGTH_LONG).show()
            val i = Intent(context, IntroActivity::class.java)
            i.flags = Intent.FLAG_ACTIVITY_NEW_TASK
            val pendingIntent = PendingIntent.getActivity(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT)

            try {
                pendingIntent.send()
            } catch (e: Exception) {
                Logger.e("onReceive", e.toString())
            }
        }
    }
}

유연성이 높음 -> 특정 이벤트에 반응하여 액티비티를 실행할 수 있음 (부팅 완료 후에만 실행할 작업 설정 가능)



4️⃣ 콘텐츠 제공자(Contents Provider)

안드로이드 앱 간 데이터 공유 정보를 관리함 (앱 내 데이터에 대한 액세스 권한을 관리함)

  • 특정 앱이 다른 앱의 데이터를 마음대로 열람할 수 있다면 보안상 큰 문제가 생길 것
  • BUT 갤러리에서 사진을 가지고 와야 하는 등 로컬 데이터에 접근해야 하는 경우가 있는데, 이때 콘텐츠 제공자가 안전하게 콘텐츠를 제공받을 수 있도록 함


  • 콘텐츠 제공자는 한 프로세스의 데이터에 다른 프로세스에서 실행 중인 코드를 연결하는 표준 인터페이스로, 데이터를 캡슐화하고 데이터 보안을 정의하는데 필요한 메커니즘을 제공함으로써 다른 애플리케이션이 앱 데이터에 안전하게 액세스하여 이를 수정할 수 있도록 허용함
  • 연락처, 갤러리 등과 같은 기본 데이터를 이용하는 용도로, 대부분 안드로이드 OS에 이미 구현되어 있는 콘텐츠 제공자로부터 데이터를 제공받아 사용함
  • 다른 컴포넌트와 달리 콘텐츠 제공자는 인텐트로 활성화되지 않는다!
    대신 콘텐츠 리졸버에 URI을 전달함으로써 콘텐츠 제공자의 데이터에 접근할 수 있게 된다
    *콘텐츠 리졸버: 다른 앱에서 콘텐츠 제공자를 통해 제공하는 데이터를 사용하기 위한 도구

🤔 실제로 구현해보면 좋을 것 같다
https://developer.android.com/guide/topics/providers/content-provider-basics?hl=ko
시간이 된다면.. 해보도록 하자



*️⃣ 인텐트(Intent)

컴포넌트 간 통신에 이용되는 메시징 객체

사용 사례

  • 액티비티 시작
      1. 실행할 대상의 액티비티 이름과 전달할 데이터를 담아서 인텐트를 생성함
      1. 생성한 인텐트를 startActivity()에 담아서 호출하면 액티비티 매니저에 전달됨
      1. 액티비티 매니저는 인텐트를 분석해서 지정한 액티비티를 실행시킴
      1. 전달된 인텐트는 최종 목적지인 타깃 액티비티까지 전달됨
      1. 타킷 액티비티에서는 전달받은 인텐트에 데이터가 있다면 이를 꺼내서 사용할 수 있음
	val intent = Intent(this, SubActivity::class.java)
	startActivity(intent)

  • 서비스 시작
    • Android 5.0 이상부터는 JobScheduler로 서비스를 시작할 수 있음
    • Android 5.0 이하는 Intent를 startService()에 전달하여 서비스를 시작할 수 있음

  • 브로드캐스트 전달
    • Intent을 sendBroadcast() 또는 sendOrderedBroadcast()에 전달하면 다른 앱에 브로드캐스트를 전달할 수 있음

인텐트 유형

  • 명시적 인텐트
    • 어떤 컴포넌트로 메시지를 보낼지 컴포넌트의 이름을 명확하게 개발자가 지정함
    • 시작하려는 액티비티 또는 서비스의 클래스 명을 알고 있어야 하기 때문에, 앱 내의 컴포넌트를 시작할 때 사용함

  • 암시적 인텐트
    • 특정 컴포넌트의 클래스명을 주는 것과 같은 직접적인 지정 없이, 어떠한 작업을 수행할 것인지만 선언해 다른 앱의 컴포넌트가 이를 처리할 수 있도록 함
      1. 암시적 인텐트를 사용하면, 안드로이드 시스템에서 작업을 수행할 적절한 컴포넌트를 찾음
      1. 안드로이드 시스템이 모든 앱에서 해당 인텐트와 일치하는 인텐트 필터를 검색함
      1. 해당 인텐트와 일치하는 인텐트 필터가 있으면 시스템에서 해당 컴포넌트를 시작하고, 인텐트 객체를 전달함
      1. 호환되는 인텐트 필터가 여러 개인 경우, 시스템에서 대화상자를 표시하여 사용자가 어느 앱을 사용할지 직접 선택할 수 있게 함
        ex) 사진을 업로드할 때 카메라 or 갤러리 앱 중 사용자에게 선택하게 하는 것
      1. 호환되는 인텐트 필터가 없을 경우, 호출은 실패하고 앱은 다운됨 -> 다운 방지를 위해 resolveActivity() 호출이 필요함
// ACTION_SEND 작업을 수행하는 인텐트이며, "text/plain" 데이터가 담김 
val sendIntent = Intent().apply {
    action = Intent.ACTION_SEND
    putExtra(Intent.EXTRA_TEXT, textMessage)
    type = "text/plain"
}

// 결과가 null이 아닌 경우, 인텐트를 처리할 수 있는 앱이 최소 하나는 있다는 뜻이므로 startActivity()를 호출해도 안전함 
if (sendIntent.resolveActivity(packageManager) != null) {
    startActivity(sendIntent)
}

<!--데이터 유형이 텍스트인 경우, ACTION_SEND 인텐트를 수신할 인텐트 필터가 있는 액티비티 선언-->
<activity android:name="ShareActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
</activity>






참고자료

https://codezaram.tistory.com/50
https://hungseong.tistory.com/23
https://while1.tistory.com/177
https://velog.io/@jeongminji4490/Android-Context
https://developer.android.com/guide/components/intents-filters?hl=ko
https://parkjh7764.tistory.com/151

profile
🐥👩‍💻💰

0개의 댓글