티스토리 뷰



이 자료들은 팁스소프트에서 제공하는 [ 알짜배기 ] 프로그램을 이용하면 더 편리하게 볼수 있습니다.
* 알짜배기 프로그램 받기 - http://www.tipssoft.com/bulletin/tb.php/QnA/8406
* 안드로이드 강좌 목록 - http://www.tipssoft.com/bulletin/tb.php/old_bbs/501
안드로이드용 어플리케이션은 여러 개의 컴포넌트들로 이루어져 있습니다. 컴포넌트의 종류는
Activities, Services, Content Providers, Broadcast Receivers 인데, 이 강좌에서는 실행의
기준이 될 수 있는 액티비티(Activity) 컴포넌트에 대해서 설명하겠습니다.
1. 액티비티(Activity) 컴포넌트의 역할
안드로이드 시스템에서 액티비티 컴포넌트는 사용자와 어플리케이션 간의 상호작용을 할 수 있도록
다이얼이나 웹브라우저 같은 가시적인 화면을 제공하는 역할을 합니다. 보편적으로 아래의 그림처럼
어플리케이션이 실행됐을 때 가장 먼저 실행되는 액티비티를 메인 액티비티 (Main Activity) 라고
부르기도 합니다.
일반적으로 액티비티는 사용자가 원하는 작업을 할 수 있도록 화면을 제공하기 때문에 사용자
환경을 그릴 수 있는 윈도우 기반으로 구성되어 있습니다. 이러한 윈도우는 사용자 기기 화면을
가득 채우는 것이 일반적이지만 때때로 화면보다 작거나 다른 윈도우 위에 항상 존재하는 형태로
표현되기도 합니다.
예전부터 프로그램이 컴포넌트의 집합으로 표현된 적은 있었지만 항상 특정 컴포넌트만이 시작을
담당하는 것이 일반적이었습니다. 하지만 실행 권한을 가진 안드로이드의 액티비티 컴포넌트는 기존
개념을 깨고 어플리케이션 내에 포함된 어떠한 액티비티 컴포넌트든지 시작 시점이 될 수 있습니다.
이렇게 다중 실행시점을 가지도록 설계한것은 모바일 기기의 특성상 열악한 시스템 자원을 좀더
효과적으로 관리하기 위해서 실행과 관련된 절차를 간소화시키고 특정 어플리케이션이 가지고 있는
액티비티를 다른 어플리케이션에서 쉽게 재사용할수 있도록 하기 위함입니다.
결국, 잘 만들어진 액티비티 컴포넌트를 재사용하기 편리하도록 구성하여 다른 어플리케이션이
동일한 기능의 컴포넌트가 필요할때, 추가적인 개발없이 해당 액티비티 컴포넌트를 사용하게
유도함으로써 개발의 편리성을 증대시키고 불필요한 시스템 자원을 줄일수 있습니다.
2. 액티비티의 실행형식과 전환방식
보통 어플리케이션은 여러 종류의 사용자 화면을 가집니다. 예를 들어, 전화걸기 어플리케이션은
시작 시에 전화번호를 입력할 수 있는 화면을 제공하고 번호 입력 후 Send 버튼을 누르면 통화
화면으로 전환됩니다. 그리고 통화가 끝나면 재입력을 선택하거나 종료를 선택할 수 있는 화면을
제공합니다.
안드로이드 어플리케이션에서는 이런 사용자 화면을 보통 액티비티 컴포넌트로 구성하게 됩니다.
위의 예처럼 화면이 세개라면 각 화면을 개별적인 액티비티로 구성하고 상황에 따라서 액티비티를
실행하고 전환하는 형태로 작업이 진행될 것입니다.
따라서 처음 실행되는 액티비티가 추가적인 기능을 필요로할 때 다른 액티비티를 실행할 수 있으며
이 때 자신은 대기상태가 되고, 새로 실행된 액티비티가 활성화되어 작업을 계속 진행하게 됩니다.
안드로이드 시스템은 액티비티의 전환으로 생기는 사항을 "back stack" 이라고 불리는 스택에 보관
하여 관리하고 프로그램이 상황을 인지할수 있도록 각 액티비티의 상태에 관련된 콜백 메소드를
호출하여 현재 해당 액티비티가 어떤 상태로 변화했는지 알려주게 됩니다.
이렇게 액티비티의 상황에 따라서 콜백함수가 호출되기 때문에 개발자는 필요한 콜백함수를 재정의
하여 액티비티 상태에 따라 필요한 작업을 추가할수 있습니다.
3. 액티비티의 생성
액티비티를 생성하기 위해서는 Activity 클래스에서 당신이 사용할 클래스를 상속해야 합니다.
public class MyActivity extends Activity {
// ... 생략 ...
}
그리고 액티비티가 자신의 생명주기에 따라 다양한 상태(생성, 중지, 재기동, 파괴, ...) 전환이 이루어
지기 때문에, 각 상태별로 자신이 해야할 작업을 정하고 각 상태에 해당하는 콜백 메소드를 재정의
해야 합니다. 해당 콜백 메소드는 액티비티의 상태가 바뀔때마다 시스템에서 자동으로 호출해주기
때문에 자신이 재정의한 콜백 메소드가 필요한 타이밍에 수행될 것입니다.
예를 들어, 액티비티의 생성시에 수행할 작업이 있다면 onCreate 메소드를 재정의하고 해당 메소드에
필요한 코드를 명시하면 됩니다.
public class MyActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 여기에 자신이 작업할 내용을 구성한다.
}
// ... 생략 ...
}
액티비티의 상태에 따른 콜백 메소드를 모두 재정의해야 하는것은 아닙니다. 자신이 필요한 콜백
메소드만 재정의해서 사용하면 됩니다. 하지만, onCreate 는 액티비티가 출력할 화면을 설정할 수
있는 유일한 시점이기 때문에 반드시 재정의 해야하는 메소드입니다. 즉, 아래와 같이 onCreate
메소드 내에 자신이 리소스상에 지정한 레이아웃을 명시하기위해 사용하는 setContentView 메소드는
생략할수 없는 기본 코드입니다.
public class MyActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); // main.xml 파일의 레이아웃을 이 액티비티에 적용
// 여기에 자신이 작업할 추가적인 내용을 구성한다.
}
// ... 생략 ...
}
만약 자신이 만든 어플리케이션 내에 정의한 액티비티를 시스템이 접근할 수 있도록 하고 싶다면
해당 어플리케이션의 프로젝트 폴더에 포함되어 있는 manifest 파일에 정의한 액티비티 클래스명을
명시해야 합니다. manifest 파일에는 여러가지 요소를 정의할 수 있는데 <application> - <activity>
요소에 android:name 속성을 추가하고 아래와 같이 자신의 액티비티 클래스명을 명시하면 됩니다.
<manifest ... 생략 ... >
<application ... 생략 ... >
<activity android:name=".MyActivity" />
... 생략 ...
</application>
... 생략 ...
</manifest>
보통 command-line 으로 "android create project ..." 명령어를 사용하여 프로젝트를 생성할 때
자신이 사용할 액티비티명을 명시하는데 생성된 프로젝트의 manifest 파일에는 자신이 명시한
액티비티명으로 위 형식의 내용이 자동으로 구성되어 있기때문에 별도의 작업을 하지 않아도 됩니다.
생성된 manifest 파일을 보면 <activity> 요소 아래에 <intent-filter> 요소가 추가로 명시되어 있는데
보통 <action>, <category> 요소가 존재합니다. <action> 요소는 프로그램의 엔트리를 명시한
것인데 "android.intent.action.MAIN" 이라고 되어 있으면 해당 어플리케이션의 "main" 엔트리 즉,
"main activity" 를 의미합니다. 그리고 <category> 요소는 시스템 어플리케이션 런쳐(launcher) 에
목록화 될 때 사용되어 집니다.
<activity android:name=".MyActivity" android:icon="@drawable/icon">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
당신이 만든 액티비티가 다른 어플리케이션에 의해서 활성화되는 것을 필요치 않는 경우( 자신의
어플리케이션 내에서만 해당 액티비티를 활성화시키고자 하는 경우)에는 <intent-filter> 요소를
사용하지 않으면 됩니다.
<intent-filter> 요소에는 <action>, <category> 요소 외에도 <data> 라는 요소도 명시할 수 있는데
이것은 추가적인 정보를 가지고 액티비티를 활성화하고 싶을 때 사용합니다. ( 예전의 command
line 과 유사한 방법입니다. )
4. 다른 액티비티 시작하기
어플리케이션의 어떤 액티비티에서 다른 액티비티를 시작시킬 때에는 인텐트(Intent) 를 생성하고
startActivity 메소드를 호출하면 됩니다. 그리고 생성될 인텐트에는 실행시키고자 하는 액티비티의
정보를 명시해주어야 하는데 이 때, 명시적인 액티비티의 정보를 이용하는 방법과 암시적인 정보를
사용하는 방법이 있습니다.
4.1 명시적인 정보 사용하기
동일한 어플리케이션 내에 존재하는 액티비티를 호출하거나 액티비티에 대한 정보를 알고 있고
반드시 해당 액티비티를 호출해야 할 때에는 액티비티의 클래스명을 사용하여 액티비티를 시작
시킵니다.
예를 들어 이메일을 전송하는 기능이 구현된 클래스가 있다고 가정하고 해당 액티비티 클래스의
이름이 MyEmailActivity 라고하면 아래와 같이 코드를 구성하여 해당 액티비티를 시작할 수
있습니다.
Intent act = new Intent(this, MyEmailActivity.class);
startActivity(act);
Intent 클래스의 생성자 중에서 위의 생성자를 사용할 때에는 첫번째 인자에 Intent 객체를 생성하여
사용하는 컨텍스트를 명시하고, 두번째 인자에 사용하고자 하는 컴포넌트 클래스를 명시해주어야
합니다.
4.2 암시적인 정보 사용하기
다른 액티비티를 시작시킬 때 어떤 액티비티를 사용할 것인지를 직접적으로 결정할 수 없는
경우가 있습니다. 예를 들어, 메일 보내기, 웹서치, 맵 등과 같은 기능은 다양한 어플리케이션이
존재하고 거기에 포함된 액티비티명도 서로 다릅니다. 자신의 어플리케이션에서 이메일 기능을
사용하고 싶은 경우, 해당 기기를 사용하는 사람이 어떤 이메일을 주로 사용하고 있는지 그리고
그 메일 시스템의 액티비티 이름이 무엇인지를 예측하기는 어렵습니다.
이러한 경우에는 액티비티 클래스명을 직접적으로 사용하지 않고, 자신이 원하는 행위를 명시하여
액티비티를 실행하는 방법을 사용합니다. 즉, "메일을 보내고 싶다" 와 같이 행위를 명시하면
안드로이드 시스템은 가장 최근에 사용된 메일 시스템의 액티비티를 실행시켜줍니다.
아래의 코드는 Intent 객체를 생성하고 이메일 전송 행위를 명시하여 안드로이드 시스템이 권장하는
이메일 전송 액티비티를 실행하는 예제코드입니다.
// 이메일 주소의 수만큼 to_array 의 배열을 생성하여, 배열에 이메일 주소 정보를 저장
String[] to_array;
// ... 생략 ...
// 이메일 전송 행위를 명시하여 이메일 전송관련 액티비티를 시작시킬 수 있는 인텐트 생성
Intent act = new Intent(Intent.ACTION_SEND);
// 이메일 주소 정보를 실행될 액티비티에 전달
act.putExtra(Intent.EXTRA_EMAIL, to_array);
// 액티비티 실행
startActivity(act);
위 코드에서 Intent 클래스의 생성자에는 어떤 행위를 수행할 것인지 명시합니다. 각 행위는
시스템에 상수값으로 미리 정의되어 있으며 ACTION_SEND 도 그 중에 하나입니다.
( 각 행위와 행위에 대한 구체적인 내용은 나중에 Intent 를 별도로 다루면서 설명하겠습니다.)
그리고 인텐트가 실행시킬 액티비티에 데이터를 전달하는 putExtra 메소드는 String[] 형 뿐만
아니라 int, double, float 등 여러가지 형을 전달할 수 있도록 오버로딩 되어 있습니다.
5. 시작시킨 액티비티에서 결과 값 얻기
종종 액티비티를 실행시키고 해당 액티비티를 수행한 후에 그 수행한 결과를 반환받아하는 경우가
있습니다. 예를 들어 사진을 찍는 액티비티를 실행했다면 사진찍기 행위를 수행한 결과로 찍은 사진
정보를 얻어오는 것이 이에 해당합니다. 이런 경우에는 액티비티를 실행할 때 사용했던 startActivity
메소드 대신 startActivityForResult 메소드를 사용하고, onActivityResult 메소드를 재정의 해주어야
합니다.
startActivityForResult 메소드에 의해 실행된 액티비티가 수행을 완료하면 onActivityResult 콜백
메소드가 안드로이드 시스템에 의해서 자동으로 호출됩니다. 이 때 onActivityResult 메소드의 인자로
액티비티의 수행 결과가 전달됩니다.
onActivityResult 콜백 메소드에 전달되는 인자는 총 3가지 이며, 각가의 의미는 아래와 같습니다.
① requestCode : startActivityForResult 메소드의 두번째 인자로 사용한 값이 그대로 전달됩니다..
따라서 여러개의 액티비티를 수행시킨 경우 이 값으로 어떤 액티비티의 결과값인지
구별합니다.
② resultCode : 실행 결과 값을 성공으로 받았는지 여부에 대한 값입니다.
③ data : 액티비티의 구체적인 실행 결과 값입니다.
아래의 코드는 액티비티를 실행하고 그 결과 값을 받는 것에 대한 간단한 예입니다.
private void startActivity() {
// 반환 값을 받을 수 있는 액티비티 혹은 액티비티의 종류를 명시하여 Intent 객체 생성
Intent intent = new Intent(...);
// 생성한 Intent 객체와 실행될 액티비티의 결과값과 함께 반환될 데이터 구분 코드를 명시한다.
startActivityForResult(intent, 1);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// 결과 값이 있고, 액티비티를 시작할 때 1로 설정해둔 결과값인 경우
if (resultCode == Activity.RESULT_OK && requestCode == 1) {
// 여기에 자신이 작업할 추가적인 내용을 구성한다.
}
}
6. 액티비티 종료하기
액티비티는 finish 메소드를 이용하여 종료할 수 있으며 startActivityForResult 메소드를 이용하여
실행시킨 액티비티는 해당 메소드의 두번째 인자에 명시한 값을 이용하여 finishActivity 메소드로
종료시킬 수 있습니다.
그러나 안드로이드 시스템이 액티비티들의 생명 주기를 알아서 관리해주기 때문에 액티비티를
종료시키는데에 그다지 신경쓰지 않아도 됩니다.

 

댓글