태터데스크 관리자

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

태터데스크 메시지

저장하였습니다.

인텐트(Intent) 입문- (2) 액티비티간 데이터 주고받기

2009.03.14 06:52

인텐트를 다루는 두 번째 시간이 돌아왔습니다.  (와우!)
이번 강좌는 저도 인텐트를 쪼~까 공부하느라 뭔가 깔끔하지 못할 지도 모르겠네요(...)
그래도 최대한 자세하게 다뤄보도록 할테니! 걱정은 마시고!! 따라오시면 될겁니다. (아마도요...펑...)

지난 시간에는 다른 액티비티를 단순히 "호출"하는 것만 배웠습니다. 그런데, 실제 어플리케이션을 개발하다보면 액티비티를 호출하는 것은 어찌보면 당연한 것이고, 액티비티간에 데이터를 주고받아야 할 일이 생깁니다. 그럴 땐 어떻게 해야 할까요? => 바로, 이 때도 인텐트를 사용하면 됩니다(...)

인텐트는, 액티비티를 호출하는 수단 뿐 아니라 인텐트 자체에 액티비티간 주고받아야 할 정보들을 실어줄 수 있습니다. 예를 들자면 심부름꾼(???) 이라고 할까나요??

A라는 사람이 B에게 물건을 가져오라고 심부름꾼에게 시키면, 심부름꾼은 B에게 가서 물건을 받아 A에게 전달해주게 됩니다. 마찬가지로, 액티비티 A가 B로부터 어떠한 정보를 받고 싶다면, 인텐트를 사용하여 B를 호출한 다음, 인텐트에 원하는 정보를 실어서 그 정보를 다시 돌려받으면 됩니다.

일단, 호출하는 액티비티 (InformationInput)호출당하는 액티비티(InformationProc)의 코드를 보도록 하겠습니다.


(주의)
액티비티를 추가하는 방법을 모르신다면, 2009/03/01 - [안드로이드/안드로이드 입문] - [강좌] [수정] 이클립스에서 안드로이드 액티비티 추가하기 를 읽고 액티비티 추가 방법에 대해 숙지하신 후 이 강좌를 읽어주세요.


[InformationInput.java]

package com.androidhuman.IntentTest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class InformationInput extends Activity {	
	/** Called when the activity is first created. */
	@Override    public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		final Button requestInfo  = (Button)findViewById(R.id.requestInfo);
		requestInfo.setOnClickListener(new Button.OnClickListener(){ // 버튼을 클릭할 경우
			public void onClick(View v){
				Intent intent = new Intent(InformationInput.this,InformationProc.class);
				startActivityForResult(intent, 1); // Sub_Activity 호출
				}
			});
		}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data){
		super.onActivityResult(requestCode, resultCode, data);
		TextView name_view = (TextView)findViewById(R.id.name_view);
		TextView digit_view = (TextView)findViewById(R.id.digit_view);
		if(resultCode==RESULT_OK) // 액티비티가 정상적으로 종료되었을 경우
			{
			if(requestCode==1) // InformationInput에서 호출한 경우에만 처리합니다.
				{				// 받아온 이름과 전화번호를 InformationInput 액티비티에 표시합니다.
				name_view.setText(data.getStringExtra("data_name"));
				digit_view.setText(data.getStringExtra("data_digit"));
				}
			}
		}
	}


[main.xml]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_height="fill_parent" 
android:layout_width="fill_parent" 
android:orientation="vertical" 
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:layout_height="wrap_content" 
android:layout_width="fill_parent" 
android:text="@string/name" />
<TextView android:layout_height="wrap_content" 
   android:layout_width="fill_parent" 
   android:text="-이름이 입력되지 않음-" 
   android:id="@+id/name_view"/>

<TextView android:layout_height="wrap_content" 
    android:layout_width="fill_parent" 
    android:text="@string/digit"/>

<TextView android:layout_height="wrap_content" 
   android:layout_width="fill_parent" 
    android:text="-전화번호가 입력되지 않음-" 
    android:id="@+id/digit_view"/>

<Button android:layout_height="wrap_content" 
    android:layout_width="wrap_content" 
    android:text="@string/button_launch" 
    android:id="@+id/requestInfo"  
    android:layout_gravity="center_horizontal"/>
</LinearLayout>



[InformationProc.java]

package com.androidhuman.IntentTest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class InformationProc extends Activity {	
	/** Called when the activity is first created. */	
	@Override	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.informationproc);
		Button input_info = (Button)findViewById(R.id.inputinfo);
		input_info.setOnClickListener(new OnClickListener(){
			
		public void onClick(View v) { //버튼을 클릭하면
			Intent intent = getIntent(); // 이 액티비티를 시작하게 한 인텐트를 호출
			EditText name_input = (EditText)findViewById(R.id.name_input);
			EditText digit_input = (EditText)findViewById(R.id.digit_input);
			intent.putExtra("data_name",name_input.getText().toString());
			intent.putExtra("data_digit", digit_input.getText().toString());
			setResult(RESULT_OK,intent); // 추가 정보를 넣은 후 다시 인텐트를 반환합니다.
			finish(); // 액티비티 종료
			}
		});
	}



[informationproc.xml]



 


<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout 
    android:layout_height="wrap_content" 
    android:layout_width="fill_parent" 
    android:orientation="vertical" 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/overview_layout">

<TextView android:layout_height="wrap_content" 
    android:layout_width="wrap_content" 
    android:text="@string/text_information"/>

<LinearLayout android:layout_height="wrap_content" 
    android:layout_width="fill_parent" 
    android:orientation="horizontal" 
    android:id="@+id/name_layout">

<TextView android:layout_height="wrap_content" 
    android:layout_width="wrap_content" 
    android:text="@string/name"/>

<EditText android:layout_height="wrap_content" 
    android:layout_width="fill_parent" 
    android:id="@+id/name_input" 
    android:hint="ex)안드로이드"/>
</LinearLayout>

<LinearLayout android:layout_height="wrap_content" 
    android:layout_width="fill_parent" 
    android:orientation="horizontal" 
    android:id="@+id/digit_layout">

<TextView android:layout_height="wrap_content" 
    android:layout_width="wrap_content" 
    android:text="@string/digit"/>

<EditText android:layout_height="wrap_content" 
    android:layout_width="fill_parent" 
    android:id="@+id/digit_input" 
    android:hint="ex)011-123-4567"/>

</LinearLayout>

<Button android:layout_height="wrap_content" 
    android:layout_width="wrap_content" 
    android:text="@string/input" 
    android:id="@+id/inputinfo" 
    android:layout_gravity="center_horizontal"/>
</LinearLayout>


단순히 액티비티를 호출할 때에는 startActivity(Intent)를 사용했었지만, 액티비티를 호출한 후 결과값을 받기 위해서는 다른 메소드를 사용해야 합니다. 바로 startActivityForResult(Intent intent, int requestCode)입니다.


public void startActivityForResult(Intent intent, int requestCode)
호출당하는 액티비티로부터 데이터를 넘겨받기 위해 사용합니다.
intent - 인텐트
requestCode - 이 액티비티를 호출하는 액티비티가 여러 개가 있을 경우, 어떤 액티비티가 호출했는지를 알기 위해 사용


requestCode는 별로 특이한 것은 아니고, 한 액티비티를 여러 액티비티가 호출해야 할 경우, 호출이 어디에서 일어났는지를 알려주는 인자값입니다.
일단, InformationInput 액티비티를 봅시다. 버튼을 클릭하면 InformationInput 액티비티가 InformationProc 액티비티를 호출해야 하므로, 일단 intent를 생성하고, startActivityForResult()를 통해 InformationProc 액티비티를 실행시킵니다.



InformationProc 액티비티가 실행되면, 사용자로부터 이름과 전화번호를 입력받게 됩니다.
입력이 끝나고, 입력 버튼을 누르면, 입력받은 데이터를 인텐트에 집어넣게 됩니다.
Intent intent = getIntent(); // 이 액티비티를 시작하게 한 인텐트를 호출	
     EditText name_input = (EditText)findViewById(R.id.name_input);	
     EditText digit_input = (EditText)findViewById(R.id.digit_input);
     intent.putExtra("data_name",name_input.getText().toString());	
     intent.putExtra("data_digit", digit_input.getText().toString());	
     setResult(RESULT_OK,intent); // 추가 정보를 넣은 후 다시 인텐트를 반환합니다.	
finish(); // 액티비티 종료

차근차근 하나씩 보도록 하겠습니다.
일단, 첫번째, 인텐트를 생성하는 것을 볼 수 있습니다. 보통, 인텐트를 생성할 때 new 생성자를 써서 인텐트를 생성했던 것에 반해, 여기에서는 getIntent()를 사용하여 인텐트를 불러오고 있습니다. getIntent()메소드는 현재 자신을 호출했던 인텐트를 반환해줍니다.

여기서, 자신을 호출한 인텐트를 받아오는 것은, 아까 예로 들었던 심부를꾼을 생각해보면 쉽게 이해할 수 있습니다. A라는 심부름꾼에게서 물건을 받았는데, B라는 심부름꾼에게 물건을 주면 안되겠죠? 인텐트도 마찬가지입니다. :)

이렇게 해서 인텐트를 생성하면, 이제 EditText로부터 입력한 값들을 받아와야 합니다. findViewById()를 이용하여 레이아웃 객체와 코드상의 객체를 연결한 후, putExtra()메소드를 이용해 정보를 실어줍니다.

intent.putExtra(String name, _value)
name이라는 이름을 가지는 데이터를 인텐트에 첨가합니다.

인텐트에 들어가는 데이터는 "키"의 역할을 하는 name과 그에 해당하는 값인 _value가 짝을 이루어 저장됩니다.
이렇게 저장이 되었다면, 호출된 액티비티가 정상적으로 끝났는지, 비정상적으로 끝났는지 (물건을 제데로 받았는지, 심부름꾼이 왔는지 등등...으로 비유할 수 있겠습니다) 자신을 호출한 액티비티에게 알려주기도 해야 하고, 요청한 데이터도 같이 주어야 합니다.

일단, 호출당한 액티비티가 정상적으로 끝났음을 알리기 위해, setResult(RESULT_OK, intent) 메소드를 사용합니다. RESULT_OK로 액티비티가 정상적으로 끝났음을 전달하게 됩니다. RESULT_OK를 반환하지 않고 중간에 비정상적으로 종료되었다면 저 코드를 반환받지 못하므로 뭔가 문제가 있구나 알게 되겠죠? 제데로 종료가 된다면, 아까 우리가 추가로 입력한 데이터를 담은 인텐트도 함께 반환하게 됩니다.

이렇게.. 여기까지 정상적으로 돌아간 후, 호출당한 액티비티(InformationProc)가 finish()메소드에 의해 종료되게 되면, OnActivityResult() 메소드가 호출되게 됩니다. 결과를 기다리고 액티비티를 호출했으니, 액티비티가 종료되었으니 그 결과를 확인해야겠죠??


void onActivityResult(int requestCode, int resultCode, Intent data)
startActivityForResult로 호출한 액티비티가 종료되었을 때 호출됩니다.



protected void onActivityResult(int requestCode, int resultCode, Intent data)
{		super.onActivityResult(requestCode, resultCode, data);
		TextView name_view = (TextView)findViewById(R.id.name_view);
		TextView digit_view = (TextView)findViewById(R.id.digit_view);
		if(resultCode==RESULT_OK) // 액티비티가 정상적으로 종료되었을 경우
		{
			if(requestCode==1) // InformationInput에서 호출한 경우에만 처리합니다.
			{
				// 받아온 이름과 전화번호를 InformationInput 액티비티에 표시합니다.
				name_view.setText(data.getStringExtra("data_name"));
				digit_view.setText(data.getStringExtra("data_digit"));
			}
		}
	}



위의 onActivityResult에서, resultCode가 아까 setResult()에서 액티비티가 정상 종료되었는지를 판단하는 인자값, RESULT_OK를 받게 됩니다. 그래서, 이걸 가지고 적절히 예외 처리를 해 줄 수 있는 거죠.
requestCode는 아까 startActivityForResult()를 호출할 때, InformationInput이 호출한 것임을 표시하기 위해 '1'으로 설정하였으므로, 여기에서 또한 그 코드를 맞춰주어야 제데로 결과값을 받을 수 있습니다.

즉, 정상적으로 액티비티가 종료되었다면 requestCode의 값은 RESULT_OK, resultCode는 1이 됩니다.

이렇게 해서, 모두 정상이라면 인텐트에서 받아온 데이터를 꺼내 화면에 표시합니다.

putExtra() 메소드가 어떤 타입이든 상관없었던 것에 비해, 불러올 때에는 getStringExtra()메소드를 사용하여 문자열 값을 불러오면 됩니다. getStringExtra()뿐 아니라 getIntExtra(), getBooleanExtra() 등 여러 가지가 있으므로 상황에 맞추어 사용하면 됩니다.

이렇게 해서, 화면에 표시되는 TextView의 텍스트 값들이 아까 호출한 액티비티의 값들로 바뀌게 됩니다. :)


이렇게 해서, 인텐트를 통해 액티비티간에 데이터를 주고받는 것에 대해서 알아보았습니다. 이번 강좌는 다른 강좌들과는 다르게 세세한 부분에 대한 설명은 대부분 생략하였습니다. 이 강좌쯤을 보시는 분들은 어느 정도 기초가 되어 있으리라 믿기에, 일부러 안 적었습니다. 게다가 그걸 다 적으면 강좌가 한도끝도 없이 길어지기만 하죠 -_-

현재, 이 코드는 모든 문자열 값을 strings.xml에 넣어서 그 쪽에 있는 값들을 참조하는 형식으로 구성되어있습니다. 이 부분에 대해 궁금하신 분은 제가 2009/03/14 - [안드로이드/안드로이드 입문] - [강좌] 외부 리소스 사용하기 (문자열) 에 정리해놓았으니, 이걸 보시면 되겠습니다. :)



저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

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

  1. 이전 댓글 더보기
  2. Blog Icon
    촌간지

    정말 이런 좋은 자료를 제공해주셔서 정말 감사드립니다.
    다른 어플을 호출할 일이 있습니다.
    그런데 타 어플을 사용자가 "OK"를 눌러서 제대로 실행했는지 그저 백키를 누르던가 "Cancel"을 눌렀는지 확인해야할 필요가 있어서 startActivityForResult()를 사용해서 어플이 내려간 상태도 알수는 있게 되었습니다.

    문제는 Activity에서는 startActivityForResult()를 사용할 수 있는데,
    Service에서 타어플 호출 시 startActivityForResult()를 사용할 수 없다는 문제가 있네요.

    혹시 Service에서 응용가능한 방안이 있을까요?

  3. Blog Icon
    전기박사

    자료 공계해주셔서 감사합니다.
    도서실에서 잠깐 본 책이였는데... 구매해서 봐야 겠어요...게시글 보고 많이 공부 하였습니다.

  4. Blog Icon
    oO위드Oo

    전 실행을하면 오류떠서 제대로 실행이 안되요...이럴땐 어떻게 해야하나요???ㅠㅠ

  5. 어떤 오류가 뜨는건지 확인해보세요. LogCat 로그를 확인하면 어떤 것 때문에 오류가 발생했는지 알 수 있습니다.

  6. Blog Icon
    냠냠

    커니님, 강의 잘봤습니다.
    근데 텍스트가 아닌 이미지뷰의 이미지는 어떻게 넘겨주는지 궁금해요...

  7. Blog Icon
    힝힝

    좋은 거 배우고 갑니다.
    여쭤 볼께 있는데요.. 데이터 주고 받는 거 성공 했거든요?
    입력한 값을 꼭 onAcitivityResult 메소드에서 받아야 되나요?
    데이터 값을 다른 메서드에 사용하고 싶은데... 좀 가르켜 주세요

  8. 다른 액티비티에서 받은 결과값은 onActivityResult()에서만 받을 수 있습니다.

    다른 메서드에서 이를 사용하려 한다면 단순히 onActivityResult()에서 다른 메서드를 호출하면 될 듯 하네요.

    결과를 직접 받은 액티비티가 아닌 다른 곳에 구현되어 있는 메서드를 실행하는 것이라면 리스너 인터페이스를 활용하시면 될듯 하구요,

  9. Blog Icon
    ㅠㅠ

    2009년에 여길 알았다면 좀더 빨리 배웠을텐데...
    삽질하면서 머릿속으로 대충 이런건가?싶으면서 넘어간것들에 대해서 잘 배워갑니다^^

  10. Blog Icon
    ㅇㄹㅇㄹㅇㄴ

    이 블로그가 안드로이드 강좌 중에서 최강인듯 하네요
    그러나 책 사려고 알라딘 갔떠니 품절 orz

  11. Blog Icon
    kimeana

    안드로이드를 개발하는데 이번에 허니콤에서 개발하는데 fragment를 사용하여서
    화면을 분할해서 왼쪽에는 리스트 그리고 오른쪽에는 그에 따른 db데이터를 보여주려고 하는데요
    전 버전으로 개발해 놓은것이있어서 살짝 응용만 하려고 하는데 옆에 리스트 1댑스에서 클릭했을때 2depth를 보여주고 싶은데 이건 어떤 api를 참조 하면 좋을까요 왼쪽에 리스트들을 전부다 넣고 싶어서요 그런 기능이 가능할까요?

  12. Blog Icon
    조제우

    startActivityForResult() 가 OnClickListener()에 정의돼있지 않다고 하는데..
    어떻게 해결하나요 ??;;
    getIntent() 이런것도 안돼고..
    gridview를 이용해서 버튼을 여러개 생성하고
    buttonadapter에서 버튼 클릭시 activity를 호출 하고,(startActivity()로) 호출된 activity에서 값을 전달한후 그 값을 처리 하는건데.
    null 값만 옵니다.. 어떻게 해야하나요 ?

  13. Blog Icon
    wk

    좋은 정보 감사합니다. 덕분에 개념을 잡게 되었네요. (꾸벅)

  14. Blog Icon
    pooh오빠

    음 근데 이게 일반 java 개발에서 데이터 class를 만들어서, set,get하는것과 무슨 차이가 있는거죠??

    장점이??

  15. 일반 클래스랑 인텐트랑은 아예 개념 자체가 다르다 보는게 편합니다.
    인텐트는 데이터를 전달하는 매개체로 쓰임과 동시에 다른 컴포넌트를 실행시키는 역할까지 하는 것이니까요.

  16. Blog Icon
    pooh오빠

    ㄴ그렇네요....아직도 잡힐까 말까하네요..개념이....ㅠㅠ

  17. 커니님, 오타가 있는 것 같아 댓글로 제보해봅니다.

    "위의 onActivityResult에서, requestCode가 아까 setResult()에서 액티비티가 정상 종료되었는지를 판단하는 인자값, RESULT_OK를 받게 됩니다. 그래서, 이걸 가지고 적절히 예외 처리를 해 줄 수 있는 거죠."

    위 문장에서 requestCode가 아닌 resultCode가 아닌지 의문이네요. RESULT_OK를 받는 것은 resultCode여서 맞는 것 같습니다. 게다가 위 문장 바로 아래에 또 requestCode를 설명해주셔서 착오가 있었던 것 같습니다.

    최근 들어 많은 도움을 받고 있네요. 이 자릴 빌어 정말 고맙다는 말씀 드립니다. :)

  18. 수정했습니다. 제보 감사드립니다 :)

  19. Blog Icon
    SPOCK

    메인액티비티가 뉴 액티비티에 값을 던질 수는 없나요??
    그에 대한 여지가 Startforresult에서 requestcode가 될 수 있을 것 같은데 잘 안되는것 같네여 ㅠㅠ

  20. Intent에 값을 넣어 호출하면 전달 가능합니다.
    예 )
    Intent intent = new Intent(...);
    intent,putExtra([태그], [데이터]);

  21. Blog Icon
    spock

    안녕하세요! 좋은 글 감사합니다!

    sub액티비티가 아닌 인텐트를 통해, 갤러리에 접근했습니다

    갤러리에서 선택된 사진에 대한 데이터를 받아오고 싶은데

    이 갤러리(액티비티? 풀스크린 다이얼로그?)는 제가 만들어 놓은 코드가 아닌 휴대폰에 들어있는 기본 앱이기 때문에
    어떻게 처리를 해줘야 될지 모르겠습니당

    제가 만들고자하는건 갤러리에서 선택된 사진을 업로드 시키는걸 하고 싶어요!

  22. Blog Icon
    ddong

    커니야~ 내가 이제와서 너의 블로그를..애용하기 시작한단다..ㅋㅋㅋ

  23. Blog Icon
    진우제

    안녕하세요 좋은 강의 감사합니다.

    정보를 넣고 input버튼을 누르면 정보가 다음 창에 떳으면 하는 구조로 만들고 싶은데
    manifest에서 순서를 바꿔도 input을 누르면 앱이 꺼지네요 내부에서 뭔가 설정이 필요한거 같은데...ㅠ.ㅠ 너무 초보라서
    혹시 가능하시다면 소스라도 좀 적어주시면 안될까요??...염치 없음에도 불구하고 한번 여쭙습니다... 부탁드립니다....

  24. 어떤 식으로 구현하셨나요?
    구현하신 방식이나 순서를 알려주신다면 도움을 드릴 수 있을 것 같습니다.

  25. Blog Icon
    경으니

    안녕하세용 :) 많이 배우고 갑니다.

    한가지 질문이 있는데, 제가 지금 구현하려는 어플이 메인에서 버튼 누르면 인텐트 i 로 서브로 넘어가고, 서브에서 정보를 i 에 인풋받아서 또 다른 액티비티(서브서브)로 넘어가게 하고 싶은데요. 올려주신 예제대로는 다구현이 되는데, 메인화면에 데이터가 나타나는게 아니라 서브서브에서 나타나게 하고 싶은데, 정보를 담은 인텐트 i 를 어떻게 활용해야 하는지 막막합니다 ㅜㅜ

    서브에서 finish();말고 서브서브로 넘어가게 하려고 인텐트를 주자니 새로운 인텐트라 i 의 정보를 갖을 수 없고,
    메인으로 아예 돌아온 다음에 onActivityResult에서 하려고 해도 이 정보를 갖고있는 i 를 어떻게 써야 하는지 모르겠습니다ㅜㅜ 도와주세요..

  26. Blog Icon
    초보

    안녕하세요! 안드로이드 배우고있는 학생인데요!

    궁금한점이 있어서 혹시 아이디어를 얻을 수 있을까해서 댓글남기게 되었습니다...

    코딩은 자마린 안드로이드로 하고있지만 안드로이드로 설명해주시면 눈치껏 알아듣겠습니다..
    제가 NFC를 하고있는데요..

    A에서 Read한다음 B로 intent에 id값 넘긴 후 B에서 id값을 사용한 후 Write하려고하면 intent 한 값이 null 이라는 에러가 뜨는데요..
    A에서 Read하지않고 List든 뭐든... intent로 id값을 넘긴 후 B에서 id값을 사용한 후 write하려고하면 잘됩니다..

    제가 한 방식에 오류가 있는걸까요..??

    if문으로 if (this.Intent.Extras.Get("id";).ToString() == "";) 해도 먹히질않고... 방법이 있을까요 ...

  27. 말씀해 주신 부분만으론 정확히 파악이 안 되는데, Intent 객체를 그대로 B 액티비티에 넘겼을 때의 동작이 다른 건가요?

  28. Blog Icon
    대학생

    감사합니다 찾고있던 문제였습니다.