안드로이드 액티비티. (Android Activity)

2016. 8. 4. 10:22


1. 안드로이드 앱 UI 표시.

일반적으로 안드로이드 시스템에서 앱이 실행되면, 전체 화면에 앱의 UI가 표시되고, 사용자가 입력한 화면 터치 또는 버튼 터치 등의 이벤트에 따라 앱의 기능이 수행됩니다. 이 때, 앱의 기능이 동작하는 과정에서, 최초 화면에 표시된 UI의 내용이 일부 바뀌거나 새로운 UI가 화면의 전체 영역에 표시되기도 하죠.


"구글 메일 앱"을 예로 들어 앱 동작 과정을 도식화 해 보도록 하겠습니다.

안드로이드 앱 UI 표시


자, 위에서 기술한 앱 실행 및 동작 과정에서 일어나는 UI관련 세 가지 주요 활동을 콕 찝어볼까요?

  1. 앱이 실행되면, 전체 화면에 앱의 UI를 표시.
  2. 사용자가 입력한 화면 터치 또는 버튼 터치 등의 이벤트 처리.
  3. 새로운 UI를 화면의 전체 영역에 표시.

여기서 굳이 "세가지 주요 활동(activity)"이라는 단어를 사용한 이유는, 바로 안드로이드 Activity가 앱에서 그러한 역할을 담당하는 주체이기 때문입니다.


위에서 "활동"이라는 사전적 의미의 단어 사용은 저의 주관적인 선택입니다. 안드로이드 공식 홈페이지에서는 Activity를 "작업"으로 명시하고 있습니다. Activity를 이해함에 있어 단어 선택에 따른 혼동이 없으시길 바랍니다.


1.1 안드로이드 Activity

안드로이드 Activity는 화면에 표시되는 UI 구성을 위해 가장 기본이 되는 요소입니다. 안드로이드 앱은 화면에 UI를 표시하기 위해 최소 하나의 Activity를 가져야 하며, 앱 실행 시 지정된 Activity를 실행하여 사용자에게 UI를 표시하게 됩니다.


여러 예제에서 작성한 "MainActivity"가 바로 앱 실행 시 최초로 보여지는 Activity이며, 안드로이드 스튜디오에서 자동으로 생성되는 템플릿 코드에서 MainActivity가 최초 실행되도록 지정되어 있습니다. (반드시 MainActivity라는 이름이어야 하는 것은 아닙니다. 프로젝트 생성할 때 입력하는 설정에 의한 결정일 뿐이므로 개발자가 원하는 이름으로 지정할 수 있습니다.)


앱 실행 시 시작되는 Activity 정보는 "AndroidManifest.xml" 파일에서 확인할 수 있습니다.

안드로이드 액티비티 정보


아래는 Activity 클래스의 계층 구조입니다. android.app.Activity에서 상속된, 다양한 용도의 Activity가 존재하는 것을 확인할 수 있습니다.

안드로이드 액티비티 클래스


그리고 android.content.Context에서 상속된 것을 확인하시기 바랍니다. 이는 Activity 클래스가 android.content.Context의 기능들을 사용할 수 있다는 것을 의미합니다. 또한 android.content.Context가 인자로 사용되는 곳에 Activity 클래스의 참조가 사용될 수 있다는 뜻이기도 하죠.


Activity와 Context의 관계에 대한 예제는 추후 다른 예제를 통해 살펴보도록 하겠습니다.

1.2 Activity의 UI 표시

안드로이드 Activity가 화면에 UI를 표시하는 역할을 수행한다고 해서, 자체적인 그리기 기능이 실행되어 화면을 그리는 것이 아닙니다. 대신, View 또는 ViewGroup의 다양한 조합을 화면에 배치함으로써, UI를 표시하는 것이죠.


Activity가 화면에 표시할 UI는 Layout 리소스 XML 파일(R.layout.XXX)이거나, android.view.View에서 상속받은 클래스(TextView, Button, ...) 이어야 하며, setContentView() 함수를 통해 화면에 출력될 Layout 리소스 XML ID 또는 View 클래스를 지정할 수 있습니다. 이런 관점에서 보면 Activity는 화면에 UI(View 또는 ViewGroup으로 구성된)를 표시하기 위한 틀이라는 개념이 되겠네요.


아래는 템플릿 코드에 의해 생성되는, "R.layout.activity_main"을 UI로 표시하는 코드입니다.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        // 코드 계속 ...
    }

다음 코드는 TextView의 인스턴스를 하나 생성한 다음, Activity의 UI로 표시하는 예제입니다. (개념 이해를 위한 예제일 뿐, 일반적으로 거의 사용되지 않습니다.)

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        TextView textView = new TextView(this) ;
        textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 24) ;
        textView.setText("TEXT1") ;
        setContentView(textView) ;
    }

Empty 액티비티


1.3 Activity 실행.

현재 Activity에서 다른 Activity를 실행하는 방법은 startActivity()라는 함수를 호출하는 것입니다. 이름 그대로 "Activity를 시작(start)" 하는 함수죠. 그런데 Activity를 실행하는 방법과 관련하여 추가적으로 알아야 할 내용이 있습니다. 바로 Activity를 실행할 때, "어떠한 의도(Intent)를 가지고 Activity를 실행하는가"를 기술하는 과정이 필요하다는 것입니다.


의도(Intent)라고 하는 것은 아래와 같이 설명될 수 있겠네요. (다음에 나올 설명들이 다소 장황하게 느껴지더라도 양해 바랍니다.)



A라는 Activity를 실행하고자 한다.

만약 개발자가 앱 내에 A라는 Activity를 하나 만들고 이를 명시적으로(explicit) 실행하고자 한다면, "A라는 Activity를 실행"하려는 의도(Intent)를 가진다고 할 수 있습니다.

액티비티 명시적 실행


하지만 반드시 자신이 만든 Activity만을 실행 해야 하는(할수 있는) 것은 아닙니다. 다른 누군가가 이미 만들어 놓은 Activity를 실행하는 경우도 있죠. 예를 들어 아주 멋진 아이디어가 떠올라 "관리가 매우 편리한 전화번호부 앱"을 하나 만들었다고 가정해보죠. 표시된 전화번호 옆에 "전화걸기" 버튼을 배치한 다음, 버튼을 누르면 해당 전화번호로 전화를 거는 기능이 실행되도록 만드려고 합니다. 이 때, "전화번호부 앱" 내에 전화를 거는 기능을 위한 Activity를 새로 만들어야 할까요? 아니요. 그렇게 할 필요가 없습니다. 왜냐하면 안드로이드에서는 "전화걸기"를 위한 Activity가 이미 제공되고 있기 때문입니다. 앱 개발자가 할 일은 새로운 Activity를 만드는 것이 아니라, 시스템에 이미 설치된 "전화걸기" Activity가 실행되도록 만드는 것입니다.


위에서 A라는 Activity를 실행할 때는, A라는 이름을 정확하게 알고 명시적으로 실행할 수 있었습니다. 하지만 "전화걸기"를 위한 Activity는 직접 만든 것이 아니기 때문에 정확한 이름을 알지 못하죠. 따라서 명시적인 실행이 불가능합니다. 대신 다음처럼 목적을 기술하여 Activity를 실행할 수 있습니다.


"전화걸기"를 위한 Activity를 실행하고자 한다.

이런 경우, 대상이 명시적이지 않은 암묵적인(implicit) 의도(Intent)를 가지고 "전화걸기" Activity를 실행할 수 있습니다. "전화걸기를 수행(action)하는 Activity를 실행"하려는 의도로 말이죠.

액티비티 암시적 실행


1.3.1 Intent

위에서 Activity를 실행할 때 의도를 기술해야 한다고 했는데, 이를 위해 사용하는 것이 바로 Intent 클래스입니다. Intent는 사전적으로 "의도, 의향"이라는 의미를 가지고 있죠.

인텐트 의미


Intent가 사용되는 이유를 설명하기 위해 다소 글이 길어졌지만, Intent 클래스의 인스턴스를 생성하여 Activity를 실행하는 것은 매우 간단합니다.


위에서 예로 든, "A라는 Activity를 명시적으로 실행"하는 코드는 다음과 같습니다.

    Intent intent = new Intent(this, A.class) ;
    startActivity(intent) ;

암묵적인 실행 방법에 대한 코드는 다음과 같습니다.

    Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:010-999-9999"));
    startActivity(intent) ;

Intent에 대한 자세한 내용은 추후 다양한 예제를 통해 살펴보도록 하겠습니다.

1.4 Activity의 종료.

Activity가 실행된 후, 작업이 완료되어 해당 Activity를 종료하고자 한다면 finish() 함수를 호출하면 됩니다. 아니면 finishActivity() 함수를 호출하여 이전에 실행한 특정 Activity를 종료할 수도 있습니다.


하지만 구글에서는 이러한 함수의 직접적인 사용을 권장하지 않고 있습니다. 이는 안드로이드 시스템이 관리하는 Activity의 생명 주기에 영향을 줄 수 있기 때문입니다. 좀 더 자세한 내용은 관련 예제를 다룰 기회가 생기면 언급하도록 하겠습니다.

1.5 Activity 관리.

최초 Activity(예를 들면 MainActivity)가 실행되어 화면에 UI가 표시된 후에, 다른 Activity를 구성하여 사용할지 여부는, 전적으로 앱을 기획하는(또는 만드는) 기획자(또는 개발자)의 선택에 달려있습니다. 앱이 표시하고자 하는 내용과 사용 편의성 등을 고려하여 현재 Activity 내에서 내용을 갱신할지, 아니면 새로운 Activity를 실행할지 결정하면 되는 것이죠.


그런데 만약 새로 화면에 표시되는 UI 구성이 기존 Activity에 표시되는 내용과 완전히 구분되어 독립적으로 실행되고, "뒤로(Back) 가기" 버튼에 의해 기존 Activity 화면이 다시 표시되어야 하는 경우라면, 새로운 Activity로 만들 것을 권장합니다. 왜냐하면 안드로이드 시스템은 새로운 Activity를 실행하면서 기존에 실행 중이던 Activity를 "Back-Stack"이라는 곳에 자동으로 저장하고, "뒤로(Back) 가기" 버튼을 누르면 이전에 저장된 Activity를 Back-Stack에서 꺼내어 실행해주기 때문입니다. 물론 "뒤로(Back) 가기" 버튼이 눌려질 때 실행되고 있던 Activity는 화면에서 사라지고, 실행이 종료됩니다.

액티비티와 백스택


"Back-Stack"에서 "Stack"이라는 용어가 의미하는 자료구조를 떠올리면 알 수 있듯이, "Back-Stack"에 쌓이는 Activity는 LIFO(Last-In-First-Out) 구조로 관리됩니다.

2. 참고

.END.


ANDROID 프로그래밍/ACTIVITY , , , , , , , , ,

  1. 참위즈 흔적 남김

  2. 뽀따 답글 남김

  3. Blog Icon
    AnLyn

    세상에 이런 설명은 처음봅니다 ..
    이해가 쏙쏙 박혀서 글을 읽는 내내 존경과 감사한 마음으로 읽었습니다

  4. 과분한 칭찬글을 남겨주셨네요.
    존경을 받을만한 글은 아닌데...
    어쨌든 도움이 된 것 같아서 다행입니다.

    감사합니다.

  5. Blog Icon
    리무기

    감사합니다

  6. 찾아주셔서 감사합니다.

  7. Blog Icon

    비밀댓글입니다

  8. 음, 시스템 Top 윈도우(always on top)를 만드는 방법에 대해 질문하신 것 같은데요.

    아래 코드를 한번 참고해보세요.

    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
    WindowManager.LayoutParams.MATCH_PARENT,
    WindowManager.LayoutParams.MATCH_PARENT,
    WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
    PixelFormat.TRANSLUCENT);

    WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
    LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
    View myView = inflater.inflate(R.layout.my_view, null);
    myView.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
    Log.d(TAG, "touch me");
    return true;
    }
    });

    // Add layout to window manager
    wm.addView(myView, params);



    관련 내용은 "https://stackoverflow.com/questions/4481226/creating-a-system-overlay-window-always-on-top" 에서 참고하실 수 있습니다.

    정확히 찾으시는 내용이면 좋겠네요.

    감사합니다.

  9. Blog Icon

    비밀댓글입니다

  10. 도움이 되셨으면 좋겠습니다.

    방문해 주셔서 감사합니다!

  11. Blog Icon
    대학교 학생

    거짓말 아니고 sk** 대학교 자과캠 다니는데 모바일 앱 실습 수업보다 훨씬 설명 잘합니다. 2016년도 작성이라서 최근 글이 아니라는 것 빼고는 정말 대단하고 감사하네요....

  12. 에고. 과분한 칭찬글을 남겨주셨네요.

    저도 대학에서 몇년 강의를 해봤지만, 많은 사람들 앞에서 말하는 것, 게다가 잘 말하는 것, 그리고 말할 내용을 준비하는 것이 마냥 쉬운 건 아니더라고요. ^^

    전 그냥 재밌어서.. 이것 저것 시도하다보니, 좋은 모습으로 비춰지는 것 같습니다.

    어쨌든 칭찬글, 감사합니다.

  13. Blog Icon
    sgtJeong

    설명이 너무 좋아 정주행 시작합니다

  14. 정주행... 이라고 할만큼 내용이 많지 않아 도움 되실까 모르겠네요.

    부족하고 어설픈 내용이 많겠지만, 궁금한 점 있으면 언제든 질문글 남겨주세요. 최대한 올바른 답변 드릴 수 있도록 노력하겠습니다.

    감사합니다.

  15. Blog Icon
    사랑합니다

    그저빛..

  16. 그저 감사할 따름...

  17. Blog Icon
    서효석

    답글잘안남기는데 진짜 설명이 너무 좋아서 남겨요
    안드로이드 공부하는데 다들 설명이 찝찝하고 내부적인 작동원리를 몰라서
    힘들었는데 너무 좋네요 열심히 공부할게여 ㅠㅠ

  18. 아마, 그림이 첨부되어 있어서 조금 더 쉽게 느껴진 것이 아닌가 생각이 드네요.
    저도 내부적인 작동원리를 잘 모르는 건 비슷...... ㅜㅜ

    방문해 주셔서 감사합니다. ^^

  19. Blog Icon
    김범석

    정말 너무 감사합니다. 최고의 안드로이드 개발사이트 네요. 졸업작품 만드는데 정말 큰 도움이 됩니다... 시중에 나와있는 책보다 훨씬 낫네요.

  20. 답변이 늦어서 죄송합니다.

    블로그의 내용에 비해 과분한 칭찬글이네요. 부끄럽습니다.

    앞으로 더 좋은 내용 담을 수 있도록 노력하겠습니다.

    감사합니다.

  21. Blog Icon
    대박이네

    글 질도 역대급인데다가 모든 댓글에 답글 하나하나 다 다시네
    진짜 대단하시다

  22. 새로운 내용들을 정리해야 하는데,
    여유가 생기질 않네요.
    답글 남기는 것 조차 밀리는 경우가 많아 죄송할 따름입니다.

    조금 더 여유를 찾아서 많은 내용 올릴 수 있도록 노력하겠습니다.

    감사합니다.

  23. Blog Icon
    넘무

    자바 간신히 배우고 안드로이드 스튜디오 막 배울려는 쌩초보입니다
    인터넷에 좋은 글이 별로없었는데,
    설명 정말 잘해주시는 좋은 글 발견해서 정말 기분 좋습니다.
    안드로이드 스튜디오 강좌 정주행하겠습니다. 감사합니다

  24. 글이 많이 허접하여... 도움이 많이 될지 모르겠네요. 흠...

    차근차근 살펴보시고, 궁금한 내용 있으시면 언제든 질문글 남겨주세요.

    감사합니다.

  25. 이정도 퀄리티면 책을 쓰시는게...

  26. 이렇게 블로그를 쓰다보니, 책을 쓰는 건 더욱 더 힘들겠구나... 라는 생각이 드네요.

    칭찬글 남겨주셔서 감사합니다.

  27. Blog Icon
    대학생컴공

    아.. 진짜 감사해서 눈물이 다 날 지경입니다
    웬만한 책보다 훨씬 낫네요
    어떻게 블로그 글이 7판 인쇄된 안드로이드 책보다 이해가 잘 되는걸까요

    너무 감사드립니다
    보물 찾은 기분이에요
    이번달에 블로그 정주행 해서 안드로이드 마스터 해야겠어요

  28. 이 블로그를 정주행한다고,
    안드로이드를 마스터할 수는 없는 것이 확실합니다. ㅜㅜ
    그닥 볼 내용이 별로 없어요.. ㅜㅜ

    그래도 최대한 많은 도움이 되셨으면 좋겠네요.

    감사합니다.

  29. Blog Icon
    노마드

    android.content.Context에서 상속된 것을 확인하시기 바랍니다. 이는 Activity 클래스가 android.content.Context의 기능들을 사용할 수 있다는 것을 의미합니다. 또한 android.content.Context가 인자로 사용되는 곳에 Activity 클래스의 참조가 사용될 수 있다는 뜻이기도 하죠.

    이 내용에 대해서 부가적인설명이 가능할지요?
    상속되는것을 알겠는데..content.context 기능은 어떤것이 있으며,,Activity가 참조가 된다는 의미가 잘 안되네요

  30. 흠.. 자바, 즉, 객체지향 프로그래밍에 대해서 어느 정도의 이해도를 가지고 계신지 몰라서, 어떻게 설명해야 할지 감을 못잡겠네요.

    클래스, 상속, 등등 객체지향 개념을 이해하고 있으면 Context와 Activity의 관계를 어렵지 않게 이해할 수 있을텐데요.

    객체지향에 대해 하나하나 설명하자면, 지면이 모자라도 한참 모자라니, 많은 설명은 생략하고요.

    Activity의 부모가 Context라는 것의 의미는, 아주 간단하게, Context가 제공하는 기능을 Activity가 제공한다는 것입니다. 자식은 부모의 속성을 물려받으니까요.

    그리고 안드로이드에서 Context는 매우 중요한 역할을 하는 클래스입니다. Context에 대한 안드로이드 개발문서(https://developer.android.com/reference/android/content/Context)에서도 알 수 있듯이,
    App의 리소스 또는 클래스 접근, App 레벨 동작(activity 실행, broadcasting, intent 수신) 호출하는데 사용됩니다.

    조금 더 구체적으로,
    레이아웃을 inflate할 때 사용하는 시스템 서비스를 호출하거나, 뷰를 새로 생성할 때도 Context를 사용할 수 있죠.

    그럼, 안드로이드에서는, 이렇게 중요한 기능을 제공하는 Context를 개발자가 어떤 방법을 통해 사용할 수 있을까요?

    바로 Activity를 통해서입니다.
    서두에 말했듯이, Activity가 Context를 상속했기 때문입니다.

    답변이 되셨는지 모르겠네요.

    추가적으로 궁금한 내용이 있으면 질문글 남겨주세요.

    감사합니다.

  31. Blog Icon
    급한불꽃

    좋은 글 감사합니다.

  32. 방문해 주셔서 감사합니다.

  33. Blog Icon
    James

    좋은글 감사합니다.:)

  34. 감사합니다.

  35. Blog Icon
    김용환

    안녕하세요 정말 좋은 글 감사합니다.
    궁금한 점이 있어 글을 남깁니다.
    지금 막 안드로이드를 공부한지 얼마 안됐습니다.
    지금 1번 액티비티에서 블루투스 연결을 하고 데이터 까지 받아 파싱까지 완료한 상태입니다.
    다음으로 2번 액티비티에서 파싱된 데이터를 각각의 testView에 표시하고 싶은데 여기서 막혔습니다. ㅠㅠ
    1번 액티비티에 데이터 값은 전역변수로 선언된 상태인데 해결방법이 있을까 하고 글 남겨봅니다...

  36. 데이터를 주기적으로 받아와야 하는데
    1번 액티비티에서 블루투스 데이터가 들어오면 2번 액티비티에서 값이 바뀌게 할 수 있는지 궁금합니다.

  37. 답글 바로 달아드리지 못해 죄송합니다.
    최근에 블로그에 거의 신경을 쓰지 못했네요.

    원하시는 답은 찾으셨는지 모르겠네요.

    만약 답을 못찾으셨다면 다시 질문글 남겨주세요. 도움드릴 방법을 찾아보겠습니다.

    늦게 답을 달아드려서 죄송합니다.