Android

Android 01. 인텐트(Intent)란?

shin96bc 2022. 5. 12. 17:17

(1) 인텐트(Intent)의 정의

     1) 안드로이드 어플리케이션의 4가지 구성요소(Component) 간에 작업 수행을 위한

         정보를 전달하는 역할을 합니다.

         (Activity(화면구성), Service(백단작업), Broadcast Receiver(방송수신), Content Provider(Data공유))

         (Intent는 메시징 객체로 다른 앱 구성요소로부터 작업을 요청하는데 사용합니다.)

 

     2) Intent의 사례

          <1> Activity

               1> Activity의 새 인스턴스를 시작하려면 Intent를 startActivity() 로 전달하면 됩니다.

               2> Intent는 시작할 Activity 를 설명하고 모든 필수 데이터를 담습니다.

               3> 대표 메서드

                    1. startActivity(): 새 Activity를 열어줌 ( 단방향 )

                    2. startActiviryForResult(): 새 Activity를 열어줌 + 결과값 전달 ( 양방향 )

cf) requestCode 는 int형이고, 여러 Activity를 쓸 경우에 어떤 Activity인지 식별하기 위한 값입니다.

                     3. startActiviryForResult() 사용법

cf) MainActivity(위의 Arithmetics 와 동일한 역할)
cf) TestActivity(위의 DateArithmetics 와 동일한 역할)

                     4. putExtra() 사용법

                          - 1번째 파라미터로 스트링 값이 들어갈 수 있다. (이 값은 키값이 됩니다)

                          - 2번째 파라미터로 기본형, 스트링, 배열 등 다양한 값이 들어갈 수 있습니다.

                            (이 값은 벨류값이 됩니다.)

cf) MainActivity 에서 값을 세팅합니다.

                          - 이렇게 값을 put 하면 Intent 된 class 에서 키값으로 벨류값을 꺼낼 수 있습니다.

cf) TestActivity 에서 값을 꺼냅니다.

                     

               4> startActivity() 와 startActivityForResult() 의 차이점

                    1. startActivity는 새로운 Activity에 값을 전달하면서 새로운 Activity를 열어줄 수 있지만,

                       새로운 Activity로 부터 결과값을 돌려받지는 못한다.

                    2. startActivityForResult는 새로운 Activity에 값을 전달하면서 새로운 Activity를 열어줄 수 있고,

                       새로운 Activity로 부터 결과값을 돌려받을 수 있다.

 

          <2> Service

                1>service란?

                     1. service란 백그라운드에서 오래 실행되는 작업을 수행할 수 있는 애플리케이션

                        구성요소이며, 사용자 인터페이스를 제공하지 않습니다.

                     2. 다른 애플리케이션 구성 요소가 service를 시작할 수 있으며, 이는 사용자가 다른

                          애플리케이션으로 전환하더라도 백그라운드에서 계속해서 실행됩니다.

                     3. 이외에도, 구성요소를 service에 바인딩하여 service와 상호작용할 수 있으며,

                          심지어는 프로세스 간 통신(IPC)도 수행할 수 있습니다. 예를들어 한 service는

                          네트워크 트랜잭션을 처리하고, 음악을 재생하고 파일 I/O를 수행하거나

                          콘텐츠 제공자와 상호작용할 수 있으며, 이 모든 것을 background에서

                          수행할 수 있다.

                     4. 간단한 예시를 들자면,

                         안드로이드 앱 이용 중 음원재생과 같은 작업들은 홈버튼을 누르거나 전원버튼을 

                         눌러서 화면을 끄더라도 계속 음원이 재생되어야 합니다. 이럴 경우에 service

                         구성 요소를 사용하는 것입니다.

                2> service를 시작해 1회성 작업(파일 다운로드 등)을 수행하게 하려면

                     인텐트를 startService()에 전달하면 됩니다.

                3> Intent는 시작할 서비스를 설명하고 모든 필수 데이터를 담고 있습니다.

                4> service가 클라이언트 - 서버 인터페이스로 디자인 된 경우 다른 구성요소로부터

                    service에 바인딩하려면 Intent를 bindService()에 전달하면 됩니다.

Service의 생명주기 (출처: https://limkydev.tistory.com/44)

                      1. onBind()

                           - onBind() 는 BoundService타입 방식으로 사용합니다.

                      2. onCreate()

                           - service가 구동하면 최초에 한번만 실행됩니다.

                      3. onStartCommand()

                           - service가 생성되고 다음으로 실행되는 함수는 onstart() 였으나, 

                             onStartCommand() 함수를 사용할 것을 권장합니다.

                           - 또 service가 실행되고 있는 상태에서 또 service 시작을 할 경우 

                             onStartCommand() 함수를 탑니다.

                      4. onDestroy()

                           - service 중지를 하는 경우 실행되는 함수입니다.

 

                5> startService 와 bindService 의 차이점

                     1. startService는 service를 실행하고 service에 직접적인 접근을 할 수 없습니다.

 

                         하지만 bindService는 service안의 onBind callback 메서드를 통해서 값을 전달

                         받을 수 있고 service 인스턴스를 직접 return 받아 service의 public 메서드를

                         통해서 접근할 수도 있습니다.

 

                     2. startService로 실행된 service는 앱의 뒤로가기 버튼으로 애플리케이션을 종료해도

                        background에서 무한정 실행됩니다. startService로 실행된 service를 종료하기 

                        위해서는 service의 onStartCommand callback 메서드에서 작업수행 후 

                        stopSelf() 메서드를 호출하는 로직으로 구성하는 방법과, Activity에서

                        stopService() 메서드로 종료하는 방법이 있습니다.

                        ※ Oreo버전 이상부터는 startForegroundService() 로 실행해야 무한정 실행 됩니다

                            startService로 실행하면 50 ~ 60초 후에 service가 종료됩니다.

                            startForegroundService는 호출 후 대략 5초 이내에 startForeground 메서드가

                            실행되지 않으면 Exception이 발생하고, binding된 구성요소가 있으면

                            onUnbind callback 메서드 호출과 함께 파괴됩니다.※

 

                        하지만 bindService로 실행하는 service는 목적 자체가 service와 다른 구성요소 간의

                        소통이므로 애플리케이션의 Activity에서 onDestroy가 호출된 후 자동으로 unbind

                        처리가 됩니다. 다만 홈버튼으로 나갔을 경우에는 unbind처리가 되지 않습니다.

 

                     3. 같은 구성요소에서 startService를 여러번 호출하게되면 각각 다른 startId를 갖으며,

                        하나의 service 인스턴스 안에서 onStartCommand 메서드가 여럿 실행될 수 있지만,

 

                        bindService는 여러번 호출해도 onBind 메서드는 한번만 호출된다는 것입니다.

                        그러나 bindService를 호출할 때 아규먼트(파라미터)로 전달한 serviceConnection

                        인스턴스의 onServiceConnected callback 메서드는 매번 호출해줍니다.

 

                6> 설명 & 사용법

                     1. startService()

 

                     2. bindService()

 

          <3> Broadcast

                1> 브로드캐스트는 모든 앱이 수신할 수 있는 메세지입니다.

                2> 시스템이부팅될 때 또는 기기가 충전을 시작할 때 등 시스템 이벤트에 대한

                     다양한 브로드캐스트를 전달합니다.

                3> 인텐트를 sendBroadcast() 또는 sendOrderedBroadcast() 에 전달하면 다름 앱에 

                     브로드캐스트를 전달할 수 있습니다.

                2> 설명 & 사용법

                     1. broadcastIntent()

 

                     2. sendBroadcast(Intent intent)

                          - 정의되지 않은 순서로 모든 수신자에 broadcast 를 전송한다.

                          - 일반 broadcast 라고 한다.

                          - 일반 broadcast 는 상당히 효율적이지만 수신자가 다른 수신자의 결과를 읽거나

                             broadcast 로 부터 수신한 데이터를 전파하거나 브로드캐스트를 중단할 수 없음을

                             의미한다.

 

                     3. sendOrderedBroadcast(Intent intent, String str)

                          - 한 번에 하나의 수신자에 broadcast 를 전송한다.

                          - 각 수신자는 차례로 실행되기 때문에 결과를 다음 수신자로 전파하거나 broadcast 를

                             완전히 중단하여 broadcast 가 다른 수신자로 전달되지 않도록 할 수 있다.

                          - 수신자가 실행되는 순서는, 일치하는 Intent-Filter 의 android:priority 속성으로

                             제어할 수 있다.

                          - 우선순위가 동일한 수신자는 임의의 순서로 실행된다.

 

                     4. sendStickyBroadcast(Intent intent)

                          - 일반적인 broadcast 는 sendBroadcast() 로 전달되는 순간에 등록된 receiver 들의

                             onReceive() 만을 호출하지만, sendStickyBroadcast() 로 보낸 broadcast 는 system 에

                             남아있다가, 새롭게 해당 broadcast 를 받을 수 있는 receiver 가 등록되면 새로 등록된

                             receiver 의 onReceive() 를 호출해줍니다.

                          - 제거하는 방법은 removeStickyBroadcast() 를 사용합니다.

                          - sendStickyBroadcast 를 사용하려면 android.permission.BROADCAST_STICKY 라는

                             permission 이 필요합니다. 그렇지 않으면 SecurityException 이 발생합니다.

 

                     5.  LocalBroadcastManager 를 사용한 sendBroadcast(Intent intent)

                          - 발신자와 동일한 앱에 있는 수신자에 broadcast 를 전송합니다.

                          - 앱 간에 broadcast 를 전송할 필요가 없다면 LocalBroadcast 를 사용합니다.

                          - 구현이 훨씬 더 효율적이며(프로세스 간 통신이 필요 없다.) 다른 앱이 broadcast 를

                             수신하거나 전송할 수 있는 측면과 관련된 보안 문제에 관해 걱정할 필요가 없다.

                        

 

          <4> Content Provider

                1> 애플리케이션과 애플리케이션 저장소 사이에서 data 접근을 쉽게 하도록 관리해주는 class 입니다.

                2> 왜 Content Provider를 사용하는가?

                     1. 애플리케이션의 직접적인 코드 변경 없이 data 접근/변경할 수 있도록 해줍니다.

                     2. Loader나 CursorAdapter같은 class들도 사용하기 때문입니다.

                     3. 다른 사용자들이 애플리케이션에 접근, 사용, 수정할 권한을 줍니다.(안전하게)

                3> manifest에서 권한을 부여해주어야 합니다.

 

(2) Intent 사용방법은 크게 2가지입니다.

     1) 명시적 Intent

          <1> 명시적 Intent는 Intent를 충족하는 애플리케이션이 무엇인지 명시해주는 것입니다.

          <2> 보통 앱 안에서 구성요소를 시작할 때 사용하거나, 화면을 전환할 때 사용합니다.

          <3> 사용하고자 하는 Activity 또는 class의 이름을 알고 있어야 사용할 수 있습니다.

 

     2) 암시적 Intent

          <1> 특정 구성요소의 이름을 명시하지않고, 그 대신 수행할 일반적인 작업을 선언하여 다른 앱의

                 구성요소가 이를 처리할 수 있도록 해줍니다.

          <2> 암시적 Intent를 사용하면 Android시스템에서 적절한 구성요소를 찾는데, 이때 Intent의 내용을

                기기에 있는 다른 여러 앱의 Manifest 파일에서 선언된 Intent Filter와 비교해서 해당 Intent와 

                일치하는 Intent Filter가 있으면 시스템에서 해당 구성요소를 시작하고 이를 Intent객체에 

                전달하는 방법을 사용합니다.

          <3> 보통 다른 앱을 호출하거나, Uri를 띄우는 것들이 암시적 Intent라고 할 수 있습니다.

출처: 시아아빠(https://siadaddy-cordinglife.tistory.com/22)

          <4> 왜 암시적 Intent를 사용하는가?

               1> 예를 들어서 유저가 PDF 파일을 클릭하여 열기를 하면 PDF 파일을 열 수 있는 문서편집기가

                    필요한데, 이 문서편집기를 명시적 Intent를 사용하기 위해서 직접 만드는 것은 현실적으로

                    좋은 방법이 아닙니다. 그럴때 암시적 Intent를 사용해서 해당 안드로이드 폰에 PDF를

                    편집하거나 보여줄 수 있는 많은 애플리케이션들을 이용하면 좀더 효율적일 것입니다.

                    (즉, 이미 기존에 어떤 기능들을 지원하는 앱들이 있는 경우에 암시적 인텐트를 사용해서

                     그 애플리케이션들을 사용하면 되는 것입니다.)

               2> 그리고 만약 이 기능을 수행할 수 있는 애플리케이션들이 여러개 존재한다면, 어떤 

                    어플리케이션을 사용할지 선택할 수 있는 위젯을 안드로이드 시스템이 띄워줄 것입니다.

출처:&nbsp;https://limkydev.tistory.com/35

 

(3) Intent Filter 란?

     1) 안드로이드 어플리케이션을 만들 때 Manifest라는 파일이 있고, 파일 내용 중 Intent-filter라는 것이 있습니다.

     2) 암시적 Intent일 떄 컴포넌트가 자신의 속성에 부합하는 Intent인지 확인하는 작업을 하기 위해 존재합니다.

     3) Intent Filter는 엉뚱한 애플리케이션을 유저에게 보여주지않도록 걸러주는 역할을 합니다.

     4) Intent Filter내의 각 속성들

          <1> action Filter(액션 필터)

               1> Intent객체 내의 action을 검사하여 Intent-Filter에 정의된 action과 일치하는지 여부를 검사합니다.

               2> 이 검사를 통과하려면 Intent객체 내의 액션이 Intent-Filter에 정의된 action과 일치해야 합니다.

                    (Intent객체에 정의된 action == Intent-Filter에 정의된 action)

               3> 단, Intent action이 정의되어있지 않은 경우에는 action Filter를 통과할 수 있습니다.

 

          <2> category Filter(카테고리 필터)

               1> Intent객체 내의 category를 검사하여 Intent-Filter에 정의된 category와 일치하는지 여부를 검사합니다.

               2> action 검사에서는 아예 정의되어 있지 않은 경우 검사를 통과할 수 있었지만,

                    category에서는 Intent 객체에 정의된 category가 Intent-Filter에 정의된 category들과

                    일치해야만 검사를 통과할 수 있습니다.

                    (Intent객에체 정의된 category == Intent-Filter에 정의된 category)

 

          <3> data Filter(데이터 필터)

               1> Intent 객체 내의 data 항목 및 type을 검사하여 Intent-Filter에 정의된 값과 비교하여 일치하는지

                    여부를 검사합니다.

               2> 데이터 검사는 크게 data의 주소(URI)를 검사하는 부분과 data의 유형(type, MIME type)을

                    검사하는 부분으로 나누어집니다.

                    1. data 주소 검사

                         - 주소를 검사하는 부분은 data의 주소를 세분화하여 검사할 수 있도록 되어있습니다.

출처:&nbsp;https://siadaddy-cordinglife.tistory.com/23?category=839001

                    2. data 유형 검사

출처:&nbsp;https://siadaddy-cordinglife.tistory.com/23?category=839001

 

 

참고자료:

https://limkydev.tistory.com/44

 

https://siadaddy-cordinglife.tistory.com/23?category=839001

 

https://limkydev.tistory.com/35

 

https://siadaddy-cordinglife.tistory.com/22