[안드로이드] 인텐트 필터 (Intent Filter)
- 프로그래밍 정보
- 2010. 10. 19.
반응형
읽기전에 손가락 한번 클릭~ >_<
고마워요 ~ Chu ~ ♥
인텐트 필터
액티비티, 서비스, 브로드캐스트 리시버는 시스템에게, 처리할 암시적 인텐트들을 알려주기 위해 하나 이상의 인텐트 필터를 가집니다.
각각의 필터는 컴포넌트의 처리능력, 즉 컴포넌트가 수신하는 인텐트의 집합을 정의합니다. 필터는 말 그대로 관계없는 인텐트를 제외하여, 필요한 타입의 인텐트만을 걸러내는 기능을 하지요
여기에서 제외하는 것은 단지 대상 클래스의 이름이 없는 암시적 인텐트 일뿐이고, 명시적 인텐트는 필터에 상관없이 항상 대상에게 전달됩니다. 이때 필터는 고려되지 않는다는 점을 주의하세요
그러나 암시적 인텐트는 컴포넌트 필터 중에서 한개를 통과할 수 있다면, 해당 컴포넌트에게 전달되어 집니다. 컴포넌트는 각 작업별로 사용자에게 보여줄 여러개의 필터를 가질 수 있습니다.
예를들어, A 라는 어플리케이션의 액티비티에 두개의 a,b 라는 필터가 있다고 가정해 봅니다. 이때 사용자가 서로 다른 a,b 를 볼 수 있겠죠.
중요한 점은 인텐트 필터는 IntentFilter 클래스의 인스턴스라는 점입니다. 시스템은 해당 컴포넌트를 실행하기 전에 컴포넌트 기능에 대해 알아야 하기 때문에, 인텐트필터는 일반적으로 Java 소스코드가 아닌 어플리케이션의 매니페스트 파일의
<intent-filter> 속성으로 정의하게 됩니다.
보안적인 필터
인텐트 필터는 그 특성상 보안에 의존적일 수가 없습니다. 이유는 암시적 인텐트는 차단할 수 있지만, 명시적 인텐트는 차단할 수가 없기 때문입니다.
필터는 인텐트 객체의 액션과 데이터, 카테고리를 나열하는 필드들을 가집니다. 암시적 인텐트는 세 개의 영역의 필터들에 대해 찾아지게 되죠. 그 필터를 소유하고 있는 컴포넌트에게 인텐트가 전달되게 하기 위해서는 세 개의 모든 테스트가 통과되어야만 합니다. 이때 만약 하나라도 실패하면, 시스템은 컴포넌트에 인텐트를 전달하지 않습니다.
그러나 앞서 말했듯이 여러개의 인텐트 필터를 가질수 있기 때문에, 필터들 중 하나를 통과하지 못했던 인텐트라도 다른 필터를 통과할 가능성은 있습니다.
액션 테스트
매니페스트의 <intent-filter> 엘리먼트는 <action> 서브엘리먼트로 액션들을 리스트 합니다. ( 매니페스트의 엘리먼트에 대한 자세한 사항은 나중에 매니페스트 포스팅에서 따로 다룰 예정입니다 )
인텐트 객체는 하나의 액션을 지정하지만, 필터는 하나 이상의 액션을 지정할 수 있다는 의미입니다. 필터는 적어도 하나의 <action> 엘리먼트를 가져야하며, 비어있어서는 절대 안됩니다. 그렇지않으면 모든 인텐트가 차단되겠죠.
인텐트 객체의 액션은 필터의 액션들 중 하나와 일치해야됩니다. 즉, 필터가 액션을 지정하지 않았다면, 인텐트 객체의 액션과 일치하는 것이 없게 되면서 모든 테스트를 통과할 수 없게 되어버리고, 결국에는 인텐트를 얻을 수 없게 되죠
카테고리 테스트
<intent-filter> 엘리먼트는 서브 엘리먼트로 카테고리들을 리스트합니다.
액션과 카테고리의 상수는 전체 문자열 값으로 사용되어 집니다.
즉, android.intent.category.BROWSABLE 은 CATEGORY_BROWSABLE 상수에 대응됩니다.
액션도 마찬가지로 android.intent.action.EDIT 은 ACTION_EDIT 에 대응되죠.
인텐트가 카테고리 테스트를 통과하기 위해서는 인텐트 객체안의 모든 카테고리가 필터의 카테고리와 일치해야합니다.
원칙적으로 본다면 카테고리를 가지지 않은 인텐트 객체는 필터에 관계없이 항상 이 테스트를 통과하게 됩니다.
여기에 딱 한가지 예외가 있습니다
그것은 startActivity() 에 전달되는 암시적 인텐트가 "android.intent.category.DEFAULT" 카테고리를 포함하고 있다고 취급되는 것입니다. 그러므로 암시적 인텐트를 수신하려는 액티비티는 인텐트필터에서 "android.intent.category.DEFAULT" 를 포함해야 되겠습니다.
단, MAIN 액션과 런처 카테고리 (“android.intent.action.MAIN”과 “android.intent.category.LAUNCHER” ) 가 설정된 필터만 예외로 취급됩니다. 이 필터는 신규 태스크에 액티비티를 시작시키고 런처 스크린체 표시하기 때문에 디폴트 카테고리가 필요없다는 이유에서 입니다.
단, MAIN 액션과 런처 카테고리 (“android.intent.action.MAIN”과 “android.intent.category.LAUNCHER” ) 가 설정된 필터만 예외로 취급됩니다. 이 필터는 신규 태스크에 액티비티를 시작시키고 런처 스크린체 표시하기 때문에 디폴트 카테고리가 필요없다는 이유에서 입니다.
데이터 테스트
데이터도 인텐트 필터의 서브 엘리먼트에 포함됩니다. 또한 하나 이상이 될 수도 있고 아예 없을 수도 있습니다.
<data> 엘리먼트는 URI 와 MIME 타입을 지정할 수 있습니다. URI 영역에는 별도의 속성인 스키마와 호스트, 포트, path 가 있죠. "scheme://host:port/path" 형식입니다.
예를 들자면 아래와 같이 구성됩니다.
content://com.project.exam:200/folder/subfolder/etc
호스트와 포트는 URI 를 함께 구성하는데, 만약 호스트가 지정되지 않으면 포트도 무시됩니다. 각 속성들은 선택사항이지만 독립적이지 못한 구조를 띄고 있습니다. 따라서 조금 골치가 아프곤 하죠..;;;
무슨 말인고 하니, 호스트와 포트는 스키마를 필요로하며, path 는 스키마, 호스트,포트를 필요로 합니다. 인텐트 객체에 있는 URI가 필터에 있는 URI와 비교될 때, 실제 필터의 URI 부분들에 대해서만 비교가 됩니다. 이런 사항이라면 예를들어 필터가 스키마만을 정의했다면, 해당 스키마를 가진 모든 URI는 필터와 일치하게 되겠네요.
또 필터가 스키마, 호스트:포트, path를 정의하면, 같은것을 가지는 URI가 일치합니다. 필터에서 path는 와일드 카드문자(*) 를 쓸 수 있다는 것도 이러한 이유에서 일 것입니다.
<data> 엘리먼트의 type 속성은 MIME 타입을 지정하죠. 인텐트 객체와 필터는 하위타입 필드에도 '*' 를 쓸 수 있습니다. 즉, 'text/*' 처럼요...
데이터 테스트는 인텐트 객체의 URI 와 MIME 타입을 .. 필터의 URI와 MIME타입을 비교합니다.
이때 비교 규칙은 아래와 같습니다.
1. URI 와 MIME 타입 모두 갖지 않은 인텐트 객체는 , 필터가 어떠한 URI와 MIME 타입을 지정하지 않은 경우에 테스트를 통과합니다.
2. MIME 없이 URI만 가진 인텐트 객체는, 필터의 URI 와 일치하고 필터가 MIME 이 없을 때만 통과합니다. 실제 데이터를 참조하지 않는 mailto: 와 tel: 같은 URI가 이에 해당합니다.
3. MIME 타입을 가지고 있지만 URI 는 없는 인텐트 객체는, 필터도 URI가 없고, 동일한 MIME 을 가진 경우에 통과합니다.
4. URI 와 MIME 이 모두를 가지거나, MIME 이 없더라도 그것이 URI로부터 예상될 수 있는 경우의 인텐트 객체는 type 이 필터의 type과 일치할때, MIME 영역에 대한 테스트를 통과합니다. 그리고 인텐트의 URI 가 필터의 URI 와 일치하거나 content: 또는 file: 형식의 URI 이고 필터가 URI가 없을때에 URI 영역에 대한 테스트를 통과합니다. 즉, 필터가 단 하나의 MIME 만을 갖고 있다면 컴포넌트는 content: 와 file: 을 지원하는 것으로 처리된다는 의미입니다.
2. MIME 없이 URI만 가진 인텐트 객체는, 필터의 URI 와 일치하고 필터가 MIME 이 없을 때만 통과합니다. 실제 데이터를 참조하지 않는 mailto: 와 tel: 같은 URI가 이에 해당합니다.
3. MIME 타입을 가지고 있지만 URI 는 없는 인텐트 객체는, 필터도 URI가 없고, 동일한 MIME 을 가진 경우에 통과합니다.
4. URI 와 MIME 이 모두를 가지거나, MIME 이 없더라도 그것이 URI로부터 예상될 수 있는 경우의 인텐트 객체는 type 이 필터의 type과 일치할때, MIME 영역에 대한 테스트를 통과합니다. 그리고 인텐트의 URI 가 필터의 URI 와 일치하거나 content: 또는 file: 형식의 URI 이고 필터가 URI가 없을때에 URI 영역에 대한 테스트를 통과합니다. 즉, 필터가 단 하나의 MIME 만을 갖고 있다면 컴포넌트는 content: 와 file: 을 지원하는 것으로 처리된다는 의미입니다.
만약, 인텐트가 하나 이상의 액티비티 또는 서비스의 필터를 통과할 수 있다면 컴포넌트 선택을 위해 사용자에게 질의를 할 것입니다. 대상이 찾아지지 않으면 예외를 발생시키겠죠.
일반적인 경우
위의 데이터 테스트의 4번을 보시면 컴포넌트들이 파일 또는 CP로부터 로컬 데이터를 사용할 수 있다는 의미를 내포하고 있습니다. 그러므로 그 컴포넌트의 필터는 MIME 타입만을 리스트 하기 때문에 명시적인 content: 와 file: 스키마를 따로 필요로 하지 않는다는 뜻이 됩니다. 이것이 일반적인 경우입니다.
예를들어 <data android:type="image/*"> 라는 엘리먼트는 컴포넌트가 CP로부터 이미지를 얻고 사용할 수 있다는 것을 지정하는 것이죠.
대부분의 데이터는 CP로부터 분배되며, 따라서 URI 외의 MIME 타입을 지정하는 필터가 일반적인 경우입니다.
또 다른 일반적인 경우는 스키마와 MIME 을 같이 지정한 필터가 있습니다.
<data android:scheme=”http” android:type=”video/*” />
이 <data> 엘리먼트는 컴포넌트가 http로부터 video 타입 데이터를 얻고 사용할 수 있다고 지정하는 것입니다. 예를들어 브라우저에서 어느 링크를 따라갈 때를 생각해 보세요. 이때 먼저 브라우저는 HTML 과 같은 데이터를 표시할 것입니다. 만약 표시할 수 없다면 암시적 인텐트에 스키마와 MIME을 넣은 다음에, 이 작업을 처리할 액티비티를 시작시킬 것입니다. 또 그 인텐트를 받을 액티비티가 없다면 데이터를 다운로드 하게 될 것입니다. 이것은 CP가 제어하기 때문에 MIME만을 지정한 필터를 가진 액티비티들의 집합인 pool 이라는 곳에서 응답하게 할 수도 있습니다.
대부분의 어플리케이션은 특정 데이터 참조 없이 시작할 수 있는데요, 어플리케이션을 초기화하는 액티비티는 액션으로 "android.intent.action.MAIN" 이 지정된 필터를 갖고 있습니다. 또 그것이 어플리케이션 런처에서 보여지게 하려면 "android.intent.category.LAUNCHER" 카테고리를 지정합니다.
끝~~
관련글
[안드로이드] 인텐트 필터 (Intent Filter)
[안드로이드] 인텐트 객체
[안드로이드] 인텐트
[안드로이드] 컴포넌트 활성화 - 인텐트(Intent)
[안드로이드] 컴포넌트 종료하기
[안드로이드] 인텐트 필터
[안드로이드] 메뉴 아이템 인텐트
[안드로이드] 인텐트 객체
[안드로이드] 인텐트
[안드로이드] 컴포넌트 활성화 - 인텐트(Intent)
[안드로이드] 컴포넌트 종료하기
[안드로이드] 인텐트 필터
[안드로이드] 메뉴 아이템 인텐트
반응형