본문 바로가기

어플리케이션 구성/인텐트(Intent)

인텐트는 어플리케이션을 변하게 한다 : 확장 컴포넌트

요즘 나오는 휴대폰들은 거의 대부분 카메라가 장착되어 있습니다. 그래서 사진도 찍을 수 있고, 찍은 사진을 앨범에서 보기도 하고 관리도 할 수 있죠. 근데, 사진을 보기만 하는 것에 싫증을 느껴 뭐 재미있는 것이 없을까? 하던 중 사진을 동영상으로 만들어주는 어플리케이션(이하 동영상 변환 어플리케이션)을 발견하여 설치하였습니다.

사진을 동영상으로 바꿔주는 어플리케이션을 설치하였으므로, 이제 자신이 원하는 사진을 동영상으로 만들 수 있게 되었습니다. 하지만, 평상시 패턴을 보면 자신이 원하는 사진을 동영상으로 만드는 과정은 다소 복잡한 절차를 거치게 됩니다.


1. 사진 앨범에서 찍은 사진들을 봅니다. 찍은 사진들을 보다가 동영상으로 만들고 싶은 사진을 발견합니다.
2. 선택한 사진을 기억해놓고, 앨범을 종료한 후 동영상 변환 어플리케이션을 구동합니다.
3. 동영상 변환 어플리케이션에서 사진 앨범을 찾아보면서 아까 선택했던 사진을 선택합니다.
4. 선택한 사진을 동영상으로 만듭니다.


위와 같이, 사진을 보다가 사진들을 동영상으로 만들고 싶어도 앨범 어플리케이션과 동영상 변환 어플리케이션은 서로 다른 어플리케이션이므로 앨범 어플리케이션을 종료한 후 동영상 변환 어플리케이션을 실행해야 합니다. 이는 앨범 어플리케이션에서 바로 동영상 변환 어플리케이션을 호출하는 메뉴가 없기에 발생하는 문제들이죠.


하지만, 안드로이드에서는 이런 걱정을 할 필요가 없습니다. 기존에 설치된 어플리케이션에서 확장 컴포넌트를 지원한다면, 나중에 사용 가능한 확장 컴포넌트가 설치되었을 때 기존의 어플리케이션에서 새로 설치한 어플리케이션을 이용할 수 있도록 하는 메뉴가 추가되도록 할 수 있습니다.

이렇게 각각의 어플리케이션이 서로에게 영향을 주는 것은 모바일에서는 생소할지 몰라도, 사실 PC 환경에서는 꽤 익숙한 모습입니다. 웹 브라우저인 인터넷 익스플로러에서도 이러한 모습을 확인할 수 있습니다.



위 화면은 인터넷 익스폴로러의 옵션 창입니다. 프로그램 탭을 보면 각각의 작업에 대해 사용할 프로그램을 선택하는 항목이 있습니다. HTML 편집기의 경우 위의 화면에서는 MS워드, 엑셀, 메모장(Notepad)가 표시되고 있는데, 만약 드림위버나 프론트페이지같이 HTML을 편집할 수 있는 프로그램이 설치되면 이 목록에 각 프로그램이 표시될 것입니다.

이와 마찬가지로, 안드로이드에서도 특정 데이터 혹은 처리할 작업에 대해 현재 어플리케이션의 컴포넌트 외에 동일한 데이터 혹은 동일한 작업을 처리할 수 있는 컴포넌트가 추후에 설치된다면 그 컴포넌트를 통해 작업을 할 수 있도록 새로 설치한 컴포넌트로 연결되는 메뉴를 추가해주도록 해줄 수 있습니다.

이렇게, 특정 컴포넌트에서 어떠한 데이터 및 작업에 대한 대안 컴포넌트, 즉 "나도 그 작업 할 수 있다" 혹은 "나도 그 데이터를 처리할 수 있다" 라고 선언하고 싶다면, 인텐트 필터에 다음의 두 카테고리를 추가해주면 됩니다.

CATEGORY_ALTERNATIVE (android.intent.category.ALTERNATIVE)
CATEGORY_SELECTED_ALTERNATIVE (android.intent.category.SELECTED_ALTERNATIVE)

CATEGORY_ALTERNATIVE와 CATEGORY_SELECTED_ALTERNATIVE는 둘 다 특정 데이터 및 작업을 처리할 수 있는 또다른 컴포넌트로 선언한다는 점에서 그 성격이 비슷하지만, 각 카테고리마다 인텐트를 통해 컴포넌트가 호출되는 시점이 다소 차이가 있습니다.

CATEGORY_ALTERNATIVE는 사용자가 어떠한 데이터를 보고 있을 때, (예:사진을 보고 있을 때) 현재 작업 혹은 데이터를 처리하는 (예:사진 데이터를 처리) 컴포넌트 외에 동일한 작업을 처리할 수 있는 다른 컴포넌트를 찾을 때 사용합니다.
반면, CATEGORY_SELECTED_ALTERNATIVE는 데이터를 보고 있는 상황이 아닌, 데이터 목록(List)에서 특정 데이터를 선택 (하이라이트 된 상태)한 상태에서 해당 데이터를 처리할 수 있는 다른 컴포넌트를 찾을 때 사용합니다. 

만약, 앨범 컴포넌트에서 처리하는 데이터의 mimeType이 image/jpeg이고 이 컴포넌트에서는 확장 컴포넌트를 지원하며, 새로 설치한 컴포넌트 또한 이 데이터를 사용하는 것을 지원하고 확장 컴포넌트가 될 수 있도록 인텐트 필터가 설정되어있다면,  각각의 상태에서 호출되는 인텐트 객체가 가지는 카테고리는 다음과 같습니다.



위와 같은 상황에 따라 대안 컴포넌트로 표시되도록 하려면, 인텐트 필터에 그 내용을 정의해야 합니다. 위의 확장 컴포넌트의 인텐트 필터는 아래와 비슷한 모습을 하고 있을 겁니다.

 

                
                
                
                
                
 

위의 인텐트 필터를 보면 일반적인 인텐트 필터에서는 볼 수 없었던 "label" 속성이 정의되어 있는 것을 볼 수 있습니다. 이는 다른 액티비티에서 확장 컴포넌트를 찾아 그와 연결되는 메뉴를 표시할 때, 메뉴 항목의 이름으로 사용하게 됩니다.

데이터의 Type으로는 JPEG 이미지, 즉 image/jpeg를 설정해주었고, 확장 컴포넌트로 표시될 수 있도록 CATEGORY_ALTERNATIVE와 CATEGORY_SELECTED_ALTERNATIVE를 모두 받을 수 있도록 두 카테고리가 모두 정의되어있습니다. 그리고, 암시적 인텐트를 받기 위해 CATEGORY_DEFAULT가 정의되어있습니다.

이렇게 해서, 확장 컴포넌트가 될 수 있는 컴포넌트의 인텐트 필터 설정은 끝났고, 이제 확장 컴포넌트를 사용할 컴포넌트만 확장 컴포넌트를 사용할 수 있도록 설정해주기만 하면 됩니다. 확장 컴포넌트의 지원은 액티비티의 메뉴를 이용하게 되며, 사용할 수 있는 컴포넌트가 설치되었을 때 메뉴에 그 컴포넌트를 사용할 수 있는 메뉴를 추가해주도록 구현합니다.

확장 컴포넌트와 연결되는 메뉴 항목의 추가는 addIntentOptions() 메소드를 사용하며, 이는 onCreateOptionsMenu() 혹은 onPrepareOptionsMenu()에 구현하면 됩니다.

만약, 위의 예제에서 만든 컴포넌트를 확장 컴포넌트로 사용할 수 있는 컴포넌트를 만드려면 아래와 같이 코드를 구현하면 됩니다.

@Override
           public boolean onCreateOptionsMenu(Menu menu){
           super.onCreateOptionsMenu(menu);
            Intent intent = new Intent();
            intent.setType("image/jpeg"); // 데이터의 mimeType 설정
            intent.addCategory(Intent.CATEGORY_ALTERNATIVE); // 카테고리 설정
            
            int menuGroup = 0;
            int menuItemId = 0;
            int menuItemOrder = Menu.NONE;
            
            // 다른 컴포넌트를 호출하고 있는 액티비티
            ComponentName caller = getComponentName();
            
            // 대안 컴포넌트가 여러 개 있을 경우,
            // 대안 액티비티 호출 메뉴의 가장 처음에 추가되어야 할 컴포넌트의 속성
            Intent[] specificIntents = null; // 예제에서는 사용하지 않음
            // 가장 처음에 추가되어야 할 컴포넌트들에
            // 연결되는 MenuItem은 아래에 추가됨
            MenuItem[] outputspecificItems = null;
            
            // 기타 flags
            int flags = 0;
            
            // 확장 컴포넌트를 표시하는 메뉴 추가
            menu.addIntentOptions(menuGroup, menuItemId, 
            		menuItemOrder, caller, specificIntents, 
            		intent, flags, outputspecificItems);
            
            return true;


예제 어플리케이션을 통해 한번 어떤 식으로 메뉴가 추가되는지 알아보도록 합시다.
확장 컴포넌트를 지원하는 어플리케이션으로는 NotePad 어플리케이션을 그대로 사용하고, 우리는 NotePad 어플리케이션에서 확장 컴포넌트로 표시되는 확장 컴포넌트를 작성해보도록 하겠습니다.

AlternativeActivity 프로젝트를 작성한 후, 메니페스트 파일을 열어 AlternativeActivity의 인텐트 필터를 하나 더 추가해준 후, 아래와 같이 카테고리 및 데이터, 액션을 추가합니다. 그 후, Label에 적절한 이름을 적어줍니다.




우리가 만드는 확장 컴포넌트는 NotePad 어플리케이션에서 확장 컴포넌트로 사용되게끔 해야 합니다. 따라서, 데이터의 mimeType에는 NotePad 어플리케이션에서 사용하는 데이터 타입을 적어줍니다. (vnd,android.cursor.item/vnd.google.note)

우리가 만든 어플리케이션을 실행시키기 전에, NotePad 어플리케이션을 먼저 실행해 봅니다. NotePad 어플리케이션을 실행한 후 새로운 메모를 하나 만듭니다. 그 후에 방향키를 눌러 메모가 선택되도록 한 후 메뉴 버튼을 눌러줍니다.



아직까지는 메뉴에 별다른 것이 표시되지 않습니다. 새로 추가된 2개의 메뉴들은 NotePad 어플리케이션 내에서 정의된 확장 컴포넌트들입니다. 이젠 우리가 만든 어플리케이션을 설치한 후, 다시 동일한 동작을 수행해보도록 합시다.



우리가 만든 컴포넌트를 확장 컴포넌트로 인식하여 메뉴에 추가된 모습을 볼 수 있습니다. 이 메뉴를 클릭하면 우리가 만든 확장 컴포넌트가 실행되게 됩니다.

여기까지 인텐트를 이용하여 확장 컴포넌트를 사용하는 것에 대해 알아보았습니다. 이 정도까지 왔다면 인텐트에 대해서는 어느정도 기본이 되어있다고  할 수 있을 것입니다. :) 인텐트는 안드로이드 전반에서 매우 자주 사용되므로 꼭 개념을 숙지해야 하므로, 여기에서 다룬 것 외에 다른 것들도 보고 공부하신다면 많은 도움이 될 것입니다.

AlternativeActivity의 소스 코드를 첨부합니다.