API GUIDE/2. App Components
2014. 2. 28. 07:34


 


안드로이드 앱 독학으로 개발하기 - 일반적인 인텐트(Common Intents) (1)


지금까지 앞서 진행되어 왔던 글들을 보면 항상 "인텐트"를 연발해 왔습니다.


수도 없이 들어온 탓에 인텐트라는 것이 뭘 하는 건지는 대충 알겠는데 막상 사용법은 어떻게 되고 또 어떤 것들이 있는지는 확실히 알지 못했습니다.


이번 글은 그런 궁금증을 어느정도 해결해 주는 글이 아닐까합니다. 안드로이드 개발자 사이트에 있는 도움말이 개발자들을 참 세심하게 배려했다는 생각을 갖게 되는 글입니다.


물론 안드로이드 API에 존재하는 인텐트가 이 글에 나오는 것들이 전부는 아닙니다. 하지만 많이 사용되는 일부를 추려서 설명한 만큼 이 글을 독파하고 나면 다른 인텐트들도 어떻게 사용해야할 지 쉽게 접근할 수 있으리라 생각합니다.


이후 제 블로그에서도 지금의 번역글을 기반으로 하여 개발하는 과정을 다뤄볼까 생각중입니다.(물론, 지금은 실력이 안되서 곤란하지만 ^^;) 그 때까지 기초를 다진다고 생각하시고 읽어주시기 바랍니다.


그럼 공부 열심히 하시고 언제나 그렇듯 오역, 오타, 깨진 링크가 있으면 제보 부탁드립니다.


 

저작권 표시 : 

 

Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.

 

현재 보시는 페이지는 안드로이드 오픈 소스 프로젝트에 의해 작성되고 공유된 작업물의 수정/번역본이며 크리에이티브 커먼즈 저작자 표시 2.5 라이센스에 기술된 조건의 사용 근거를 따른 것입니다.

 

본 문서의 원본은 http://developer.android.com/guide/components/intents-common.html이며 안드로이드 4.4 Kitkat 기준으로 설명되었습니다.


일반적인 인텐트(Common Intents)


인텐트는 Intent오브젝트 안에 단순한 액션("지도를 본다." 또는 "사진을 찍는다."처럼)을 기술함으로써 다른 앱의 액티비티를 실행시킬 수 있다. 이런 종류의 인텐트는 실행시킬 컴포넌트를 지정하지 않기 때문에 암시적 인텐트라고 부른다. 하지만 수행할 액션과 함께 액션을 수행하는데 필요한 정보를 정해준다.


startActivity()startActivityForResult()를 호출할 때 암시적 인텐트를 넘겨주면 시스템은 인텐트를 다룰 수 있는 앱을 결정하고 해당하는 Activity를 실행시킨다. 만일 인텐트를 다룰 수 있는 앱이 여러 개 존재한다면 시스템은 사용자가 그 중에서 하나를 고를 수 있도록 다이얼로그를 띄운다.


이 글은 일반적인 액션으로 사용될 수 있는 몇몇 암시적 인텐트를 소개한다. 각 센션에서는 같은 액션을 수행할 수 있는 능력을 외부로 알리는 intent filter의 생성방법에 대해서도 함께 보여준다.


Caution : 만일 암시적 인텐트를 처리할 수 있는 앱이 단말에 설치되어 있지 않다면 startActivity() 메서드를 호출하는 순간 앱은 크래시되고 말 것이다. 먼저 인텐트를 처리할 수 있는 앱이 존재하는지를 확인하기 위하여 Intent 오브젝트를 사용해 resolveActivity() 메서드를 호출한다. 결과가 null이 아니면 인텐트를 처리할 수 있는 앱이 최소 하나는 존재한다는 뜻이며 startActivity()를 호출해도 안전하다. 반면에 결과가 null이면 해당 인텐트를 사용해서는 안되며 가능하다면 인텐트를 사용하게 되는 기능을 비활성화시키는 것이 좋다.


만약, 인텐트나 인텐트 필터를 생성하는 법을 잘 모른다면 인텐트와 인텐트 필터(Intents and Intent Filters)를 먼저 읽기 바란다.


카메라(Camera)



사진이나 동영상을 찍고 결과물 돌려받기
(Capture a picture or video and return it)

카메라 앱을 열고 사진이나 동영상 결과물을 돌려받기 위해서는 ACTION_IMAGE_CAPTUREACTION_VIDEO_CAPTURE액션을 사용한다. 또한 EXTRA_OUTPUT 부가정보 키에 카메라가 사진이나 동영상을 저장할 URI위치를 지정한다.


액션(Action)

ACTION_IMAGE_CAPTURE 또는 ACTION_VIDEO_CAPTURE


데이터 URI 스키마(Data URI Scheme)

필요없음


MIME Type

필요없음


부가정보(Extras)

EXTRA_OUTPUT

카메라 앱에서 사진이나 동영상 파일을 저장하기 위한 URI위치(Uri 오브젝트 사용)


카메라 앱이 정상종료되고 호출자의 액티비티로 포커스가 돌아오면(호출한 앱은 onActivityResult() 콜백을 받게 된다.) EXTRA_OUTPUT으로 지정한 URI위치에 있는 사진이나 동영상을 액세스할 수 있다.


Note : ACTION_IMAGE_CAPTURE를 사용해 사진을 촬영하며 카메라 앱은 결과 Intent내에 "data"라는 필드명으로 Bitmap형태의 썸네일을 제공하기도 한다.


인텐트 예제 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static final int REQUEST_IMAGE_CAPTURE = 1;
static final Uri mLocationForPhotos;

public void capturePhoto(String targetFilename) {
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT,
            Uri.withAppendedPath(mLocationForPhotos, targetFilename);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(intent, REQUEST_IMAGE_CAPTURE);
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
        Bitmap thumbnail = data.getParcelable("data");
        // Do other work with full size photo saved in mLocationForPhotos
        ...
    }
}


이 인텐트로 어떻게 촬영하고 저장위치를 위한 올바른 Uri를 생성하는 법에 대한 보다 자세한 설명은 Taking Photos SimplyTaking Videos Simply를 읽어보기 바란다.


인텐트 필터 예제 :

1
2
3
4
5
6
<activity ...>
    <intent-filter>
        <action android:name="android.media.action.IMAGE_CAPTURE" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>


연락처 앱(Contacts/People App)



연락처 선택하기(Select a contact)

사용자가 연락처를 선택하도록 하고 연락처의 정보를 완전히 액세스하려면 ACTION_PICK 액션을 사용하고 MIME 타입은 Contacts.CONTENT_TYPE을 사용해야 한다.


onActivityResult() 콜백함수로 돌려받은 Intent에는 선택된 연락처가 content:의 스키마(scheme)를 갖는 URI로 포함되어 있다. 앱이 READ_CONTACTS 권한을 갖고 있지 않더라도 반환된 결과는 Contacts Provider API를 통해 연락처의 내용을 읽을 수 있는 임시권한을 부여해준다.


Tip : 만일 전화번호나 이메일 주소와 같은 연락처 정보의 일부분만 액세스하려고 한다면 다음 섹션(연락처의 특정 데이터 선택하기; select specific contact data)을 참고 바란다.


액션(Action)

ACTION_PICK


데이터 URI 스키마(Data URI Scheme)

필요없음


MIME Type

Contacts.CONTENT_TYPE


인텐트 예제 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static final int REQUEST_SELECT_CONTACT = 1;

public void selectContact() {
    Intent intent = new Intent(Intent.ACTION_PICK);
    intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(intent, REQUEST_SELECT_CONTACT);
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_SELECT_CONTACT && resultCode == RESULT_OK) {
        Uri contactUri = data.getData();
        // Do something with the selected contact at contactUri
        ...
    }
}


연락처 URI의 상세 정보를 읽는 법은 Retrieving Details for a Contact를 참고하기 바란다. 다시한번 말하자면 위에서 설명한 인텐트로 획득한 연락처 URI의 상세정보를 읽을 때는 READ_CONTACTS 권한이 필요없다.


연락처의 특정 데이터 선택하기(Select specific contact data)

사용자가 연락처를 선택하도록 하고 선택된 연락처의 내용 중 전화번호, 이메일 주소등의 일부 정보를 획득하려면 액션은 ACTION_PICK를 사용하고 MIME 타입은 아래 목록에 표시된 컨텐트 타입 중 하나를 사용한다. 예를 들어, 연락처의 전화번호를 가져오고 싶으면 MIME 타입에 CommonDataKinds.Phone.CONTENT_TYPE을 사용하면 된다.


만일 연락처의 내용 중에서 한 가지 데이터만 필요하다면 ContactsContract.CommonDataKinds 클래스의 CONTENT_TYPE을 사용하는 것이 Contacts.CONTENT_TYPE(앞에서 설명 되었다.)을 사용하는 것보다 더 효과적인다. 왜냐하면 ContactsContract.CommonDataKinds 클래스의 CONTENT_TYPE을 사용하여 얻은 결과는 ContactsProvider에 복잡한 쿼리를 하지 않고도 원하는 정보에 직접 액세스 할 수 있기 때문이다.


onActivityResult() 콜백을 통해 전달되는 결과 Intent는 선택된 연락처 정보를 가리키는 content: URI를 포함하고 있다. 응답된 결과는 앱이 READ_CONTACTS 퍼미션을 갖고 있지 않아도 연락처 정보를 읽어낼 수 있는 임시 퍼미션을 부여해 준다.


액션(Action)

ACTION_PICK


데이터 URI 스키마(Data URI Scheme)

필요없음


MIME Type

CommonDataKinds.Phone.CONTENT_TYPE

연락처의 전화번호를 추출한다.

CommonDataKinds.Email.CONTENT_TYPE

연락처의 이메일 주소를 추출한다.

CommonDataKinds.StructuredPostal.CONTENT_TYPE

연락처의 우편번호를 추출한다.

ContactsContract에는 더 많은 CONTENT_TYPE이 있다.


인텐트 예제 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
static final int REQUEST_SELECT_PHONE_NUMBER = 1;

public void selectContact() {
    // Start an activity for the user to pick a phone number from contacts
    Intent intent = new Intent(Intent.ACTION_PICK);
    intent.setType(CommonDataKinds.Phone.CONTENT_TYPE);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(intent, REQUEST_SELECT_PHONE_NUMBER);
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_SELECT_PHONE_NUMBER && resultCode == RESULT_OK) {
        // Get the URI and query the content provider for the phone number
        Uri contactUri = data.getData();
        String[] projection = new String[]{CommonDataKinds.Phone.NUMBER};
        Cursor cursor = getContentResolver().query(contactUri, projection,
                nullnullnull);
        // If the cursor returned is valid, get the phone number
        if (cursor != null && cursor.moveToFirst()) {
            int numberIndex = cursor.getColumnIndex(CommonDataKinds.Phone.NUMBER);
            String number = cursor.getString(numberIndex);
            // Do something with the phone number
            ...
        }
    }
}


연락처 보기(View a contact)

저장된 연락처의 상세정보를 표시하려면 액션은 ACTION_VIEW를 사용하고 데이터에는 표시하려는 연락처를 content: URI 형태로 지정해 준다.


연락처 URI를 얻기 위해서는 주로 두 가지 방법을 사용한다.

  • 앞에서 설명했던 ACTION_PICK을 사용하여 얻어진 연락처 URI를 사용한다.(이 방법을 사용하기 위해서 필요한 퍼미션은 따로 없다.)
  • Retrieving a List of Contacts에 기술된 방법으로 모든 연락처의 목록에 직접 액세스한다.(이 방법을 사용하기 위해서는 READ_CONTACTS 퍼미션이 필요하다.)


액션(Action)

ACTION_VIEW


데이터 URI 스키마(Data URI Scheme)

content:<URI>


MIME Type

필요없음. 타입은 연락처 URI로 부터 유추가 가능한다.


인텐트 예제 :

1
2
3
4
5
6
public void viewContact(Uri contactUri) {
    Intent intent = new Intent(Intent.ACTION_VIEW, contactUri);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}


저장된 연락처 수정(Edit an existing contact)

저장된 연락처를 수정하려면 액션은 ACTION_EDIT, 데이터에는 content: URI의 형태로 연락처를 지정해 준다. 그리고 부가정보에 수정될 항목과 수정될 내용을 입력해 준다. 수정될 항목은 ContactsContract.Intents.Insert에 정의된 상수로써 정해줄 수 있다.


연락처 URI를 얻기 위해서는 주로 두 가지 방법을 사용한다.

  • 앞에서 설명했던 ACTION_PICK을 사용하여 얻어진 연락처 URI를 사용한다.(이 방법을 사용하기 위해서 필요한 퍼미션은 따로 없다.)
  • Retrieving a List of Contacts에 기술된 방법으로 모든 연락처의 목록에 직접 액세스한다.(이 방법을 사용하기 위해서는 READ_CONTACTS 퍼미션이 필요하다.)


액션(Action)

ACTION_EDIT


데이터 URI 스키마(Data URI Scheme)

content:<URI>


MIME Type

필요없음. 타입은 연락처 URI로 부터 유추가 가능한다.


부가정보(Extras; 선택사항)

ContactsContract.Intents.Insert에 정의된 항목을 하나 이상 추가할 수 있다.


인텐트 예제 :

1
2
3
4
5
6
7
8
public void editContact(Uri contactUri, String email) {
    Intent intent = new Intent(Intent.ACTION_EDIT);
    intent.setDataAndType(contactUri, Contacts.CONTENT_TYPE);
    intent.putExtra(Intents.Insert.EMAIL, email);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}

연락처를 수정하는 법에 대한 정보는 Modifying Contacts Using Intents에 더 많이 있다.


연락처 추가(Insert a contact)

새로운 연락처를 추가하려면 ACTION_INSERT 액션을 사용하고 MIME 타입은 Contacts.CONTENT_TYPE을 지정한다. 그리고 부가정보에 수정될 항목과 수정될 내용을 입력해 준다. 수정될 항목은 ContactsContract.Intents.Insert에 정의된 상수로써 정해줄 수 있다.


액션(Action)

ACTION_INSERT


데이터 URI 스키마(Data URI Scheme)

필요없음.


MIME Type

Contacts.CONTENT_TYPE


부가정보(Extras; 선택사항)

ContactsContract.Intents.Insert에 정의된 항목을 하나 이상 추가할 수 있다.


인텐트 예제 :

1
2
3
4
5
6
7
8
9
public void insertContact(String name, String email) {
    Intent intent = new Intent(Intent.ACTION_INSERT);
    intent.setType(Contacts.CONTENT_TYPE);
    intent.putExtra(Intents.Insert.NAME, name);
    intent.putExtra(Intents.Insert.EMAIL, email);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}

연락처를 추가하는 법에 대한 더 많은 정보는 Modifying Contacts Using Intents를 참고하기 바란다.


이메일(Email)



이메일 쓰기(Compose an email with optional attachments)

이메일을 사용하기 위해서는 첨부가 있는지 여부에 따라 아래의 액션 중 하나를 사용하고 아래의 목록에 있는 부가정보 키에 맞춰 수신인이나 제목과 같은 세부사항을 이메일에 포함시킬 수 있다.


액션(Action)

ACTION_SENDTO (첨부가 없을 때) 또는

ACTION_SEND (하나만 첨부할 때) 또는

ACTION_SEND_MULTIPLE (여러 개를 첨부할 때)


데이터 URI 스키마(Data URI Scheme)

필요없음.


MIME Type

PLAIN_TEXT_TYPE("text/plain")

"*/*"


부가정보(Extras; 선택사항)

Intent.EXTRA_EMAIL

모든 수신인 이메일 주소의 문자열 배열

Intent.EXTRA_CC

모든 참조자 이메일 주소의 문자열 배열

Intent.EXTRA_BCC

모든 숨김 참조자 이메일 주소의 문자열 배열

Intent.EXTRA_SUBJECT

이메일 제목을 나타내는 문자열

Intent.EXTRA_TEXT

이메일의 본문을 나타내는 문자열

Intent.EXTRA_STREAM

첨부한 파일을 가리키는 Uri. 만일 ACTION_SEND_MULTIPLE 액션을 사용하였다면 Uri 오브젝트를 포함하는 ArrayList.


인텐트 예제 :

1
2
3
4
5
6
7
8
9
10
public void composeEmail(String[] addresses, String subject, Uri attachment) {
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setType("*/*");
    intent.putExtra(Intent.EXTRA_EMAIL, addresses);
    intent.putExtra(Intent.EXTRA_SUBJECT, subject);
    intent.putExtra(Intent.EXTRA_STREAM, attachment);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}


문자 메세지, SNS 앱이 아닌 반드시 이메일로 인텐트를 처리하고 싶다면 ACTION_SENDTO 액션을 사용하고 데이터 스키마는 "mailto:"로 지정해 준다. 아래는 그 예제다.



1
2
3
4
5
6
7
8
9
public void composeEmail(String[] addresses, String subject) {
    Intent intent = new Intent(Intent.ACTION_SENDTO);
    intent.setData(Uri.parse("mailto:")); // only email apps should handle this
    intent.putExtra(Intent.EXTRA_EMAIL, addresses);
    intent.putExtra(Intent.EXTRA_SUBJECT, subject);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}



인텐트 필터 예제 :

1
2
3
4
5
6
7
8
9
10
11
12
<activity ...>
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <data android:type="*/*" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SENDTO" />
        <data android:scheme="mailto" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>




다음 글에서 이 글(일반적인 인텐트)의 내용을 계속 이어갑니다.


긴 글들은 타이핑하는 것도 꽤 큰 일이지만 보는 사람도 지겨워질 수 있을 것 같아 한 번 쉬어갑니다.


다음 글 >> 일반적인 인텐트(Common Intents) (2)

이전 글 >> 인텐트와 인텐트 필터(Intents and Intent Filters) (2)


posted by 리치크루