[Ch3-6] 인텐트 세번째! 다양한 메서드(방법)를 활용하여 액티비티 간 데이터 주고 받기 (Pass data between android activities)
오랜만이다 우리 병아리들... 정말로 요새는 시간이 없었다. 앞으로 게으름 피우지 말아야지.
각설하고, 바로 시작하도록 하겠다. 사실 나도 책을 보며 같이 공부하는 중이라 처음에는 좀 헷갈렸다. 그래서 어떻게 풀이해야 더 직관적일까를 좀 생각해보다가, 우리가 원하는 프로젝트의 결과물을 먼저 보여주고 뒤에 수반되는 절차를 보는 것이 더 낫겠더라.
※ 위의 자료는 왼쪽에서 오른쪽, 위에서 아래로 보면 된다.
ㅇ 위 프로젝트의 기능
1. 가장 왼쪽 상단에 있는 화면이 앱을 시작했을때의 초기 화면이다. 저기서 "두번째 액티비티로 고고띠 버튼을 클릭하면 두 번째 화면으로 이동한다. 그 뒤, 사용자는 아무것도 하지 않아도 순차적으로 "마칼의 공부방", 100, "최고오오오", 90000의 값을 뿌려준다.
2. 그 뒤 사용자가 다시 "첫번째 액티비티로 고고띠" 버튼을 클릭하면, 다시 화면은 첫 번째 액티비티로 돌아간다. 그다음 8282, "다비치"의 값을 뿌려준다.
자, 어떻게 하면 이것을 만들 수 있을까?
1. 우선 무엇을 하던간에 작업을 할 판때기가 필요함으로, Empty Project를 하나 생성한다.
2. 그 다음, 화면이 두 개임으로 MainActivity.java 와 activity_main.xml처럼 기본으로 제공하는 하나의 화면 이외에 다른 화면을 하나 생성해준다.
2.1 SecondActivity.java (클래스 파일을 생성한다. 위치는 MainActivity.java와 같은 곳 정리 (차곡차곡)
2.2 activity_second.xml 을 생성한다. res -> layout 에 있는 activity_main.xml을 복사하여 같은 디렉터리에 붙여 넣고 이름만 바꿔도 된다.
3. activity_main.xml과 activity_second.xml 에서 우선 화면 그림부터 그리자. 기능은 나중에 때려박아보자.
3.1 activity_main.xml 수정
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:onClick="onClick"
android:text="두번째 액티비티로 고고띠"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
3.2 activity_second.xml 수정
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:text="두번째 액티비티 임"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:onClick="onClick"
android:text="첫번째 액티비티로 고고띠"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
</android.support.constraint.ConstraintLayout>
여기까지 하면, 우선 화면은 비슷하게 나올 것이다.
4. 안드로이드 스튜디오에서 자동으로 만들어주는 MainActivity.java와 activity_main.xml 이외에 다른 액티비티가 생성되었다는 것을 AndroidManifest.xml 에 알려준다.
4.1 AndroidManifest.xml 수정 (app -> AndroidManifest.xml)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.passdata">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="com.example.passdata.SecondActivity"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
</application>
</manifest>
5. MainActivity.java 에서 기능을 때려 박아 보자.
package com.example.passdata;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onClick(View view) {
Intent i = new
Intent("com.example.passdata.SecondActivity");
//-- putExtra() : name 과 value pair(짝을) 추가한다.
i.putExtra("str1", "마칼의 공부방");
i.putExtra("age1",100);
//-- Bundle Object 사용하여 name 과 value pair 만들기
// pairs --
Bundle extras = new Bundle();
extras.putString("str2", "최고오오오");
extras.putInt("age2", 90000);
//--사용한 Bundle pair 를 Intent 에 사용하기
i.putExtras(extras);
//--result 값 받기 (request code 는 여기서 지정)
startActivityForResult(i, 1);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
//-- 만약 request code 가 1이면
if (requestCode ==1) {
//-- 만약 Reuslt 가 OK 이면
if (resultCode == RESULT_OK) {
//--getIntExtra() 메서드 사용하여 Second Activity 에서 return 된 값 받기
Toast.makeText(this, Integer.toString(data.getIntExtra("age3", 0)), Toast.LENGTH_SHORT).show();
//--getdata() 메서드 사용하여 Second Activity 에서 return 된 값 받기
Toast.makeText(this, data.getData().toString(), Toast.LENGTH_SHORT).show();
}
}
}
}
5.1 public void onCreate() 부분은 우선 app을 onCreate 상태로 만들어 실행시키는 작동을 한다. 그 뒤 setContentView에서 (R.layout.activity_main); 을 알려줌으로 activity_main.xml의 화면과 연동되어 있다는 것을 알려준다.
5.2 public void onClick()에서는 버튼이 클릭되었을 때 작동되어야 하는 행동들을 정의한다. 우선 Intent 인스턴스를 생성하여 연결할 대상 화면이 SecondActivity라는 것을 알려준 뒤, 그 뒤 putExtra()와 Bundle object를 사용하여 SecondActivity로 값과 request code를 날린다.
5.3 public void onActivityResult()에서는 Request code와 RESULT_OK (결괏값이 잘 반환되었다는 신호)를 확인한 뒤, SecondActivity에서 받은 값을 Toast (빵처럼 구워준다 "LENGTH_SHORT" 잠깐 보여준다)
ㅇ 정리해보자, 5.1 부분은 앱을 시작하는 부분은 있어야 되니까 당연한 이야기고,
ㅇ 5.2는 MainActivity에서 값을 SecondActivity로 날리는 부분
[ ("마칼의 공부방", 100, "최고오오오", 90000)를 SecondActivity로 전송]
ㅇ 5.3 은 SecondActivity에서 값을 받아와서 MainActivity에서 보여주는 부분이다. [(8282, "다비치")를 보여줌]
자, 그러면 반대로 SecondActivitiy 도 상호작용 할 수 있는 기능을 넣어야 할 것 아닌가?
6. SecondActivity.java 수정
package com.example.passdata;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import android.net.Uri;
import android.content.Intent;
public class SecondActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
//--getStringExtra() 사용하여 데이터 받기---
Toast.makeText(this,getIntent().getStringExtra("str1"),Toast.LENGTH_SHORT).show();
//--getIntExtra() 사용하여 데이터 받기--
Toast.makeText(this, Integer.toString(getIntent().getIntExtra("age1", 0)), Toast.LENGTH_SHORT).show();
//--번들 오브젝트 가져오기 ---
Bundle bundle = getIntent().getExtras();
//--getString() 메서드 사용하여 데이터 받기----
Toast.makeText(this, bundle.getString("str2"), Toast.LENGTH_SHORT).show();
//--getInt() 메서드 사용하여 데이터 받기----
Toast.makeText(this, Integer.toString(bundle.getInt("age2")),Toast.LENGTH_SHORT).show();
}
public void onClick(View view) {
//--Intent Object 사용하여 MainActivity로 데이터 보내기
Intent i = new Intent();
//--putExtra() 사용하여 값 되돌려주기
i.putExtra("age3",8282);
//--setData() 사용하여 값 되돌려주기
i.setData(Uri.parse("다비치"));
//--set the result with OK and the Intent object--
setResult(RESULT_OK, i);
//--destroy the current activity--
finish();
}
}
6.1 마찬가지로, onCreate와 setContentView를 기본으로 넣어준다. 다만 추가되는 사항은, 사용자가 아무것도 하지 않아도, onCreate() 되고 setContentView로 화면이 연결됨과 동시에, MainActivity에서 받은 값을 토스트(Toast)해준다.
6.2 그다음 public void onClick()에서, 사용자가 클릭할 경우, 다음의 지정된 값을 MainActivity로 반환한다.
6.3 그리고 언제나처럼 finish()로 자동으로 액티비티를 종료한다.
결론 : 개인적으로 비개발자이면서 센스 없는 사람에 속하는 부류임으로, 처음에 하면서 뭔가 잘못되거나 했을 때 굉장히 애를 먹었다. 여기까지 따라한 사람들 모두 개발 본인이 원하는 공부의 목표를 달성할 수 있기를 나도 같이 희망한다.
궁금증 : MainActivity에서 SecondActivity로 값을 더 Toast 하고 싶으면 어떻게 하면 되나?
package com.example.passdata;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onClick(View view) {
Intent i = new
Intent("com.example.passdata.SecondActivity");
//-- putExtra() : name 과 value pair(짝을) 추가한다.
i.putExtra("str1", "마칼의 공부방");
i.putExtra("age1",100);
//-- Bundle Object 사용하여 name 과 value pair 만들기
// pairs --
Bundle extras = new Bundle();
extras.putString("str2", "최고오오오");
extras.putInt("age2", 90000);
//----- 추가된 부분 ---------
extras.putString("str4", "글자 추가");
extras.putInt("age4", 19999);
//--------------------------
//--사용한 Bundle pair 를 Intent 에 사용하기
i.putExtras(extras);
//--result 값 받기 (request code 는 여기서 지정)
startActivityForResult(i, 1);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
//-- 만약 request code 가 1이면
if (requestCode ==1) {
//-- 만약 Reuslt 가 OK 이면
if (resultCode == RESULT_OK) {
//--getIntExtra() 메서드 사용하여 Second Activity 에서 return 된 값 받기
Toast.makeText(this, Integer.toString(data.getIntExtra("age3", 0)), Toast.LENGTH_SHORT).show();
//--getdata() 메서드 사용하여 Second Activity 에서 return 된 값 받기
Toast.makeText(this, data.getData().toString(), Toast.LENGTH_SHORT).show();
}
}
}
}
해결 : 다음과 같이 그냥 MainActivity에서 추가해버리고, SecondActivity에서 Toast 해버리면 되더라.
오늘은 유난히 고생 많으셨습니다. 다들 화이팅!! 나도 화이팅!!