태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

암시적 인텐트(Implicit Intent)를 사용해보자!

2009.10.30 23:42

강좌 작성환경
SDK Version : Android SDK 2.0, release 1
ADT Version : 0.9.4

추후 SDK업데이트로 인해 글의 내용과 실제 내용간 차이가 있을 수 있습니다.


이번 강좌에서는 예제를 통해 여러 암시적 인텐트를 사용하는 방법에 대해 알아보도록 하겠습니다. 이번 예제에서 사용해볼 암시적 인텐트들은 다음과 같습니다.

  • 전화번호 입력(Dial)
  • 전화 걸기 (Call)
  • 오디오 파일 불러오기
  • 전화번호부 데이터 불러오기

예제 어플리케이션은 각 버튼를 누르면 해당 인텐트를 실행하도록 되어있으며, 예제에서 사용된 코드는 다음과 같습니다.

[IntentTester.java]

package com.androidhuman.IntentTester;

package com.androidhuman.IntentTester;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class IntentTester extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        Button callButton = (Button)findViewById(R.id.callbutton);
        Button dialButton = (Button)findViewById(R.id.dialButton);
        Button getAudioButtonWithChooser = (Button)findViewById(R.id.getAudioButtonWithChooser);
        Button getAudioButton = (Button)findViewById(R.id.getAudioButton);
        Button getContactsButton = (Button)findViewById(R.id.getContactsButton);
        
        callButton.setOnClickListener(new OnClickListener(){

			public void onClick(View v) {
				Intent i = new Intent(Intent.ACTION_CALL);
				i.setData(Uri.parse("tel:0101234567"));
				startActivity(i);
			}
        	
        });
        
        dialButton.setOnClickListener(new OnClickListener(){

			public void onClick(View v) {
				Intent i = new Intent(Intent.ACTION_DIAL);
				i.setData(Uri.parse("tel:0101234567"));
				startActivity(i);
			}
        	
        });
        
        getAudioButton.setOnClickListener(new OnClickListener(){

			public void onClick(View v) {
				Intent i = new Intent(Intent.ACTION_GET_CONTENT);
				i.setType("audio/*");
				startActivityForResult(i, 0);
			}
        	
        });
                
       getAudioButtonWithChooser.setOnClickListener(new OnClickListener(){

 			public void onClick(View v) {
 				Intent i = new Intent(Intent.ACTION_GET_CONTENT);
 				i.setType("audio/*");
        		startActivityForResult(Intent.createChooser(i, "Select Audio Source..."), 0);
        		}
                	
            });         
        
        
        getContactsButton.setOnClickListener(new OnClickListener(){

			public void onClick(View v) {
				Intent i = new Intent(Intent.ACTION_PICK);
				i.setData(Uri.parse("content://contacts/phones"));
				startActivityForResult(i,0);
			}
        	
        });
    }
    
    protected void onActivityResult(int requestCode, int resultCode, Intent data){
    	super.onActivityResult(requestCode, resultCode, data);
    	if(resultCode == RESULT_OK){
    		Log.i("IntentTester", data.getData().toString());
    	}
    }
}

[main.xml]

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >

<Button android:layout_height="wrap_content" 
	android:id="@+id/callbutton" 
	android:layout_width="fill_parent" 
	android:text="action : ACTION_CALL / data : tel:0101234567"></Button>

<Button android:layout_height="wrap_content" 
	android:layout_width="fill_parent" 
	android:id="@+id/dialButton" 
	android:text="action : ACTION_DIAL / data : tel:0101234567"></Button>

<Button android:layout_height="wrap_content" 
	android:layout_width="fill_parent" 
	android:id="@+id/getAudioButton" 
	android:text="action : ACTION_GET_CONTENT / type : audio/*"></Button>

<Button android:layout_height="wrap_content" 
	android:layout_width="fill_parent" 
	android:text="action : ACTION_GET_CONTENT / type : audio/* / with Chooser" 
        anddroid:id="@+id/getAudioButtonWithChooser"></Button>

<Button android:layout_height="wrap_content" 
	android:layout_width="fill_parent" 
	android:id="@+id/getContactsButton" 
	android:text="action : ACTION_PICK / data : content://contacts/phones"></Button>
</LinearLayout>

IntentTester 액티비티는 데이터를 받아오는 인텐트를 사용했을 때 데이터를 받아오는 것을 확인하기 위해 onActivityResult() 메소드에서 받은 데이터를 LogCat을통해 표시해주도록 하고 있습니다.



또한, 예제에서 전화번호 입력, 전화 걸기 및 주소록에서 데이터베이스를 읽어야 하므로 이에 따른 권한이 필요합니다. 메니페스트 파일에 해당 권한을 추가해주도록 합시다.



우선, 전화번호를 입력(Dial)하는 인텐트와 전화를 거는 인텐트부터 살펴보겠습니다. 

callButton.setOnClickListener(new OnClickListener(){

			public void onClick(View v) {
				Intent i = new Intent(Intent.ACTION_CALL); // 전화를 거는 액션
				i.setData(Uri.parse("tel:0101234567")); // 전화번호를 인텐트에 넣어줍니다.
				startActivity(i); // 해당 인텐트를 처리하는 액티비티 (Dialer) 실행
			}
        	
        });
        
        dialButton.setOnClickListener(new OnClickListener(){

			public void onClick(View v) {
				Intent i = new Intent(Intent.ACTION_DIAL); // 전화번호를 입력하는 액션
				i.setData(Uri.parse("tel:0101234567")); // 전화번호를 인텐트에 추가합니다.
				startActivity(i); // 해당 인텐트를 처리하는 액티비티 (Dialer) 실행
			}
        	
        });


전화를 거는 동작은 액션으로 ACTION_CALL을 가지고, 전화번호를 입력하는 동작은 액션으로 ACTION_DIAL을 가지며, 두 액션 모두 데이터(Data)로 전화를 걸거나 입력할 번호를 필요로 합니다. 보통, 데이터에는 실제 데이터가 아닌 데이터의 주소(URI; Uniform Resource Identifier)가 들어가는데, Dialer, 웹 브라우저, 구글맵 어플리케이션 등에서는 위의 데이터처럼 실제 값을 받게 됩니다. 이와 같이 데이터에 실제 값을 넣는 경우는 Intents List : Invoking Google Applications on Android Devices 를 참고하세요.

이렇게 인텐트에 액션과 데이터를 설정한 후 인텐트를 실행시키면 다음과 같은 화면이 표시됩니다.



ACTION_CALL은 바로 왼쪽 화면처럼 바로 전화가 걸리게 되며, ACTION_DIAL은 오른쪽 화면에서 보는 것처럼, Dialer 액티비티가 호출된 후, 전화번호 입력 창에 우리가 데이터로 넘겨준 전화번호가 입력되어있는 것을 볼 수 있습니다.

다음으로는 오디오 데이터를 불러오는 인텐트를 보도록 하겠습니다.

데이터를 받아와야 하기 때문에 액션은 ACTION_GET_CONTENT, 특정 형식의 오디오 데이터가 아닌 모든 형식의 오디오 데이터를 불러와야 하므로 mimeType을 audio/* 로 지정합니다.

getAudioButton.setOnClickListener(new OnClickListener(){

			public void onClick(View v) {
				Intent i = new Intent(Intent.ACTION_GET_CONTENT);
				i.setType("audio/*");
				startActivityForResult(i, 0);
			}
        	
        });

이 인텐트를 실행시켜 보면, 다음과 같은 화면이 나타나게 됩니다.




현재 오디오 데이터를 받아올 수 있는 컴포넌트로 음악 트랙 선택(Music플레이어)와 Sound Recorder 2개가 있는 것을 알 수 있습니다. 암시적 인텐트는 이런 식으로 해당 작업을 할 수 있는 모든 컴포넌트들을 호출할 수 있습니다. 따라서 인텐트 해석 결과, 위와 같이 해당 데이터를 처리할 수 있는 컴포넌트가 여러 가지인 경우 사용자가 원하는 컴포넌트를 선택하여 액션을 "마무리" 해 줘야 합니다. 

그럼, 바로 아래의 인텐트를 실행시켜볼까요? 

getAudioButtonWithChooser.setOnClickListener(new OnClickListener(){

 			public void onClick(View v) {
 				Intent i = new Intent(Intent.ACTION_GET_CONTENT);
 				i.setType("audio/*");
        		startActivityForResult(Intent.createChooser(i, "Select Audio Source..."), 0);
        		}
                	
            });

이 인텐트를 실행시키게 되면 다음과 같은 화면이 표시됩니다.



여기에서는 인텐트를 실행시킬 때 IntentChooser를 사용하여 인텐트를 처리할 수 있는 컴포넌트가 하나 이상이 되어 여러 컴포넌트 중 하나를 선택할 때 나오는 다이얼로그의 이름을 지정해 줄 수 있습니다. 위와 같이 모든 어플리케이션에서 사용될 수 있는 파일 형식 (이미지, 사진, 비디오 등..)을 가진 데이터를 받아오게 될 경우, 위와 같이 IntentChooser를 사용하여 미리 다이얼로그의 이름을 지정해주는 것이 더 좋겠죠? 

마지막으로, 주소록에서 전화번호를 받아오는 인텐트를 보도록 하겠습니다.

[SDK 1.6 이하]

getContactsButton.setOnClickListener(new OnClickListener(){

			public void onClick(View v) {
				Intent i = new Intent(Intent.ACTION_GET_CONTENT);
				i.setType("vnd.android.cursor.item/phone");
				startActivityForResult(i,0);
			}
        	
        });

위의 인텐트를 실행하면 다음과 같은 화면이 표시되며, 주소록에서 이름을 선택하게 되면 LogCat 화면에 선택한 이름의 전화번호가 저장된 주소(URI)가 표시되게 됩니다.

전화번호부 액티비티가 호출된 화면


DDMS에 선택한 주소록 데이터의 주소가 표시됩니다.



인텐트의 액션은 ACTION_PICK, 데이터로는 content://contacts/phones를 설정하였습니다. 이 인텐트는 전화번호부의 데이터를 받아올 수 있는 인텐트입니다. 

ACTION_PICK은 ACTION_GET_CONTENT와 같이 데이터를 받아올 때 사용하는 액션입니다. 하지만, 두 액션은 부가적으로 필요로 하는 정보에 다소 차이가 있습니다. ACTION_PICK은 부가적으로 필요한 데이터로 데이터의 실제 주소(URI; Uniform Resource Identifier)를 사용하며, ACTION_GET_CONTENT는 데이터의 유형(mimeType)을 사용합니다.

따라서, 일반적으로 이미지, 영상 등 여러 어플리케이션에서 범용으로 사용되는 데이터를 불러올 대는 ACTION_GET_CONTENT 및 해당 데이터의 타입을 가지는 인텐트를 사용하고 전화번호부처럼 특정 어플리케이션에서만 사용하는 데이터를 불러올 경우 ACTON_PICK 및 해당 데이터의 주소를 사용합니다. 하지만, 꼭 이렇게 정해진 것은 아니므로 편의에 따라 ACTION_GET_CONTENT 및 ACTION_PICK 중 하나를 선택하여 사용할 수도 있습니다. 

위의 전화번호부를 받아오는 인텐트는 아래와 같이 ACTION_GET_CONTENT를 사용하도록 만들 수도 있습니다.

Intent i = new Intent(Intent.ACTION_GET_CONTENT);
				i.setType("vnd.android.cursor.item/phones");
				startActivityForResult(i,0);

위의 인텐트를 실행하면 위의 인텐트와 같이 주소록이 표시되게 되며, 이름을 선택하게 되면 위의 ACTON_PICK을 사용한 인텐트와 동일하게 전화번호가 저장되어 있는 주소를 반환합니다.

SDK 2.0 (Eclair) 버전부터는 주소록의 주소가 다소 변경되었습니다. 따라서 위의 코드를 그대로 쓰시면 주소록을 정상적으로 받아올 수 없습니다. 2.0 에서는 다음과 같이 사용하시면 됩니다. 기존의 코드를 그대로 사용하시면 아래와 같이 주소록을 찾을 수 없다는 메시지가 표시됩니다.

				Intent i = new Intent(Intent.ACTION_GET_CONTENT); // ACTION_GET_CONTENT 액션을 사용하는 경우
				i.setType("vnd.android.cursor.item/phone_v2");
				startActivityForResult(i,0);

				Intent i = new Intent(Intent.ACTION_PICK); // ACTION_PICK 액션을 사용하는 경우
				i.setData(Uri.parse("content://com.android.contacts/data/phones"));
				startActivityForResult(i,0);

위의 코드를 사용한 경우

1.6 버전용 코드를 사용한 경우




지금까지, 인텐트의 개념부터 시작하여 특징, 종류 및 실제로 암시적 인텐트를 사용하는 방법까지 알아보았습니다. 여기까지 잘 따라오셨다면 인텐트의 정체(!)에 대해 어느 정도 눈을 뜨셨을겁니다. :)

여기에서 인텐트에 대해 다루는 범위는 여기까지이지만, 이것 외에도 인텐트는 심오한 면들을 많이 가지고 있습니다. 안드로이드 시스템에서 없어서는 안될 핵심적인 역할을 하기도 하구요. 비록 영문이기는 하지만, 인텐트와 관련된 다른 내용들은 Android Developers 사이트의 문서들을 찾아보면 상세히 기술되어 있으니 이 문서들을 정독해보는 것을 추천합니다.
저작자 표시 비영리 변경 금지
신고

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

  1. Blog Icon
    나그네

    정말 잘봤습니다!!!
    이렇게 집중하면서 재미있게 정독이 가능한 글을 써주시다니.. 다시한번 감사드립니다. ^^
    초반개념잡기가 너무 어려웠던 안드로이드.. 이곳에서 많이 배우고 가네요.

  2. Blog Icon

    비밀댓글입니다

  3. 정지되어있다고 보시는게 맞습니다.
    프로세스는.....
    일반적으로는 같은 어플리케이션 내의 컴포넌트일 경우 같은 프로세스 내에서 실행되며, 다른 프로세스 내의 어플리케이션일 경우 해당 어플리케이션의 프로세스가 별도로 생성됩니다.

    같은 어플리케이션 내의 컴포넌트라 할지라도 별도로 매니페스트에서 지정해주면 다른 프로세스에서 실행하도록 할 수 있습니다.

  4. Blog Icon
    소망아기

    암시적 인텐트로 호출할 때, 그 type을 받을 수 있는 모든 app를 찾아서 리스트 팝업으로 뿌려 주잖아요..
    그 리스트 팝업의 Title을 바꿀수 있는 방법이 있을까요?

  5. 위 글 내용 중 IntentChooser를 사용하시면 됩니다 :)

  6. Blog Icon
    진인

    혹!

    [2010-11-14 21:13:51 - DeviceMonitor]Sending jdwp tracking request failed!

    이런 메시지는 먼가요?? 실행할때마다 자꾸 뜨네요??

  7. 보통은 에뮬레이터 끌때나 기기를 컴퓨터에서 분리할때 뜨는 메시지인데... 별로 신경쓰지 않으셔도 됩니다.

    예전에는 안나오다가 최근 업데이트 버전부터 그러는 것 같은데.. 원인은 자세히 모르겠습니다;;

  8. Blog Icon
    jbin_k

    저기 죄송한데 ACTION_GET_CONTENT를 쓰고 주소록 받아올 때 SDK 2.1에서는 안의 내용을 어떻게 써야 하는지 혹시 알고 계신가요??2.1로 실습을 하고 있는데 주소록 부분만 이전 버전용 코드를 입력했을때와 동일한 결과값이 나와서 말이죠.. 알려주시면 감사히 따라하겠습니다. (--)(__)

  9. phone_v2로 입력해서 주소록 선택 화면이 나왔다면 이상이 없는 것입니다.

    동일한 결과값이 나온다는 것이 정확히 어떤 것을 의미하는건가요?

  10. Blog Icon
    Rew

    저기 혹시 ACTION_DIAL를 ListView-ArrayAdapter에서도 사용이 가능할까요??

  11. Blog Icon
    ho

    저 코드 그대로 쓰면 실행 되나요? 인텐트필터 따로 지정 안해줘도 되나요???

    저 코드 그대로 쓰니까
    콘솔창에
    No Launcher activity found!
    The launch will only sync the application package on the device!
    이렇게 뜨는데 어떻게 해야 하나요 ㅜㅜ

  12. 해당 내용은 만드신 애플리케이션에서 기본으로 실행할 애플리케이션이 없어서 나오는 내용으로 위의 글과는 관련이 없습니다.

  13. Blog Icon
    덜지

    퍼가도되죠???!!!!!