Application Fundamentals

来源:互联网 发布:linux中安装idea 编辑:程序博客网 时间:2024/05/22 13:44

Application Fundamentals


Android applications are written in the Java programming language. The compiled Java code along with any data and resource files required by the application is bundled by the aapt tool into an Android package, an archive file marked by an .apk suffix. This file is the vehicle for distributing the application and installing it on mobile devices; it's the file users download to their devices. All the code in a single .apk file is considered to be one application.

안드로이드 애플리케이션은 Java 프로그래밍 언어로 작성된다. 컴파일된 Java 코드 - 애플리케이션에 필요한 임의의 데이터와 리소스 파일과 함께 ? 는 SDK에 존재하는 aapt 유틸리티에 의해 안드로이드 패키지로 묶여지며, 이렇게 하나로 압축된 아카이브archive 파일에는 .apk 접미사가 부쳐진다. 이 파일은 모바일 디바이스에 안드로이드 애플리케이션을 배포하고 설치하기 위한 수단이다(사용자들이 자신의 모바일 디바이스에 다운로드하게 되는 파일이 바로 이 파일이다). 하나의 .apk 파일 안에 있는 모든 코드는 하나의 애플리케이션으로 간주된다.   

In many ways, each Android application lives in its own world:

다양한 방법으로 각각의 안드로이드 애플리케이션은 그것 자신의 세계 내에서in its own world 존속한다.

  • By default, every application runs in its own Linux process. Android starts the process when any of the application's code needs to be executed, and shuts down the process when it's no longer needed and system resources are required by other applications.
  • Each process has its own Java virtual machine (VM), so application code runs in isolation from the code of all other applications.
  • By default, each application is assigned a unique Linux user ID. Permissions are set so that the application's files are visible only that user, only to the application itself although there are ways to export them to other applications as well.
  • 디폴트로 모든 애플리케이션은 자신의 리눅스 프로세스 내에서 실행된다. 안드로이드는 임의의 애플리케이션 코드가 실행될 필요가 있을 때 그 프로세스를 시작시키며, 그것이 더 이상 필요치 않고 다른 애플리케이션이 시스템 자원을 요구할 때 그 프로세스를 종료시킨다shuts down.
  • 각각의 프로세스는 자기 자신의 Java 가상머신을 가진다. 그러므로 애플리케이션 코드는 다른 모든 애플리케이션 코드와는 격리되어 실행된다.
  • 디폴트로 각각의 애플리케이션에는 고유한 리눅스 유저user ID가 부여된다. 애플리케이션을 구성하는 파일들은 해당 사용자와 해당 애플리케이션 그 자신에게만 보여지도록 퍼미션permission이 설정된다 - 비록, 다른 애플리케이션에게도 그 파일을 보여줄 방법이 있기는 하지만.

It's possible to arrange for two applications to share the same user ID, in which case they will be able to see each other's files. To conserve system resources, applications with the same ID can also arrange to run in the same Linux process, sharing the same VM.

두 개의 애플리케이션에 대해 동일한 유저user ID를 공유할 수 있도록 배치하는 것이 가능하다. 그런 경우에 두 개의 애플리케이션은 각자 다른 애플리케이션의 파일을 볼 수 있을 것이다. 시스템 자원을 절약하기 위해 동일한 ID를 가지는 애플리케이션은 또한 동일한 리눅스 프로세스 안에서 실행되도록 배치되며, 동일한 가상머신을 공유한다.

Application Components

A central feature of Android is that one application can make use of elements of other applications (provided those applications permit it). For example, if your application needs to display a scrolling list of images and another application has developed a suitable scroller and made it available to others, you can call upon that scroller to do the work, rather than develop your own. Your application doesn't incorporate the code of the other application or link to it. Rather, it simply starts up that piece of the other application when the need arises.

안드로이드의 중심 특징은 하나의 애플리케이션이 다른 애플리케이션의 엘리먼트를(단, 그 엘리먼트의 애플리케이션이 사용을 허가하는 조건하에서) 사용할 수 있다는 것이다. 예를 들어 만약 여러분의 애플리케이션이 이미지 스크롤 리스트를 표시할 필요가 있고, 다른 애플리케이션이 그에 알맞은 스크롤러scroller를 개발했고 또한 그것을 다른 애플리케이션이 사용할 수 있도록 만들어 놓았다면, 여러분은 자신의 스크롤러를 별도로 개발하지 않고 이미 있는 스크롤러가 그 작업을 수행할 수 있도록 호출할 수 있다. 이를 위해, 여러분의 애플리케이션은 다른 애플리케이션의 코드를 통합하거나 링크하지는 않는다. 오히려 그것이 필요할 때 다른 애플리케이션 내에 있는 해당 영역piece을 간단하게 구동start-up시킬 수 있다.

For this to work, the system must be able to start an application process when any part of it is needed, and instantiate the Java objects for that part. Therefore, unlike applications on most other systems, Android applications don't have a single entry point for everything in the application (no main() function, for example). Rather, they have essential components that the system can instantiate and run as needed. There are four types of components:

이런 작업을 위해서는, 어떤 애플리케이션의 특정 영역이 필요해 질 때 시스템은 애플리케이션 프로세스를 시작할 수 있어야 하며, 그리고 그 영역에 대한 Java 오브젝트를 인스턴스화 할 수 있어야 한다. 그러므로 다른 대부분 시스템에서의 애플리케이션과는 달리, 안드로이드는 애플리케이션 안의 모든 것들에 대한 하나의 시작점entry point을 가지지 않는다(예를 들어 main() 함수가 없음). 대신에, 안드로이드 애플리케이션에는 시스템이 그것을 필요로 할 때 인스턴스화하고 실행할 수 있는 기본적인 컴포넌트들이 존재한다. 안드로이드 애플리케이션에는 네 가지 유형의 컴포넌트가 존재한다.

Activities
An activity presents a visual user interface for one focused endeavor the user can undertake. For example, an activity might present a list of menu items users can choose from or it might display photographs along with their captions. A text messaging application might have one activity that shows a list of contacts to send messages to, a second activity to write the message to the chosen contact, and other activities to review old messages or change settings. Though they work together to form a cohesive user interface, each activity is independent of the others. Each one is implemented as a subclass of the Activity base class.

An application might consist of just one activity or, like the text messaging application just mentioned, it may contain several. What the activities are, and how many there are depends, of course, on the application and its design. Typically, one of the activities is marked as the first one that should be presented to the user when the application is launched. Moving from one activity to another is accomplished by having the current activity start the next one.

Each activity is given a default window to draw in. Typically, the window fills the screen, but it might be smaller than the screen and float on top of other windows. An activity can also make use of additional windows for example, a pop-up dialog that calls for a user response in the midst of the activity, or a window that presents users with vital information when they select a particular item on-screen.

The visual content of the window is provided by a hierarchy of views objects derived from the base View class. Each view controls a particular rectangular space within the window. Parent views contain and organize the layout of their children. Leaf views (those at the bottom of the hierarchy) draw in the rectangles they control and respond to user actions directed at that space. Thus, views are where the activity's interaction with the user takes place. For example, a view might display a small image and initiate an action when the user taps that image. Android has a number of ready-made views that you can use including buttons, text fields, scroll bars, menu items, check boxes, and more.

A view hierarchy is placed within an activity's window by the Activity.setContentView() method. The content view is the View object at the root of the hierarchy. (See the separate User Interface document for more information on views and the hierarchy.)

액티비티는 사용자가 착수할 수 있는 하나의 포커스된 시도에 대한 비쥬얼visual 사용자 인터페이스를 나타낸다. 예를 들어 액티비티는 사용자들이 선택할 수 있는 메뉴 아이템 리스트를 나타내거나, 사진과 함께 그것의 캡션caption을 나타낼 수도 있다. 텍스트 메시징 애플리케이션은, 메시지를 보내기 위한 컨택contact 리스트를 보여주는 하나의 액티비티와 선택된 컨택contact에 대해 메시지를 작성하는 두 번째 액티비티, 그리고 오래된 메시지들을 다시 보거나 설정을 바꾸기 위한 나머지 액티비티를 가질 수 있다. 이들 액티비티들은 하나의 결합된 사용자 인터페이스를 형성하기 위해 함께 동작함에도 불구하고, 각각의 액티비티는 다른 액티비티와 독립되어 있다. 각각의 액티비티는 Activity 베이스 클래스의 서브클래스로 구현된다.

하나의 애플리케이션은 단지 한 개의 액티비티로 구성될 수도 있으며, 또한 앞서 간단히 언급했던 텍스트 메시징 애플리케이션처럼 몇 개의 액티비티를 포함하고 있을 수도 있다. 당연히 애플리케이션을 구성하는 액티비티가 무엇인지 그리고 얼마나 많은 액티비티가 그곳에 있는 지는, 그 애플리케이션과 그것의 디자인에 의존적이다. 일반적으로 액티비티들 중 하나에는, 그 애플리케이션이 시작됐을 때 사용자에게 보여질 수 있도록 첫 번째 액티비티라는 표시가 붙게 된다. 하나의 액티비티에서 또 다른 액티비티로의 이동은, 현재 액티비티가 다음번 액티비티를 시작함으로써 이루어진다.

각각의 액티비티에는 그리기draw가 가능한 하나의 디폴트 윈도우가 부여된다. 일반적으로 윈도우는 스크린 전체를 채우지만 스크린보다 작을 수도 있고, 다른 윈도우 그 위에 떠있을 수도 있다. 하나의 액티비티는 또한 추가적인 윈도우를 사용할 수 있다 - 예를 들어 액티비티의 한복판에서 사용자 응답을 요청하는 팝업 다이얼로그dialog라든지, 또는 스크린 상에서 특정 아이템을 선택할 때 사용자에게 필수적인 정보를 표시하는 윈도우가 그것이다.

윈도우 내의 비쥬얼visual 컨텐트는 - 베이스 뷰 클래스로부터 파생된 오브젝트들인 - 뷰View들의 계층구조hierarchy에 의해 만들어진다. 각각의 뷰는 윈도우 내의 하나의 특정 직사각형 영역을 제어한다. 부모Parent 뷰은 그것들의 자식들children의 레이아웃을 포함하고 구조화한다. 계층구조의 최하단의 뷰는 그것들이 제어하는 직사각형 영역을 그리며, 그 영역에 국한된 사용자 액션에 대한 책임을 진다. 이와 같이 뷰는 액티비티와 사용자 간의 상호작용이 이루어지는 영역이다. 예를 들어 하나의 뷰는 작은 이미지를 보여줄 수도 있고, 사용자가 그 이미지를 만질 때 특정 액션을 일으킬 수도 있다. 안드로이드는 여러분이 사용할 수 있는 - 버튼, 텍스트 필드, 스크롤 바, 메뉴 아이템, 체크 박스, 그리고 추가적인 것들을 포함해서 - 이미 만들어진 많은 뷰를 가지고 있다.

뷰 계층구조는 Activity.setContentView() 메쏘드에 의해 액티비티의 윈도우 내에 위치하게 된다. 그 컨텐트 뷰는 그 계층구조의 최상위에 있는 뷰view 오브젝트이다(뷰와 계층구조에 대한 더 많은 정보에 대해서는, 3장. “사용자 인터페이스”를 보라).

Services
service doesn't have a visual user interface, but rather runs in the background for an indefinite period of time. For example, a service might play background music as the user attends to other matters, or it might fetch data over the network or calculate something and provide the result to activities that need it. Each service extends the Service base class.

A prime example is a media player playing songs from a play list. The player application would probably have one or more activities that allow the user to choose songs and start playing them. However, the music playback itself would not be handled by an activity because users will expect the music to keep playing even after they leave the player and begin something different. To keep the music going, the media player activity could start a service to run in the background. The system would then keep the music playback service running even after the activity that started it leaves the screen.

It's possible to connect to (bind to) an ongoing service (and start the service if it's not already running). While connected, you can communicate with the service through an interface that the service exposes. For the music service, this interface might allow users to pause, rewind, stop, and restart the playback.

Like activities and the other components, services run in the main thread of the application process. So that they won't block other components or the user interface, they often spawn another thread for time-consuming tasks (like music playback). See Processes and Threads, later.

서비스는 비쥬얼한 사용자 인터페이스를 가지지 않는다. 하지만 오히려 정해지지 않은 시간동안 백그라운드background에서 실행된다. 예를 들어 서비스는 사용자가 다른 일에 주의를 기울이는 동안에 백그라운드 음악을 재생할 수 있다. 또한 그것은 네트워크 상에서 데이터를 가져오거나, 또는 어떤 것을 계산해서 그 결과를 필요로 하는 액티비티에게 제공할 수도 있다. 각각의 서비스는 Service 베이스 클래스를 확장extend한다.

이것의 기본적인 예제는 재생 목록에서 음악을 재생하는 미디어 플레이어이다. 아마도 그 플레이어 애플리케이션은 사용자에게 음악을 선택할 수 있게 하고 그것을 재생하는, 하나 또는 그 이상의 액티비티를 가지고 있을 수 있다. 하지만 음악 재생 그 자체는 액티비티에 의해 제어되어서는 안된다. 왜냐하면 사용자가 플레이어 화면을 벗어난 후, 다른 어떤 것을 실행한 이후에도 그 음악이 계속 재생되길 기대할 것이기 때문이다. 음악이 계속 재생되게 하기 위해, 미디어 플레이어 액티비티는 백그라운드에서 실행되는 하나의 서비스를 시작할 수 있다. 시스템은 심지어 그 서비스를 시작했던 액티비티가 스크린에서 사라진 후 조차도 음악 재생 서비스를 계속 유지할 것이다.

실행되고 있는 서비스에 접속connect하는 것(바인드하는 것)이 (그리고 만약 아직 실행되지 않았다면, 그 서비스를 실행하는 것이) 가능하다. 그것에 접속되어 있는 동안, 여러분은 그 서비스가 제공하는 인터페이스를 통해 서비스와 커뮤니케이션할 수 있다. 음악 서비스의 경우, 이러한 인터페이스는 사용자에게 음악을 일시 멈추고, 되감고, 정지시키고, 다시 재생하는 것을 가능하게 한다.

액티비티와 다른 컴포넌트 처럼, 서비스도 애플리케이션 프로세스의 메인 쓰레드 내에서 실행된다. 그러므로 서비스가 다른 컴포넌트 또는 사용자 인터페이스에 의해 방해받지 않도록 하기 위해서 음악 재생같이 시간을 요하는 작업들을 위해서는 종종 또 다른 쓰레드를 만들어서 작동시킨다. 이 부분에 대해서는 추후 언급되는 “프로세스와 쓰레드”를 보라.

Broadcast receivers
broadcast receiver is a component that does nothing but receive and react to broadcast announcements. Many broadcasts originate in system code for example, announcements that the timezone has changed, that the battery is low, that a picture has been taken, or that the user changed a language preference. Applications can also initiate broadcasts for example, to let other applications know that some data has been downloaded to the device and is available for them to use.

An application can have any number of broadcast receivers to respond to any announcements it considers important. All receivers extend the BroadcastReceiver base class.

Broadcast receivers do not display a user interface. However, they may start an activity in response to the information they receive, or they may use the NotificationManager to alert the user. Notifications can get the user's attention in various ways flashing the backlight, vibrating the device, playing a sound, and so on. They typically place a persistent icon in the status bar, which users can open to get the message.

브로드캐스트 리시버는 아무 것도 하지 않는 컴포넌트지만, 브로드캐스트 공지announcement를 수신하고 응답한다. 많은 브로드캐스트는 시스템 코드에서 발생된다 - 예를 들어 시간대가 바뀌었다, 배터리가 부족하다, 사진이 찍혔다, 사용자가 언어 설정을 바꾸었다 등이 그것이다. 애플리케이션 또한 브로드캐스트를 발생시킬 수 있다 - 예를 들어 다른 애플리케이션에게 어떤 데이터가 디바이스에 다운로드되었고, 그것들이 그것을 사용하는 것이 가능하다는 것을 알게 할 수 있다.

애플리케이션은 중요하다고 여겨지는 임의의 공지에 응답할 수 있는 임의의 수의 브로드캐스트 리시버를 가질 수 있다. 모든 리시버는 Broadcast Receiver 베이스 클래스를 확장extend한다.

브로드캐스트 리시버는 사용자 인터페이스를 보여주지 않는다. 하지만 그것이 수신한 정보에 응답하는 액티비티를 시작하거나, 또는 사용자에게 알려주기 위해 노티피케이션 매니저notification manager를 사용할 수 있다. 노티피케이션은 여러가지 방법으로 사용자의 주의를 끌 수 있다 - 배경조명 발광, 디바이스 진동, 사운드 재생 등이 있다. 그것은 일반적으로 상태바status bar 내에 아이콘을 상주시켜 놓으며, 사용자는 그 메시지를 얻기 위해 그것을 오픈할 수 있다.

Content providers
content provider makes a specific set of the application's data available to other applications. The data can be stored in the file system, in an SQLite database, or in any other manner that makes sense. The content provider extends the ContentProvider base class to implement a standard set of methods that enable other applications to retrieve and store data of the type it controls. However, applications do not call these methods directly. Rather they use a ContentResolver object and call its methods instead. A ContentResolver can talk to any content provider; it cooperates with the provider to manage any interprocess communication that's involved.

See the separate Content Providers document for more information on using content providers.

컨텐트 프로바이더는 다른 애플리케이션에게 유용한 특정 애플리케이션의 데이터 집합set을 만든다. 그 데이터는 파일 시스템 내, SQLite 데이터베이스 내, 또는 의미있는 다른 어떤 방식으로 저장될 수도 있다. 컨텐트 프로바이더는 자신이 제어하는 타입의 데이터를 다른 애플리케이션이 얻고 저장할 수 있도록 하게 하는 표준 메쏘드 집합set을 구현하기 위해, ContentProvider 베이스 클래스를 확장extend한다. 하지만 애플리케이션은 이러한 메쏘드를 직접적으로 호출하지 않는다. 대신 애플리케이션은 컨텐트 리졸버ContentResolver 오브젝트를 사용하여 그것의 메쏘드를 호출한다. 컨텐트 리졸버는 어떤 컨텐트 프로바이더와도 대화할 수 있으며, 그것과 관련된 임의의 프로세스 간 통신(IPC, interprocess communication)을 관리하기 위해 프로바이더와 협력한다. 컨텐트 프로바이더 사용법에 관한 더 많은 정보는 7장. 컨텐트 프로바이더를 보라.

Whenever there's a request that should be handled by a particular component, Android makes sure that the application process of the component is running, starting it if necessary, and that an appropriate instance of the component is available, creating the instance if necessary.

특정 컴포넌트에 의해 처리되어야 하는 요청이 있을 때마다, 안드로이드는 그 컴포넌트의 애플리케이션 프로세스가 실행running되도록 하며, 필요하다면 그것을 시작start하기도 한다. 그리고 그 컴포넌트에 맞는 인스턴스가 사용가능해지도록 하며, 필요하다면 그 인스턴스를 생성도 한다.

Activating components: intents

Content providers are activated when they're targeted by a request from a ContentResolver. The other three components activities, services, and broadcast receivers are activated by asynchronous messages called intents. An intent is an Intent object that holds the content of the message. For activities and services, it names the action being requested and specifies the URI of the data to act on, among other things. For example, it might convey a request for an activity to present an image to the user or let the user edit some text. For broadcast receivers, the Intent object names the action being announced. For example, it might announce to interested parties that the camera button has been pressed.

컨텐트 프로바이더content provider는 컨텐트 리졸버content resolver 요청의 대상target이 될 때 활성화된다. 하지만 다른 세 가지 컴포넌트, 즉 액티비티, 서비스, 그리고 브로드캐스트 리시버는 인텐트intent라 불리는 비동기적인 메시지에 의해 활성화된다. 인텐트는 컨텐트 메시지를 보유하고 있는 인텐트Intent 오브젝트다. 인텐트는 액티비티와 서비스에 대해서, 그것에게 요청되는requested 액션을 가리키고 그 액션이 처리해야 하는 데이터의 URI를 나머지 다른 것들과 함께 명시한다. 예를 들어 인텐트는 어떤 액티비티가 사용자에게 이미지를 보여주도록 하거나, 또는 사용자가 어떤 텍스트를 편집할 수 있도록 하는 요청을 전달할 수 있다. 인텐트 오브젝트는 브로드캐스트 리시버에 대해서는, 공지되는announced 액션을 가리킨다. 예를 들어 그것은 카메라 버튼이 눌려졌다는 사실에 관심을 갖는 관계자party에게 공지될 수 있다.

There are separate methods for activiating each type of component:

각각의 컴포넌트 타입을 활성화하기 위한 별도의 메쏘드가 있다.

  • An activity is launched (or given something new to do) by passing an Intent object to Context.startActivity() or Activity.startActivityForResult(). The responding activity can look at the initial intent that caused it to be launched by calling its getIntent() method. Android calls the activity's onNewIntent() method to pass it any subsequent intents.

    One activity often starts the next one. If it expects a result back from the activity it's starting, it calls startActivityForResult() instead of startActivity(). For example, if it starts an activity that lets the user pick a photo, it might expect to be returned the chosen photo. The result is returned in an Intent object that's passed to the calling activity's onActivityResult()method.

  • A service is started (or new instructions are given to an ongoing service) by passing an Intent object to Context.startService(). Android calls the service's onStart() method and passes it the Intent object.

    Similarly, an intent can be passed to Context.bindService() to establish an ongoing connection between the calling component and a target service. The service receives the Intent object in an onBind() call. (If the service is not already running, bindService() can optionally start it.) For example, an activity might establish a connection with the music playback service mentioned earlier so that it can provide the user with the means (a user interface) for controlling the playback. The activity would call bindService() to set up that connection, and then call methods defined by the service to affect the playback.

    A later section, Remote procedure calls, has more details about binding to a service.

  • An application can initiate a broadcast by passing an Intent object to methods like Context.sendBroadcast()Context.sendOrderedBroadcast(), and Context.sendStickyBroadcast() in any of their variations. Android delivers the intent to all interested broadcast receivers by calling their onReceive() methods.

  • 액티비티는 인텐트 오브젝트를 Context.startActivity() 또는 Activity.startActivityForResult()에 파라미터로 전달함으로써 런치된다(또는 새로 처리할 어떤 것이 주어진다). 이것에 응답하는 액티비티는 getIntent() 메쏘드를 호출함으로써, 그것을 런치하도록 한 초기 인텐트를 볼 수 있다. 안드로이드는 그 액티비티에게 그 이후 이어지는 임의의 인텐트를 전달하기 위해서는, 그 액티비티의 onNewIntent() 메쏘드를 호출한다.

    하나의 액티비티는 흔히 그 다음번 액티비티를 시작시킨다. 만약 그것이 자신이 시작시킨 액티비티로부터 결과를 리턴받고자 한다면, 그것은 start Activity() 대신에 startActivityForResult()를 호출해야 한다. 예를 들어 어떤 액티비티가 사용자에게 사진을 선택하게 하는 액티비티를 시작시킨다면, 그 액티비티는 사용자가 선택한 사진을 리턴받기를 원할 수 있다. 그 결과는, 액티비티의 onActivityResult() 메쏘드가 호출되는 곳에 전달되는 인텐트 오브젝트 내에서 리턴된다.

  • 서비스는 Context.startService()에 인텐트 오브젝트를 파라미터로 전달함으로써 시작된다(또는 이미 실행중인 서비스에게 새로운 명령이 주어진다). 안드로이드는 서비스의 onStart() 메쏘드를 호출하고 그곳에 인텐트 오브젝트를 전달한다.

    유사한 방식으로, 인텐트는 호출하는 컴포넌트와 타겟target 서비스 간의 지속적인 연결을 확립하기 위해 Context.bindService()에 파라미터로 전달될 수도 있다. 그리고 해당 서비스는 onBind()가 호출되는 곳에서 그 인텐트 오브젝트를 전달받는다(만약 서비스가 아직 실행중이 아니라면, bindService()는 선택적으로 서비스를 시작시킬 수 있다). 예를 들어 액티비티는 앞서 언급했듯이 음악 재생을 제어하는 수단(즉, 사용자 인터페이스)을 사용자에게 제공하기 위해 음악 재생 서비스와의 연결을 확립할 수 있다. 액티비티는 그러한 커넥션을 셋업하기 위해 bindService()를 호출할 것이며, 그런 다음 음악 재생에 관여하기 위해 서비스에 정의된 메쏘드를 호출하게 된다.

    나중에 나오는 원격 프로시저 호출 섹션은 서비스에 바인딩하는 것에 대해 좀 더 상세히 설명한다.

  • 애플리케이션은 Context.sendBroadcast(), Context.sendOrderedBroadcast(), 그리고 Context.sendStickyBroadcast() 같이 다양하게 변형된 메쏘드에 인텐트 오브젝트를 전달함으로써 브로드캐스트broadcast를 만들어낼 수 있다. 안드로이드는 이것에 관심을 갖는 모든 브로드캐스트 리시버에게 그들의 onReceive() 메쏘드를 호출해 줌으로써 그 인텐트를 전달한다.

For more on intent messages, see the separate article, Intents and Intent Filters.

인텐트 메시지에 대한 보다 많은 정보는 5장. “인텐트와 인텐트 필터”를 보라.

Shutting down components

A content provider is active only while it's responding to a request from a ContentResolver. And a broadcast receiver is active only while it's responding to a broadcast message. So there's no need to explicitly shut down these components.

컨텐트 프로바이더는 컨텐트 리졸버의 요청에 응답하는 동안에만 활성화되어 있다. 그리고 브로드캐스트 리시버도 브로드캐스트 메시지에 응답하는 동안에만 활성화되어 있다. 그러므로 이러한 컴포넌트는 명시적으로 종료시켜야 할 필요가 없다.

Activities, on the other hand, provide the user interface. They're in a long-running conversation with the user and may remain active, even when idle, as long as the conversation continues. Similarly, services may also remain running for a long time. So Android has methods to shut down activities and services in an orderly way:

반면, 액티비티는 사용자 인터페이스를 제공한다. 이것은 사용자와 오랜시간 동안 대화를 하며 활성화 상태로 남아 있다. 심지어는 대화가 지속될 수 있는 한, 그것이 사용되지 않는idle 상태에도 활성화 상태로 남는다. 유사하게, 서비스 또한 오랜 시간동안 실행 상태로 남아 있다. 그래서 안드로이드는 어떤 규칙적인 방식으로 액티비티와 서비스를 종료시키기 위한 메쏘드를 가지고 있다.

  • An activity can be shut down by calling its finish() method. One activity can shut down another activity (one it started with startActivityForResult()) by calling finishActivity().
  • A service can be stopped by calling its stopSelf() method, or by calling Context.stopService().
  • 액티비티는 finish() 메쏘드의 호출을 통해 스스로 종료될 수 있다. 그리고 finishActivity()를 호출함으로써, 다른 액티비티(startActivityForResult()를 사용해서 시작된 액티비티)를 종료시킬 수도 있다.
  • 서비스는 stopSelf() 메쏘드의 호출이나 Context.stopService()를 호출함으로써 종료될 수 있다.

Components might also be shut down by the system when they are no longer being used or when Android must reclaim memory for more active components. A later section, Component Lifecycles, discusses this possibility and its ramifications in more detail.

또한, 컴포넌트는 그것이 더 이상 사용되지 않을 때, 또는 안드로이드가 더 많은 활성화된 컴포넌트를 위해 메모리를 회수해야 할 때 시스템에 의해 종료될 수 있다. 이후에 나오는 “컴포넌트 생명주기” 섹션에서 그것이 일어나는 경우를 좀 더 상세히 논의할 것이다.

The manifest file

Before Android can start an application component, it must learn that the component exists. Therefore, applications declare their components in a manifest file that's bundled into the Android package, the .apk file that also holds the application's code, files, and resources.

안드로이드는 애플리케이션의 컴포넌트를 시작하기 전에, 컴포넌트의 존재를 인식해야 한다. 그러므로 애플리케이션은 매니페스트 파일에 그것들의 컴포넌트를 선언한다. 그리고 그 매니페스트 파일은 안드로이드 패키지, .apk 파일 내에 포함된다. 이 패키지는 애플리케이션의 코드, 파일, 리소스 또한 보유하고 있다.

The manifest is a structured XML file and is always named AndroidManifest.xml for all applications. It does a number of things in addition to declaring the application's components, such as naming any libraries the application needs to be linked against (besides the default Android library) and identifying any permissions the application expects to be granted.

But the principal task of the manifest is to inform Android about the application's components. For example, an activity might be declared as follows:

그러나 매니페스트의 주요한 작업은 안드로이드에게 애플리케이션의 컴포넌트를 알려주는 것이다. 예를 들어 액티비티는 다음과 같이 선언될 수 있다.

<?xml version="1.0" encoding="utf-8"?><manifest . . . >    <application . . . >        <activity android:name="com.example.project.FreneticActivity"                  android:icon="@drawable/small_pic.png"                  android:label="@string/freneticLabel"                   . . .  >        </activity>        . . .    </application></manifest>

The name attribute of the <activity> element names the Activity subclass that implements the activity. The icon and label attributes point to resource files containing an icon and label that can be displayed to users to represent the activity.

<activity> 엘리먼트의 name 애트리뷰트는 액티비티를 구현하는 Activity 서브클래스를 지칭한다. icon과 label 애트리뷰트는 액티비티를 나타내기 위해 사용자에게 보여주는 아이콘과 라벨을 담고있는 리소스 파일을 가리킨다.

The other components are declared in a similar way <service> elements for services, <receiver> elements for broadcast receivers, and <provider> elements for content providers. Activities, services, and content providers that are not declared in the manifest are not visible to the system and are consequently never run. However, broadcast receivers can either be declared in the manifest, or they can be created dynamically in code (as BroadcastReceiver objects) and registered with the system by calling Context.registerReceiver().

나머지 다른 컴포넌트도 유사한 방법으로 선언된다 ? 서비스는 <service> 엘리먼트로, 브로드캐스트 리시버는 <receiver> 엘리먼트로, 컨텐트 프로바이더는 <provider> 엘리먼트로 선언된다. 매니페스트에 선언되지 않은 액티비티, 서비스, 컨텐트 프로바이더는 시스템에게 보여지지 않으며, 결과적으로 결코 실행되지 않는다. 하지만 브로드캐스트 리시버는 매니페스트 내에서 선언되거나, 또는 (BroadcastReceiver 오브젝트 형태로) 코드 내에서 동적으로 만들어져서 Context.registerReceiver()를 호출함으로써 시스템에 등록될 수 있다.

For more on how to structure a manifest file for your application, see The AndroidManifest.xml File.

애플리케이션의 매니페스트 파일을 구조화하는 방법에 대한 더 많은 정보는 9장. “AndroidManifest.xml”을 보라.

Intent filters

An Intent object can explicitly name a target component. If it does, Android finds that component (based on the declarations in the manifest file) and activates it. But if a target is not explicitly named, Android must locate the best component to respond to the intent. It does so by comparing the Intent object to the intent filters of potential targets. A component's intent filters inform Android of the kinds of intents the component is able to handle. Like other essential information about the component, they're declared in the manifest file. Here's an extension of the previous example that adds two intent filters to the activity:

인텐트 오브젝트는 그것의 대상이 되는 컴포넌트를 명시적으로 지정할 수 있다. 만약 그렇다면, 안드로이드는 (매니페스트 파일 내의 선언들에 기초해서) 그 컴포넌트를 찾아 내고 그것을 활성화한다. 하지만 타겟target이 명시적으로 지정되지 않으면, 안드로이드는 인텐트를 처리할 수 있는 최선의 컴포넌트를 찾아내야 한다. 이것은 해당 인텐트 오브젝트와 그 인텐트의 잠재적 대상이 될 수 있는 컴포넌트들의 인텐트 필터를 비교함으로써 이루어진다. 컴포넌트의 인텐트 필터는 안드로이드에게 해당 컴포넌트가 처리할 수 있는 인텐트의 종류를 알려준다. 컴포넌트에 대한 다른 필수적인 정보들처럼, 인텐트 필터도 매니페스트 파일 내에 선언된다. 여기에 액티비티에 두 개의 인텐트 필터를 추가한, 앞선 예제의 확장된 형태가 있다.

<?xml version="1.0" encoding="utf-8"?><manifest . . . >    <application . . . >        <activity android:name="com.example.project.FreneticActivity"                  android:icon="@drawable/small_pic.png"                  android:label="@string/freneticLabel"                   . . .  >            <intent-filter . . . >                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>            <intent-filter . . . >                <action android:name="com.example.project.BOUNCE" />                <data android:mimeType="image/jpeg" />                <category android:name="android.intent.category.DEFAULT" />            </intent-filter>        </activity>        . . .    </application></manifest>

The first filter in the example the combination of the action "android.intent.action.MAIN" and the category "android.intent.category.LAUNCHER" is a common one. It marks the activity as one that should be represented in the application launcher, the screen listing applications users can launch on the device. In other words, the activity is the entry point for the application, the initial one users would see when they choose the application in the launcher.

예제의 첫 번째 필터, 즉 “android.intent.action.MAIN” 액션과 “android.intent.category.LAUNCHER” 카테고리로 구성된 필터는 일반적인 것이다. 이것은 디바이스에서 사용자가 실행할 수 있는 애플리케이션 리스트를 스크린에 보여주는 애플리케이션 런처launcher에 그 액티비티가 표시되게 한다. 달리 말하면, 그 액티비티가 애플리케이션의 시작점이고, 사용자가 런처에서 애플리케이션을 선택했을 때 그들이 처음으로 보게 될 액티비티라는 것을 의미한다.

The second filter declares an action that the activity can perform on a particular type of data.

두 번째 필터는 특정 타입의 데이터에 대해 액티비티가 수행할 수 있는 액션을 선언한다.

A component can have any number of intent filters, each one declaring a different set of capabilities. If it doesn't have any filters, it can be activated only by intents that explicitly name the component as the target.

컴포넌트는 인텐트 필터를 얼마든지 가질 수 있다. 그리고 각각의 필터는 각기 다른 능력capability을 선언할 수 있다. 만약 컴포넌트가 어떤 필터도 가지지 않는다면, 그것은 인텐트의 대상으로 컴포넌트를 명시적으로 지정하는 인텐트에 의해서만 활성화될 수 있다.

For a broadcast receiver that's created and registered in code, the intent filter is instantiated directly as an IntentFilter object. All other filters are set up in the manifest.

코드 내에서 생성되어 등록된 브로드캐스트 리시버에 있어서, 인텐트 필터는 IntentFilter 오브젝트에 의해 직접적으로 인스턴스화 된다. 나머지 모든 필터들은 매니페스트 내에서 설정된다.

For more on intent filters, see a separate document, Intents and Intent Filters.

인텐트 필터에 대한 보다 많은 것은 5장. “인텐트와 인텐트 필터”를 보라.

Activities and Tasks

As noted earlier, one activity can start another, including one defined in a different application. Suppose, for example, that you'd like to let users display a street map of some location. There's already an activity that can do that, so all your activity needs to do is put together an Intent object with the required information and pass it to startActivity(). The map viewer will display the map. When the user hits the BACK key, your activity will reappear on screen.

앞에서 언급했던 것처럼 하나의 액티비티는 또 다른 액티비티를 시작시킬 수 있다. 그렇게 시작시킬 수 있는 액티비티에는 다른 애플리케이션이 정의한 액티비티도 포함된다. 예를 들어 여러분이 사용자에게 특정 위치 상의 시가지에 대한 지도를 보여주고 싶다고 가정해 보자. 이미 안드로이드에는 그 위치를 보여줄 수 있는 액티비티가 존재한다. 그러므로 여러분의 액티비티에 필요한 모든 것은, 인텐트 오브젝트에 필요한 정보들을 추가한 후 그것을 startActivity()의 파라미터로 전달하는 것이다. 그러면 맵 뷰어는 그 지도를 보여줄 것이다. 그리고 사용자가 BACK 키를 누를 때 여러분의 액티비티는 화면에 다시 나타날 것이다.

To the user, it will seem as if the map viewer is part of the same application as your activity, even though it's defined in another application and runs in that application's process. Android maintains this user experience by keeping both activities in the same task. Simply put, a task is what the user experiences as an "application." It's a group of related activities, arranged in a stack. The root activity in the stack is the one that began the task typically, it's an activity the user selected in the application launcher. The activity at the top of the stack is one that's currently running the one that is the focus for user actions. When one activity starts another, the new activity is pushed on the stack; it becomes the running activity. The previous activity remains in the stack. When the user presses the BACK key, the current activity is popped from the stack, and the previous one resumes as the running activity.

맵 뷰어는 다른 애플리케이션 내에 정의되어 있고 다른 애플리케이션 프로세스 상에서 실행되고 있음에도 불구하고, 사용자에게 맵 뷰어는 여러분의 액티비티처럼 동일한 애플리케이션의 일부분처럼 비춰질 것이다. 안드로이드는 두 개의 액티비티를 같은 태스크내에 유지함으로써 이런 사용자 경험user experience을 유지시킨다. 간단히 말하면, 태스크는 하나의 “애플리케이션”처럼 사용자들이 경험하는 그 무엇인 것이다. 그것은 하나의 스택 내에 정렬된 관련 액티비티들의 그룹이다. 스택의 루트Root 액티비티는 그 태스크를 시작했던 액티비티이다 ? 일반적으로, 그것은 사용자가 애플리케이션 런처에서 선택했던 액티비티이다. 스택의 최상위 액티비티는 현재 실행중인 액티비티이다 ? 그것은 사용자 액션을 위해 포커스 된 액티비티이다. 하나의 액티비티가 다른 것을 시작할 때 새로운 액티비티는 스택에 푸쉬(push)되며, 실행중인 상태의 액티비티가 된다. 이전 액티비티는 여전히 스택에 남아있다. 사용자가 BACK 키를 누를 때 현재의 액티비티는 스택으로부터 팝(pop)되며, 이전의 액티비티는 실행중인 액티비티로 재개resume된다.

The stack contains objects, so if a task has more than one instance of the same Activity subclass open multiple map viewers, for example the stack has a separate entry for each instance. Activities in the stack are never rearranged, only pushed and popped.

스택은 오브젝트들을 포함하고 있다. 그러므로 태스크가 - 예를 들어 여러 개의 맵 뷰어와 같이 - 동일 액티비티 서브클래스의 인스턴스를 한 개 이상 가지고 있다면, 스택은 각각의 인스턴스에 대한 별도의 시작점을 가진다. 스택에서 액티비티는 결코 재정렬되지 않는다. 다만 푸쉬push되고 팝pop될 뿐이다.

A task is a stack of activities, not a class or an element in the manifest file. So there's no way to set values for a task independently of its activities. Values for the task as a whole are set in the root activity. For example, the next section will talk about the "affinity of a task"; that value is read from the affinity set for the task's root activity.

태스크는 매니페스트 파일에 있는 클래스나 엘리먼트가 아니라, 액티비티에 대한 스택이다. 그러므로 태스크의 액티비티와 독립적으로 그 값을 설정할 방법은 없다. 태스크에 대한 값은 총괄적으로 루트 액티비티에 설정된다. 예를 들어 다음 섹션에서 태스크의 어피니티affinity에 대해 이야기할 것인데, 태스크의 어피니티affinity 값은 태스크의 루트 액티비티의 어피니티affinity 설정으로 나타내어 진다.

All the activities in a task move together as a unit. The entire task (the entire activity stack) can be brought to the foreground or sent to the background. Suppose, for instance, that the current task has four activities in its stack three under the current activity. The user presses the HOME key, goes to the application launcher, and selects a new application (actually, a new task). The current task goes into the background and the root activity for the new task is displayed. Then, after a short period, the user goes back to the home screen and again selects the previous application (the previous task). That task, with all four activities in the stack, comes forward. When the user presses the BACK key, the screen does not display the activity the user just left (the root activity of the previous task). Rather, the activity on the top of the stack is removed and the previous activity in the same task is displayed.

태스크 안에서 모든 액티비티는 하나의 단위로 함께 움직인다. 전체 태스크(전체 액티비티 스택)는 포어그라운드foreground로 가져와 질 수 있으며, 또한 백그라운드background로 보내질 수도 있다. 예를 들어 현재의 태스크가 자신의 스택에 네 개의 액티비티(세 개의 액티비티는 현재 액티비티 아래 있음)를 가지고 있다고 가정해 보자. 사용자가 HOME 키를 누르고 애플리케이션 런처로 간다. 그리고 새로운 애플리케이션(실제로 새로운 태스크)을 선택한다. 현재 태스크는 백그라운드로 가고, 새로운 태스크에 대한 루트 액티비티가 보여진다. 그런 다음 잠시 후, 사용자가 홈 스크린으로 돌아가서 이전 애플리케이션(이전 태스크)을 다시 선택한다. 스택에 모두 네개의 액티비티를 가지고 있는 그 태스크가 앞으로 온다. 그곳에서 사용자가 BACK 키를 누르면, 스크린에는 사용자가 조금 전에 떠났던 이전 태스크의 루트 액티비티가 보여지지는 않는다. 대신에 스택의 최상위의 액티비티가 제거되고 같은 태스크 내의 이전 액티비티가 보여진다.

The behavior just described is the default behavior for activities and tasks. But there are ways to modify almost all aspects of it. The association of activities with tasks, and the behavior of an activity within a task, is controlled by the interaction between flags set in the Intent object that started the activity and attributes set in the activity's <activity> element in the manifest. Both requester and respondent have a say in what happens.

방금 기술되었던 동작방식은 액티비티와 태스크에 대한 디폴트 동작방식이다. 그러나 이러한 동작방식 대부분의 측면을 수정하는 방법이 존재한다. 액티비티와 태스크 간의 결합과 태스크 내에서의 액티비티의 동작방식은 매니페스트 내의 액티비티의 <activity> 엘리먼트에 설정된 애트리뷰트와 액티비티를 시작시켰던 인텐트 오브젝트 내에 설정된 플래그 간의 상호작용에 의해 제어된다. 인텐트를 요청하는 쪽과 그것에 응답하는 쪽 모두, 일어나는 것에 참견할 권리를 갖는다.

In this regard, the principal Intent flags are:

이 점에 있어서 주요 인텐트 플래그는 다음과 같다.

FLAG_ACTIVITY_NEW_TASK 
FLAG_ACTIVITY_CLEAR_TOP 
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 
FLAG_ACTIVITY_SINGLE_TOP

The principal <activity> attributes are:

주요 <activity> 애트리뷰트는 다음과 같다.

taskAffinity 
launchMode 
allowTaskReparenting 
clearTaskOnLaunch 
alwaysRetainTaskState 
finishOnTaskLaunch

The following sections describe what some of these flags and attributes do, how they interact, and what considerations should govern their use.

다음 섹션은 이 플래그와 애트리뷰트가 무엇을 하는지, 어떻게 상호작용하며, 무엇을 고려해서 이것의 사용을 결정해야 하는지에 대해 설명한다.

Affinities and new tasks

By default, all the activities in an application have an affinity for each other that is, there's a preference for them all to belong to the same task. However, an individual affinity can be set for each activity with the taskAffinity attribute of the <activity> element. Activities defined in different applications can share an affinity, or activities defined in the same application can be assigned different affinities. The affinity comes into play in two circumstances: When the Intent object that launches an activity contains the FLAG_ACTIVITY_NEW_TASK flag, and when an activity has itsallowTaskReparenting attribute set to "true".

디폴트로 애플리케이션 내의 모든 액티비티는 서로에 대해 하나의 어피니티affinity를 갖는다. 즉, 동일 태스크에 속하는 그것들 모두에 대해 하나의 설정preference이 존재한다. 하지만 각각의 액티비티에 대한 개별적인 어피니티affinity가 <activity> 엘리먼트의 taskAffinity 애트리뷰트를 통해 설정될 수 있다. 다른 애플리케이션들내에 정의된 액티비티들이 하나의 어피니티affinity를 공유할 수도 있으며, 또한 같은 애플리케이션 내에 정의된 액티비티들에게 다른 어피니티affinity가 지정될 수도 있다. 어피니티affinity는 두 가지의 조건하에서 동작하게 된다. 액티비티를 런치하는 인텐트 오브젝트가 FLAG_ACTIVITY_NEW_TASK 플래그를 포함하고 있고, 그리고 액티비티에 allowTaskReparenting 애트리뷰트 값이 “true”로 설정되어 있을 때이다.

The FLAG_ACTIVITY_NEW_TASK flag
As described earlier, a new activity is, by default, launched into the task of the activity that called startActivity(). It's pushed onto the same stack as the caller. However, if the Intent object passed to startActivity() contains the FLAG_ACTIVITY_NEW_TASK flag, the system looks for a different task to house the new activity. Often, as the name of the flag implies, it's a new task. However, it doesn't have to be. If there's already an existing task with the same affinity as the new activity, the activity is launched into that task. If not, it begins a new task.
TASK 플래그가 포함되어 startActivity()의 파라미터로 전달된다면, 시스템은 새로운 액티비티를 담기 위해 다른 태스크를 찾는다. 대개 그것은 플래그의 이름이 나타내듯이 신규 태스크가 된다. 하지만 꼭 그렇게 되어야만 하는 것은 아니다. 만약 신규 액티비티와 동일 어피니티affinity를 가지는 태스크가 이미 존재한다면, 그 액티비티는 그 태스크 내에서 런치된다. 만약 그렇지 않다면 신규 태스크가 런치된다.
The allowTaskReparenting attribute
If an activity has its allowTaskReparenting attribute set to "true", it can move from the task it starts in to the task it has an affinity for when that task comes to the fore. For example, suppose that an activity that reports weather conditions in selected cities is defined as part of a travel application. It has the same affinity as other activities in the same application (the default affinity) and it allows reparenting. One of your activities starts the weather reporter, so it initially belongs to the same task as your activity. However, when the travel application next comes forward, the weather reporter will be reassigned to and displayed with that task.
만약 액티비티의 allowTaskReparenting 애트리뷰트가 “true”로 설정되어 있다면, 액티비티는 그것이 시작된 태스크로부터 어피니티affinity를 갖는 태스크로, 그 태스크가 앞으로 오게 될 때 이동할 수 있다. 예를 들어 선택해 놓은 도시의 날씨 상황을 예보하는 어떤 여행 애플리케이션의 일부를 정의하는 액티비티가 있다고 가정하자. 그것은 동일 애플리케이션 내의 다른 액티비티들과 같은 어피니티(디폴트 어피니티)를 가지고 있고, 리페어런팅(reparenting, 부모 태스크를 변경하는 것)이 허용되고 있다. 만약 여러분의 액티비티들 중의 하나가 일기 예보 액티비티를 시작하면, 그것은 여러분의 액티비티와 같은 태스크에 처음에는 속한다. 하지만 나중에 여행 애플리케이션이 앞으로 오게 되면, 그 일기 예보 액티비티는 다른 태스크에 재지정 될 것이고, 그 태스크에서 보여지게 된다.

If an .apk file contains more than one "application" from the user's point of view, you will probably want to assign different affinities to the activities associated with each of them.

만일 .apk 파일이 사용자 관점에서 하나 이상의 “애플리케이션”을 포함하고 있다면, 여러분은 아마도 그것들 각각과 연관된 액티비티들에 대해 다른 어피니티affinity를 지정하고자 할 것이다.

Launch modes

There are four different launch modes that can be assigned to an <activity> element's launchMode attribute:

네 개의 다른 런치 모드가 <activity> 엘리먼트의 launchMode 애트리뷰트에 지정될 수 있다.

"standard" (the default mode) 
"singleTop
"singleTask
"singleInstance"

The modes differ from each other on these four points:

위의 모드mode들은 네 가지 점에서 서로 차이가 있다.

  • Which task will hold the activity that responds to the intent. For the "standard" and "singleTop" modes, it's the task that originated the intent (and called startActivity()) unless the Intent object contains the FLAG_ACTIVITY_NEW_TASK flag. In that case, a different task is chosen as described in the previous section, Affinities and new tasks.

    In contrast, the "singleTask" and "singleInstance" modes mark activities that are always at the root of a task. They define a task; they're never launched into another task.

  • 어떤 태스크가 인텐트에 응답하는 액티비티를 보유할 것인가? “standard” 와 “singleTop” 모드에 대해서 인텐트 오브젝트가 FLAG_ACTIVITY_NEW_TASK 플래그를 가지지 않았다면, 그것은 인텐트를 만들었던(그리고 startActivity()를 호출했던) 액티비티가 있는 태스크이다. FLAG_ACTIVITY_NEW_TASK 플래그를 인텐트 오브젝트가 포함하고 있는 경우라면, 이전 섹션의 “어피니티와 신규 태스크”에서 설명된 것처럼 다른 태스크가 선택된다.

    반면, “singleTask” 와 “singleInstance” 모드는 액티비티가 항상 태스크의 루트에 나타나게 한다. 그것은 태스크를 정의한다; 그것은 결코 다른 태스크 안으로 런치되지 않는다.

  • Whether there can be multiple instances of the activity. A "standard" or "singleTop" activity can be instantiated many times. They can belong to multiple tasks, and a given task can have multiple instances of the same activity.

    In contrast, "singleTask" and "singleInstance" activities are limited to just one instance. Since these activities are at the root of a task, this limitation means that there is never more than a single instance of the task on the device at one time.

  • 액티비티에 대한 인스턴스가 여러 개가 존재할 수 있는가? “standard” 또는 “singleTop” 액티비티는 여러 번 인스턴스화될 수 있다. 그들은 다양한 태스크에 속할 수 있으며, 주어진 태스크는 동일 액티비티에 대한 여러 개의 인스턴스를 가질 수 있다.

    반면, “singleTask” 와 “singleInstance” 액티비티는 단지 하나의 인스턴스로 제한된다. 이러한 액티비티는 태스크의 루트에 있기 때문에, 이 제약은 그 태스크의 인스턴스가 한 개 이상 그 디바이스 상에 동시에 있을 수 없다는 것을 의미한다.

  • Whether the instance can have other activities in its task. A "singleInstance" activity stands alone as the only activity in its task. If it starts another activity, that activity will be launched into a different task regardless of its launch mode as if FLAG_ACTIVITY_NEW_TASK was in the intent. In all other respects, the "singleInstance" mode is identical to "singleTask".

    The other three modes permit multiple activities to belong to the task. A "singleTask" activity will always be the root activity of the task, but it can start other activities that will be assigned to its task. Instances of "standard" and "singleTop" activities can appear anywhere in a stack.

  • 액티비티의 인스턴스가 그것의 태스크에 다른 액티비티를 가질 수 있는가? “singleInstance” 액티비티는 그것이 속한 태스크 내에서 하나의 액티비티로 홀로 존재한다. 만약 그것이 다른 액티비티를 시작하면, 그 액티비티는 그 런치 모드와 상관없이 별도의 태스크에서 런치될 것이다. 이것은 마치 FLAG_ACTIVITY_NEW_TASK 플래그가 인텐트 내에 있는 것과 같다. 그 밖의 모든 측면에서, “singleInstance” 모드는 “singleTask”와 동일하다.

    나머지 다른 세 개의 모드는 그 태스크에 여러 개의 액티비티가 속하는 것을 허용한다. “singleTask” 액티비티는 항상 그 태스크의 루트 액티비티가 될 것이다. 그러나 그것은 그 태스크에 지정될 다른 액티비티들을 시작할 수 있다. “standard” 와 “singleTop” 액티비티의 인스턴스는 스택의 어디에서든 나타날 수 있다.

  • Whether a new instance of the class will be launched to handle a new intent. For the default "standard" mode, a new instance is created to respond to every new intent. Each instance handles just one intent. For the "singleTop" mode, an existing instance of the class is re-used to handle a new intent if it resides at the top of the activity stack of the target task. If it does not reside at the top, it is not re-used. Instead, a new instance is created for the new intent and pushed on the stack.

    For example, suppose a task's activity stack consists of root activity A with activities B, C, and D on top in that order, so the stack is A-B-C-D. An intent arrives for an activity of type D. If D has the default "standard" launch mode, a new instance of the class is launched and the stack becomes A-B-C-D-D. However, if D's launch mode is "singleTop", the existing instance is expected to handle the new intent (since it's at the top of the stack) and the stack remains A-B-C-D.

    If, on the other hand, the arriving intent is for an activity of type B, a new instance of B would be launched no matter whether B's mode is "standard" or "singleTop" (since B is not at the top of the stack), so the resulting stack would be A-B-C-D-B.

    As noted above, there's never more than one instance of a "singleTask" or "singleInstance" activity, so that instance is expected to handle all new intents. A "singleInstance" activity is always at the top of the stack (since it is the only activity in the task), so it is always in position to handle the intent. However, a "singleTask" activity may or may not have other activities above it in the stack. If it does, it is not in position to handle the intent, and the intent is dropped. (Even though the intent is dropped, its arrival would have caused the task to come to the foreground, where it would remain.)

  • 새로운 클래스 인스턴스가 새로운 인텐트를 처리하기 위해 런치될 것인가? 디폴트 “standard” 모드에 대해서는, 새로운 인스턴스가 모든 신규 인텐트에 응답하도록 생성된다. 각각의 인스턴스는 단지 하나의 인텐트를 처리한다. “singleTop” 모드에 대해서는, 만약 그것이 타겟target 태스크의 최상위 액티비티 스택에 존재한다면, 이미 존재하는 클래스 인스턴스가 신규 인텐트 처리를 위해 재사용된다. 만약 그것이 최상위에 존재하지 않다면 재사용되지 않는다. 대신 신규 인텐트를 위한 새 인스턴스가 생성되고, 스택에 푸쉬push된다.

    예를 들어 태스크의 액티비티 스택이 A-B-C-D 가 되도록, 루트 액티비티 A와 그 위에 순서대로 액티비티 B, C, D로 구성되어 있다고 가정하자. 타입 D 액티비티에 대한 인텐트가 도착한다. 만약에 D가 디폴트 “standard” 런치 모드를 가지고 있다면, 새로운 클래스 인스턴스가 시작되며 스택은 A-B-C-D-D가 된다.

    그러나 D의 런치 모드가 “singleTop” 이라면, (그것이 스택의 최상위에 있기 때문에) 기존에 있는 인스턴스가 새로운 인텐트를 처리하게 될 것이고 스택은 A-B-C-D로 남는다. 반면 도착한 인텐트가 타입 B 액티비티에 대한 것이라면, B가 “standard”든 “singleTop”이든 상관없이 (B가 스택의 최상위에 없기 때문에) 새로운 B 인스턴스가 런치될 것이다. 그러므로 결과적으로 스택은 A-B-C-D-B가 될 것이다

    위에서 언급했듯이, “singleTask”나 “singleInstance” 액티비티에 대해서는 하나 이상의 인스턴스가 결코 존재하지 않는다. 그러므로 그 인스턴스는 모든 새로운 인텐트를 처리하게 될 것이다. “singleInstance” 액티비티는 (이것이 태스크에 있는 유일한 액티비티이기 때문에) 항상 스택의 최상위에 있다. 그러므로 그것은 항상 인텐트를 처리하기 위한 위치에 있다. 그러나 “singleTask” 액티비티는 스택에서 그것 위에 다른 액티비티를 가질 수도 있고 가지지 않을 수도 있다. 만약 다른 액티비티가 있다면 인텐트를 처리할 위치에 있지 않는 것이고, 결과적으로 그 인텐트는 누락된다(비록 인텐트가 누락된다고 할지라도, 인텐트의 도착은 해당 태스크를 포어그라운드로 오게 할 것이며, 태스크는 그 상태로 남게된다).

When an existing activity is asked to handle a new intent, the Intent object is passed to the activity in an onNewIntent() call. (The intent object that originally started the activity can be retrieved by calling getIntent().)

이미 존재하는 액티비티가 새로운 인텐트를 처리하도록 요청될 때, 인텐트 오브젝트는 onNewIntent() 호출을 통해서 그 액티비티에 전달된다(최초에 그 액티비티를 시작했던 인텐트 오브젝트는 getIntent()를 호출함으로써 얻어질 수 있다).

Note that when a new instance of an Activity is created to handle a new intent, the user can always press the BACK key to return to the previous state (to the previous activity). But when an existing instance of an Activity handles a new intent, the user cannot press the BACK key to return to what that instance was doing before the new intent arrived.

액티비티의 신규 인스턴스가 신규 인텐트를 처리하기 위해 만들어질 때, 사용자가 이전의 상태(이전의 액티비티로) 돌아가기 위해 BACK 키를 항상 누를 수 있다는 점에 주의하라. 하지만 이미 존재하던 액티비티의 인스턴스가 신규 인텐트를 처리할 때, 사용자는 신규 인텐트가 도달하기 전에 그 인스턴스가 하던 작업으로 돌아가기 위해 BACK 키를 누를 수 없다.

For more on launch modes, see the description of the <activity> element.

시작 모드에 대한 더 자세한 것들에 대해서는 9장. “AndroidManifest.xml”의 <activity> 엘리먼트 설명을 보라.

Clearing the stack

If the user leaves a task for a long time, the system clears the task of all activities except the root activity. When the user returns to the task again, it's as the user left it, except that only the initial activity is present. The idea is that, after a time, users will likely have abandoned what they were doing before and are returning to the task to begin something new.

만약 사용자가 오랫동안 하나의 태스크를 떠나 있다면, 시스템은 루트 액티비티를 제외한 모든 액티비티를 태스크에서 제거한다. 사용자가 다시 그 태스크로 돌아왔을 때, 오직 최초의 액티비티만이 존재한다는 것 이외에 그것은 사용자가 그것을 떠났을 때와 같다. 이 아이디어는, 어느정도 시간이 지난 후 사용자는 그들이 이전에 하던 것을 포기했을 것이라는 것이고 뭔가 새로운 것을 시작하기 위해 그 태스크로 돌아왔을 거라고 생각하는 것이다.

That's the default. There are some activity attributes that can be used to control this behavior and modify it:

이것이 디폴트다. 이러한 동작을 제어하고 수정하기 위한 몇몇 액티비티 애트리뷰트가 있다.

The alwaysRetainTaskState attribute
If this attribute is set to "true" in the root activity of a task, the default behavior just described does not happen. The task retains all activities in its stack even after a long period.
The clearTaskOnLaunch attribute
If this attribute is set to "true" in the root activity of a task, the stack is cleared down to the root activity whenever the user leaves the task and returns to it. In other words, it's the polar opposite of alwaysRetainTaskState. The user always returns to the task in its initial state, even after a momentary absence.
The finishOnTaskLaunch attribute
This attribute is like clearTaskOnLaunch, but it operates on a single activity, not an entire task. And it can cause any activity to go away, including the root activity. When it's set to "true", the activity remains part of the task only for the current session. If the user leaves and then returns to the task, it no longer is present.
alwaysRetainTaskState 애트리뷰트
만약 태스크의 루트 액티비티에 이 애트리뷰트가 “true”로 설정된다면, 앞서 언급된 디폴트 동작은 발생하지 않는다. 태스크는 긴 시간 지난 이후에도 스택 내의 모든 액티비티들을 유지한다.
clearTaskOnLaunch 애트리뷰트
만약 태스크의 루트 액티비티에 이 애트리뷰트가 “true”로 설정된다면, 사용자가 태스크를 떠났다가 다시 돌아올 때마다, 스택은 루트 액티비티를 제외하고 모두 제거된다. 바꾸어 말하면 그것은 alwaysRetainTaskState와 정반대이다. 일시적으로 떠났다고 하더라도, 사용자는 항상 그것의 최초 상태로 태스크에 돌아오게 된다.
finishOnTaskLaunch 애트리뷰트
이 애트리뷰트는 clearTaskOnLaunch와 비슷하다. 그러나 그것은 전체 태스크가 아닌, 하나의 액티비티에서 동작한다. 그리고 그것은 루트 액티비티를 포함한 모든 액티비티를 제거할 수 있다. 이것이 “true”로 설정되면, 액티비티는 현재 세션에 대한 태스크의 부분으로만 남게된다. 만약 사용자가 떠났다가 태스크에 돌아오면 그것은 더 이상 존재하지 않는다.

There's another way to force activities to be removed from the stack. If an Intent object includes the FLAG_ACTIVITY_CLEAR_TOP flag, and the target task already has an instance of the type of activity that should handle the intent in its stack, all activities above that instance are cleared away so that it stands at the top of the stack and can respond to the intent. If the launch mode of the designated activity is "standard", it too will be removed from the stack, and a new instance will be launched to handle the incoming intent. That's because a new instance is always created for a new intent when the launch mode is "standard".

스택에서 액티비티가 제거되도록 하는 다른 방법이 있다. 만약 인텐트 오브젝트가 FLAG_ACTIVITY_CLEAR_TOP 플래그를 가지고 있고, 타겟target 태스크가 그것의 스택에 해당 인텐트를 처리해야 하는 타입의 액티비티 인스턴스를 이미 가지고 있다면, 그것이 스택의 최상위 존재해서 그 인텐트에 응답할 수 있도록 하기 위해 그 위의 모든 액티비티들은 제거된다. 만약 지정된 액티비티의 런치 모드가 “standard”라면, 그것 또한 스택에서 제거될 것이고, 새로운 인스턴스는 도착한 인텐트를 처리하기 위해 시작될 것이다. 왜냐하면 런치 모드가 “standard” 일 때 새로운 인스턴스는 새로운 인텐트를 위해 항상 생성되기 때문이다.

FLAG_ACTIVITY_CLEAR_TOP is most often used in conjunction with FLAG_ACTIVITY_NEW_TASK. When used together, these flags are a way of locating an existing activity in another task and putting it in a position where it can respond to the intent.

FLAG_ACTIVITY_CLEAR_TOP은 거의 대부분 FLAG_ACTIVITY_NEW_TASK와 함께 사용된다. 이것이 함께 사용될 때 이 플래그들은 다른 태스크 내에 있는 기존 액티비티를 지정하고, 그것을 인텐트에 응답할 수 있는 위치에 놓는다.

Starting tasks

An activity is set up as the entry point for a task by giving it an intent filter with "android.intent.action.MAIN" as the specified action and "android.intent.category.LAUNCHER" as the specified category. (There's an example of this type of filter in the earlier Intent Filters section.) A filter of this kind causes an icon and label for the activity to be displayed in the application launcher, giving users a way both to launch the task and to return to it at any time after it has been launched.

액티비티는 그것의 인텐트 필터에 액션을 “android.intent.action.MAIN”으로 지정하고 카테고리를 “android.intent.category.LAUNCHER”로 지정함으로써, 태스크에 대한 시작점으로 설정된다(이 필터 타입의 예제가 이전의 인텐트 필터 섹션에 있다). 이런 종류의 필터는 액티비티에 대한 아이콘과 라벨이 애플리케이션 런처에서 보여지도록 하며, 사용자에게 태스크를 런치하고 태스크가 런치된 이후 언제든 그 태스크로 다시 돌아갈 수 있는 두 가지 방법 모두를 제공한다.

This second ability is important: Users must be able to leave a task and then come back to it later. For this reason, the two launch modes that mark activities as always initiating a task, "singleTask" and "singleInstance", should be used only when the activity has a MAIN and LAUNCHER filter. Imagine, for example, what could happen if the filter is missing: An intent launches a "singleTask" activity, initiating a new task, and the user spends some time working in that task. The user then presses the HOME key. The task is now ordered behind and obscured by the home screen. And, because it is not represented in the application launcher, the user has no way to return to it.

이 두 번째 능력은 중요하다. 사용자는 태스크를 떠날 수도 있어야 하고, 나중에 그것으로 돌아갈 수도 있어야 한다. 이런 이유로, 액티비티가 태스크를 항상 시작시키는 두 개의 런치 모드, 즉 “singleTask”와 “singleInstance”는 액티비티가 MAIN 과 LAUNCHER 필터를 가지고 있을 때만 사용되어야 한다. 예를 들어 만약 이 필터가 없다면 무슨 일이 발생할까? 상상해 보라. 인텐트는 새로운 태스크를 시작하는 “singleTask” 액티비티를 런치하고, 사용자는 그 태스크에서 일을 하면서 약간의 시간을 보낸다. 사용자는 그런 다음 HOME 키를 누른다. 태스크는 이제 뒤에 놓이고, 홈스크린에 의해 가려진다. 그리고 그것은 애플리케이션 런처에서 나타나지 않기 때문에, 사용자는 그곳에 다시 돌아갈 방법이 없게 된다.

A similar difficulty attends the FLAG_ACTIVITY_NEW_TASK flag. If this flag causes an activity to begin a new task and the user presses the HOME key to leave it, there must be some way for the user to navigate back to it again. Some entities (such as the notification manager) always start activities in an external task, never as part of their own, so they always put FLAG_ACTIVITY_NEW_TASK in the intents they pass to startActivity(). If you have an activity that can be invoked by an external entity that might use this flag, take care that the user has a independent way to get back to the task that's started.

FLAG_ACTIVITY_NEW_TASK 플래그에도 비슷한 어려움이 수반된다. 만약 이 플래그가 새로운 태스크를 시작하는 액티비티를 만들고, 사용자가 그곳을 떠나기 위해 HOME 키를 누른다면, 사용자가 그곳으로 다시 돌아갈 수 있는 몇 가지 방법이 있어야 한다. 노티피케이션Notification 매니저와 같은 어떤 엔티티entity들은, 결코 그것들의 소유 영역이 아닌, 외부 태스크에서 액티비티를 시작시킨다. 그러므로 그들은 startActivity()에 파라미터로 전달하는 인텐트에 항상 FLAG_ACTIVITY_NEW_TASK를 놓는다. 만약 여러분이 이 플래그를 사용할 수도 있는 외부 엔티티에 의해 호출될 수 있는 액티비티를 가지고 있다면, 사용자가 그것이 시작된 태스크로 다시 돌아갈 수 있는 독자적인 방법을 갖게 하도록 주의하라.

For those cases where you don't want the user to be able to return to an activity, set the <activity> element's finishOnTaskLaunch to "true". See Clearing the stack, earlier.

그곳에서 사용자가 액티비티로 돌아가는 것을 가능하게 하는 것을 여러분이 원하지 않는 경우라면, <activity> 엘리먼트의 finishOnTaskLaunch를 “true”로 설정하라. 앞서서 언급한 “스택 제거”를 보라.

Processes and Threads

When the first of an application's components needs to be run, Android starts a Linux process for it with a single thread of execution. By default, all components of the application run in that process and thread.

애플리케이션의 컴포넌트들 중 첫 번째 컴포넌트가 실행되어야 할 필요가 있을 때, 안드로이드는 그것에 대한 하나의 실행execution 쓰레드를 가지는 리눅스 프로세스를 시작한다. 디폴트로 모든 애플리케이션의 컴포넌트는 이런 프로세스와 쓰레드에서 실행된다.

However, you can arrange for components to run in other processes, and you can spawn additional threads for any process.

하지만 여러분은 컴포넌트가 다른 프로세스에서 실행되도록 배치할 수 있으며, 여러분은 임의의 프로세스에 대한 추가적인 쓰레드들을 만들 수 있다.

Processes

The process where a component runs is controlled by the manifest file. The component elements <activity><service><receiver>, and <provider> each have a process attribute that can specify a process where that component should run. These attributes can be set so that each component runs in its own process, or so that some components share a process while others do not. They can also be set so that components of different applications run in the same process provided that the applications share the same Linux user ID and are signed by the same authorities. The<application> element also has a process attribute, for setting a default value that applies to all components.

컴포넌트가 실행되는 장소인 프로세스는 매니페스트 파일에 의해 제어된다. 컴포넌트 엘리먼트 -<activity>, <service>, <receiver>, 그리고 <provider> - 각각은 그 컴포넌트가 실행되어야 하는 프로세스를 지정할 수 있는 process 애트리뷰트를 가진다. 이 애트리뷰트는 각각의 컴포넌트가 자신만의 프로세스에서 실행되도록 설정될 수 있으며, 또한 몇몇 컴포넌트는 다른 것들과 달리 하나의 프로세스를 공유하도록 설정될 수도 있다. 또한 이 애트리뷰트는 동일 프로세스에서 다른 애플리케이션의 컴포넌트가 실행되도록 설정될 수 있다. 이것은 애플리케이션이 동일 리눅스 유저user ID를 공유하고, 동일 인증서로 사인되는 조건하에서 가능하다. <application> 엘리먼트 또한 모든 컴포넌트에 디폴트 값을 설정하기 위한 process 애트리뷰트를 가지고 있다.

All components are instantiated in the main thread of the specified process, and system calls to the component are dispatched from that thread. Separate threads are not created for each instance. Consequently, methods that respond to those calls methods like View.onKeyDown() that report user actions and the lifecycle notifications discussed later in the Component Lifecycles section always run in the main thread of the process. This means that no component should perform long or blocking operations (such as networking operations or computation loops) when called by the system, since this will block any other components also in the process. You can spawn separate threads for long operations, as discussed under Threads, next.

모든 컴포넌트는 지정된 프로세스의 메인 쓰레드에서 인스턴스화 되며, 그 컴포넌트에 대한 시스템 호출은 메인 쓰레드로부터 디스패치dispatch된다. 각각의 인스턴스에 대해 별도의 쓰레드가 생성되지는 않는다. 결과적으로, 그러한 호출에 응답하는 메쏘드(사용자의 액션을 리포트 하는 View.onKeyDown()와 “컴포넌트 생명주기” 섹션에서 나중에 논의될 생명주기 노티피케이션과 같은 메쏘드)는 항상 그 프로세스의 메인 쓰레드에서 실행된다. 이것은 컴포넌트가 시스템에 의해 호출될 때 (네트워킹 오퍼레이션이나 계산 루프처럼) 오래 걸리거나 블록킹blocking되는 오퍼레이션을 수행해서는 안된다는 것을 의미한다. 왜냐하면, 이것들이 프로세스 내의 다른 컴포넌트를 방해할 것이기 때문이다. 여러분은 오래 걸리는 오퍼레이션을 위해, 이 다음의 “쓰레드”에서 논의되듯이 별도의 쓰레드를 만들 수 있다.

Android may decide to shut down a process at some point, when memory is low and required by other processes that are more immediately serving the user. Application components running in the process are consequently destroyed. A process is restarted for those components when there's again work for them to do.

안드로이드는 메모리가 부족하고 사용자를 더 즉각적으로 지원하고 있는 프로세스에 의해 메모리가 요구될 때, 임의의 시점에 프로세스를 종료하는 것을 결정할 수도 있다. 그 프로세스 안에서 실행되는 애플리케이션 컴포넌트는 결과적으로 파괴된다. 그것을 다시 수행해야 할 때 그 컴포넌트에 대한 프로세스는 다시 시작된다.

When deciding which processes to terminate, Android weighs their relative importance to the user. For example, it more readily shuts down a process with activities that are no longer visible on screen than a process with visible activities. The decision whether to terminate a process, therefore, depends on the state of the components running in that process. Those states are the subject of a later section, Component Lifecycles.

어떤 프로세스를 종료할 것인가를 결정할 때, 안드로이드는 사용자에 대한 상대적 중요성을 평가한다. 예를 들어 안드로이드는 보여지고 있는 액티비티를 가진 프로세스보다 스크린 상에서 더 이상 보이지 않는 액티비티를 가진 프로세스를 더 우선적으로 종료시킨다. 그러므로 프로세스에 대한 종료 여부 결정은 그 프로세스에서 실행되고 있는 컴포넌트의 상태에 의존한다. 그 상태는 다음에 나올 “컴포넌트 생명주기” 섹션의 주제이다.

Threads

Even though you may confine your application to a single process, there will likely be times when you will need to spawn a thread to do some background work. Since the user interface must always be quick to respond to user actions, the thread that hosts an activity should not also host time-consuming operations like network downloads. Anything that may not be completed quickly should be assigned to a different thread.

비록 애플리케이션을 하나의 프로세스에 제한할 지라도, 여러분은 몇몇 백그라운드 작업을 하기 위한 쓰레드를 생성할 필요가 있을 수 있다. 사용자 인터페이스가 사용자 액션에 항상 빠르게 응답해야 하기 때문에, 액티비티를 보유하는 쓰레드는 네트워크 다운로드와 같은 시간이 소요되는 오퍼레이션을 함께 보유해서는 안된다. 빠르게 수행이 완료될 수 없는 것은 별도의 쓰레드에 할당되어져야 한다.

Threads are created in code using standard Java Thread objects. Android provides a number of convenience classes for managing threads Looper for running a message loop within a thread,Handler for processing messages, and HandlerThread for setting up a thread with a message loop.

쓰레드는 표준 Java 쓰레드Thread 오브젝트를 사용해서 코드에서 생성된다. 안드로이드는 쓰레드 관리를 위한 몇 가지 편리한 클래스들을 제공한다 ? 쓰레드 내에서 메시지 루프를 실행하기 위한 루퍼Looper, 메시지 처리를 위한 핸들러Handler, 그리고 메시지 루프를 가진 쓰레드를 설정하기 위한 핸들러쓰레드HanlderThread가 그것이다.

Remote procedure calls

Android has a lightweight mechanism for remote procedure calls (RPCs) where a method is called locally, but executed remotely (in another process), with any result returned back to the caller. This entails decomposing the method call and all its attendant data to a level the operating system can understand, transmitting it from the local process and address space to the remote process and address space, and reassembling and reenacting the call there. Return values have to be transmitted in the opposite direction. Android provides all the code to do that work, so that you can concentrate on defining and implementing the RPC interface itself.

안드로이드는 원격 프로시저 호출(remote procedure calls, RPCs)를 위한 경량화된lightweight 메커니즘을 가지고 있다 ? 그곳에서 메쏘드는 지역적으로locally 호출되지만, 호출자에게 다시 리턴되는 결과를 가지는 다른 프로세스 상에서 원격으로remotely 실행된다. 이것은 그 메쏘드 호출과 그것이 수반하는attendant 모든 데이터를 운영체제가 이해할 수 있는 수준으로 분해decomposing하며, 그것을 로컬 프로세스와 어드레스address 공간에서 원격 프로세스와 어드레스 공간으로 전달하고, 그곳에서 그 호출을 재조합reassembling하고 재연reenacting하는 것을 야기한다. 리턴 값은 정반대의 방향에서 전달되어져야 한다. 안드로이드는 여러분이 RPC 인터페이스 자체를 정의하고 구현하는 것에 집중할 수 있도록, 그 작업을 하기 위한 모든 코드를 제공한다.

An RPC interface can include only methods. All methods are executed synchronously (the local method blocks until the remote method finishes), even if there is no return value.

RPC 인터페이스는 오직 메쏘드만을 포함할 수 있다. 모든 메쏘드는 비록 리턴 값이 없다 할지라도 동기적으로 실행된다(로컬 메쏘드는 원격지의 메쏘드가 끝날 때까지 멈춰 있다).

In brief, the mechanism works as follows: You'd begin by declaring the RPC interface you want to implement using a simple IDL (interface definition language). From that declaration, the aidl tool generates a Java interface definition that must be made available to both the local and the remote process. It contains two inner class, as shown in the following diagram:

간단하게 말하면, 그 메커니즘은 다음과 같이 동작한다. 여러분은 간단한 IDL (interface definition language, 인터페이스 정의 언어)을 사용하여 여러분이 구현하고자 하는 RPC 인터페이스를 선언하는 것에서 시작할 수 있다. 그 선언에 기반해서 aidl 툴tool은 로컬과 원격지 프로세스 모두에서 사용되어져야 하는 Java 인터페이스 정의definition를 생성한다. 이것은 아래 다이어그램에서 보여지듯이 다음과 같은 두 개의 내부inner 클래스를 포함한다.

RPC mechanism.

The inner classes have all the code needed to administer remote procedure calls for the interface you declared with the IDL. Both inner classes implement the IBinder interface. One of them is used locally and internally by the system; the code you write can ignore it. The other, called Stub, extends the Binder class. In addition to internal code for effectuating the IPC calls, it contains declarations for the methods in the RPC interface you declared. You would subclass Stub to implement those methods, as indicated in the diagram.

내부 클래스들은 IDL을 가지고 선언했던 인터페이스에 대한 원격 프로시저 호출을 관리하기 위해 필요한 모든 코드를 가지고 있다. 두 개의 내부 클래스 모두는 IBinder 인터페이스를 구현하고 있다. 그들 중 하나는 시스템에 의해 지역적이고locally 내부적으로internally 사용된다; 여러분이 작성한 코드는 그것을 무시할 수 있다. 다른 하나는 스터브Stub라고 불리는 것으로 바인더Binder 클래스를 확장하고extends 있는 것이다. 그것은 IPC 호출을 가능하게 하는 내부 코드뿐만 아니라, 여러분이 선언한 RPC 인터페이스 내의 메쏘드에 대한 선언을 포함하고 있다. 다이어그램에서 보여지듯이, 여러분이 정의한 RPC 인터페이스 내의 메쏘드를 구현하기 위해서는 스터브Stub 서브클래스가 필요할 것이다.

Typically, the remote process would be managed by a service (because a service can inform the system about the process and its connections to other processes). It would have both the interface file generated by the aidl tool and the Stub subclass implementing the RPC methods. Clients of the service would have only the interface file generated by the aidl tool.

일반적으로 원격지 프로세스는 서비스로 관리될 것이다(왜냐하면 서비스는 그 프로세스와 다른 프로세스에 대한 그것의 커넥션(connection)에 대하여 시스템에 알려줄 수 있기 때문이다). 그것은 aidl 툴tool에 의해 생성된 인터페이스 파일과 RPC 메쏘드를 구현하는 스터브Stub 서브클래스 모두를 가질 것이다. 그 서비스 클라이언트는 단지 aidl 툴tool에 의해 생성된 인터페이스 파일만을 가질 것이다.

Here's how a connection between a service and its clients is set up:

여기에 서비스와 그것의 클라이언트 간의 커넥션이 셋업되는 방법이 있다.

  • Clients of the service (on the local side) would implement onServiceConnected() and onServiceDisconnected() methods so they can be notified when a successful connection to the remote service is established, and when it goes away. They would then call bindService() to set up the connection.
  • The service's onBind() method would be implemented to either accept or reject the connection, depending on the intent it receives (the intent passed to bindService()). If the connection is accepted, it returns an instance of the Stub subclass.
  • If the service accepts the connection, Android calls the client's onServiceConnected() method and passes it an IBinder object, a proxy for the Stub subclass managed by the service. Through the proxy, the client can make calls on the remote service.
  • (로컬 쪽에 있는) 서비스 클라이언트는 그 클라이언트가 원격지 서비스에 대한 커넥션을 성공적으로 확립할 때와 그 커넥션이 끊길 때, 그것이 통보될 수 있도록 onServiceConnected()와 onServiceDisconnected() 메쏘드를 구현할 것이다. 그것들은 그런 다음 해당 커넥션을 셋업하기 위해 bindService()를 호출할 것이다.
  • 서비스의 onBind() 메쏘드는 그것이 수신하는 인텐트(bindService()에 파라미터로 전달된 인텐트)에 의존해서, 커넥션을 승인하거나 거절하도록 구현될 것이다. 만약 커넥션이 승인된다면, 그것을 스터브Stub 서브클래스에 대한 인스턴스를 리턴한다.
  • 만약 그 서비스가 그 커넥션을 수용한다면, 안드로이드는 클라이언트의 onServiceConnected() 메쏘드를 호출하며, 그것에 서비스에 의해 관리되는 스터브Stub 서브클래스에 대한 프락시proxy, IBinder 오브젝트를 전달한다. 그 프락시를 통해, 클라이언트는 원격지 서비스에 호출을 만들 수 있다.

This brief description omits some details of the RPC mechanism. For more information, see Designing a Remote Interface Using AIDL and the IBinder class description.

  • 만약 그 서비스가 그 커넥션을 수용한다면, 안드로이드는 클라이언트의 onServiceConnected() 메쏘드를 호출하며, 그것에 서비스에 의해 관리되는 스터브Stub 서브클래스에 대한 프락시proxy, IBinder 오브젝트를 전달한다. 그 프락시를 통해, 클라이언트는 원격지 서비스에 호출을 만들 수 있다.
  • Thread-safe methods

    In a few contexts, the methods you implement may be called from more than one thread, and therefore must be written to be thread-safe.

    몇몇의 컨텍스트context에서, 여러분이 구현한 메쏘드는 한 개 이상의 쓰레드로부터 호출될 수 있다. 그러므로 그것은 쓰레드-세이프thread-safe하게 작성되어져야 한다.

    This is primarily true for methods that can be called remotely as in the RPC mechanism discussed in the previous section. When a call on a method implemented in an IBinder object originates in the same process as the IBinder, the method is executed in the caller's thread. However, when the call originates in another process, the method is executed in a thread chosen from a pool of threads that Android maintains in the same process as the IBinder; it's not executed in the main thread of the process. For example, whereas a service's onBind() method would be called from the main thread of the service's process, methods implemented in the object that onBind() returns (for example, a Stub subclass that implements RPC methods) would be called from threads in the pool. Since services can have more than one client, more than one pool thread can engage the same IBinder method at the same time. IBinder methods must, therefore, be implemented to be thread-safe.

    이것은 (이전 섹션에서 논의했던 RPC 메커니즘에서와 같이) 원격으로 호출될 수 있는 메쏘드에 있어서 중요한 사실이다. IBinder 오브젝트에 구현된 메쏘드 호출이 그 IBinder로써 동일 프로세스에서 만들어질 때, 그 메쏘드는 호출자의 쓰레드에서 실행된다. 하지만 그 호출이 다른 프로세스에서 만들어질 때, 그 메쏘드는 IBinder로써 동일 프로세스에서 안드로이드가 유지하고 있는 쓰레드 풀pool로부터 선택된 쓰레드에서 실행된다. 그것은 프로세스의 메인 쓰레드 내에서 실행되지 않는다. 예를 들어 서비스의 onBind() 메쏘드가 서비스의 프로세스의 메인 쓰레드로부터 호출되는 반면에, onBind()가 반환(예를 들어 RPC 메쏘드를 구현하고 있는 스터브(Stub) 서브클래스)하는 오브젝트에 구현된 메쏘드는 풀pool 내의 쓰레드에서 호출된다. 서비스가 하나 이상의 클라이언트를 가질 수 있기 때문에, 하나 이상의 풀pool 쓰레드가 동일 시간에 동일한 IBinder 메쏘드를 사용할 수 있다. 그러므로 IBinder 메쏘드는 쓰레드-세이프thread-safe하도록 구현되어야 한다.

    Similarly, a content provider can receive data requests that originate in other processes. Although the ContentResolver and ContentProvider classes hide the details of how the interprocess communication is managed, ContentProvider methods that respond to those requests the methods query()insert()delete()update(), and getType() are called from a pool of threads in the content provider's process, not the main thread of the process. Since these methods may be called from any number of threads at the same time, they too must be implemented to be thread-safe.

    유사하게, 컨텐트 프로바이더는 다른 프로세스에서 만들어진 데이터 요청을 받을 수 있다. 비록 컨텐트 리졸버ContentResolver와 컨텐트 프로바이더ContentProvider 클래스가 그 프로세스 간 통신이 관리되는 자세한 방법을 숨기고 있지만, 그러한 요청(query(), insert(), delete(), update(), getType() 메쏘드)에 응답하는 컨텐트 프로바이더 메쏘드는 컨텐트 프로바이더 프로세스의 쓰레드 풀pool에서 호출된다. 이러한 메쏘드가 동일 시간에 다른 많은 쓰레드에서 호출될 수 있기 때문에, 그들 또한 쓰레드-세이프thread-safe하도록 구현되어야 한다.

    Component Lifecycles

    Application components have a lifecycle a beginning when Android instantiates them to respond to intents through to an end when the instances are destroyed. In between, they may sometimes be active or inactive,or, in the case of activities, visible to the user or invisible. This section discusses the lifecycles of activities, services, and broadcast receivers including the states that they can be in during their lifetimes, the methods that notify you of transitions between states, and the effect of those states on the possibility that the process hosting them might be terminated and the instances destroyed.

    애플리케이션 컴포넌트는 생명주기를 가진다 ? 그 생명주기는 인텐트에 응답하기 위해 안드로이드가 컴포넌트를 인스턴스화 할 때 시작해서, 그 인스턴스가 파괴될 때 끝난다. 액티비티의 경우에는 그 사이에 활성화되거나 비활성화될 수도 있으며, 사용자에게 보이거나 보이지 않을 수 있다. 이번 섹션은 액티비티, 서비스, 브로드캐스트 리시버에 대한 생명주기를 설명한다 ? 이곳에서는 그것들이 생존기간 동안에 있을 수 있는 상태, 상태간의 변화를 여러분이 통보받을 수 있는 메쏘드, 그리고 컴포넌트를 보유하고 있는 프로세스가 종료되고 그 인스턴스가 파괴되는 일이 발생할 때 그들 상태의 영향에 대해 언급한다.

    Activity lifecycle

    An activity has essentially three states:

    액티비티는 필수적으로 세 가지 상태를 가지고 있다.

    • It is active or running when it is in the foreground of the screen (at the top of the activity stack for the current task). This is the activity that is the focus for the user's actions.
    • It is paused if it has lost focus but is still visible to the user. That is, another activity lies on top of it and that activity either is transparent or doesn't cover the full screen, so some of the paused activity can show through. A paused activity is completely alive (it maintains all state and member information and remains attached to the window manager), but can be killed by the system in extreme low memory situations.

    • It is stopped if it is completely obscured by another activity. It still retains all state and member information. However, it is no longer visible to the user so its window is hidden and it will often be killed by the system when memory is needed elsewhere.

    • 활성화(active) 또는 실행 중(running)인 상태로, 그것이 포어그라운드foreground 화면(현재 태스크에 대한 액티비티 스택의 최상위에)으로 있을 때이다. 이것은 해당 액티비티가 사용자의 액션에 대한 포커스를 가지고 있다.
    • 멈춤(paused) 상태로, 포커스는 보유하지 않았지만 여전히 사용자에게 보여지고 있을 때이다. 즉, 다른 액티비티가 그 위에 위치하지만 그 액티비티가 투명상태 또는 전체 화면을 채우지 못하고 있어서 약간이라도 멈춤 상태의 액티비티를 볼 수 있는 상태이다. 멈춤상태의 액티비티는 완전하게 살아 있다(그것은 모든 상태와 멤버 정보를 유지하고 있으며, 윈도우 매니저에게 붙어서 존속하고 있다). 그러나 극도로 메모리가 부족한 상태에서는 시스템에 의해 종료될 수도 있다.

    • 정지(stopped) 상태는, 그것이 완벽하게 다른 액티비티에 의해서 가려진 상태이다. 그리고 여전히 모든 상태와 멤버 정보는 유지된다. 하지만 이것은 더 이상 사용자에게 보여지지 않는다. 그러므로 해당 액티비티 윈도우는 사라지게 되며, 그것은 다른 곳에서 메모리가 필요하게 될 때 시스템에 의해 가끔 종료될 것이다.

    If an activity is paused or stopped, the system can drop it from memory either by asking it to finish (calling its finish() method), or simply killing its process. When it is displayed again to the user, it must be completely restarted and restored to its previous state.

    액티비티가 멈춤paused상태이거나 또는 정지stopped상태라면, 시스템은 finish() 메쏘드를 호출함으로써 그것을 종료하게 하거나 또는 간단하게 해당 프로세스를 죽이는 방식으로 그것을 메모리에서 제거할 수 있다. 그리고 그것이 사용자에게 다시 보여지게 될 때, 그것은 완전하게 다시 시작되고 이전의 상태로 복구되어야 한다.

    As an activity transitions from state to state, it is notified of the change by calls to the following protected methods:

    액티비티의 상태가 변할 때면, 그것은 다음과 같은 프로텍티드protected 메쏘드가 호출됨으로써 그 변화가 통보된다.

    void onCreate(Bundle savedInstanceState) 
    void onStart() 
    void onRestart() 
    void onResume() 
    void onPause() 
    void onStop() 
    void onDestroy()

    All of these methods are hooks that you can override to do appropriate work when the state changes. All activities must implement onCreate() to do the initial setup when the object is first instantiated. Many will also implement onPause() to commit data changes and otherwise prepare to stop interacting with the user.

    이러한 모든 메쏘드는 여러분이 액티비티의 상태가 변할 때, 적절한 작업을 수행하기 위해 오버라이드override할 수 있는 것이다. 모든 액티비티는 오브젝트가 최초로 인스턴스화 될 때 초기화를 설정하기 위한 onCreate()를 구현해야 한다. 많은 액티비티들이 데이터 변경을 저장하기 위해, 다른 경우로는 사용자와의 상호작용 중지를 준비하기 위해, onPause()를 구현할 것이다.

    Taken together, these seven methods define the entire lifecycle of an activity. There are three nested loops that you can monitor by implementing them:

    이러한 7가지의 메쏘드들이 함께 사용되어서, 하나의 액티비티에 대한 전체 생명주기가 정의된다. 이곳에는 여러분이 그것들을 구현함으로써 모니터링할 수 있는 3개의 네스티드 루프nested loop가 존재한다.

    • The entire lifetime of an activity happens between the first call to onCreate() through to a single final call to onDestroy(). An activity does all its initial setup of "global" state in onCreate(), and releases all remaining resources in onDestroy(). For example, if it has a thread running in the background to download data from the network, it may create that thread in onCreate() and then stop the thread inonDestroy().
    • The visible lifetime of an activity happens between a call to onStart() until a corresponding call to onStop(). During this time, the user can see the activity on-screen, though it may not be in the foreground and interacting with the user. Between these two methods, you can maintain resources that are needed to show the activity to the user. For example, you can register a BroadcastReceiver in onStart() to monitor for changes that impact your UI, and unregister it in onStop() when the user can no longer see what you are displaying. TheonStart() and onStop() methods can be called multiple times, as the activity alternates between being visible and hidden to the user.

    • The foreground lifetime of an activity happens between a call to onResume() until a corresponding call to onPause(). During this time, the activity is in front of all other activities on screen and is interacting with the user. An activity can frequently transition between the resumed and paused states for example, onPause() is called when the device goes to sleep or when a new activity is started, onResume() is called when an activity result or a new intent is delivered. Therefore, the code in these two methods should be fairly lightweight.

    • 액티비티의 인타이어 라이프타임(entire lifetime)은 onCreate()에 대한 첫 번째 호출에서 onDestroy()에 대한 한번의 마지막 호출 사이에서 발생한다. 액티비티는 onCreate()에서 “전역global” 상태의 모든 초기 설정을 하며, 그리고 onDestroy()에서 존재하는 모든 리소스를 해제한다. 예를 들어 만일 그것이 네트워크에서 자료를 다운로드하기 위해 백그라운드background로 실행되고 있는 쓰레드를 가지고 있다면, 그 쓰레드는 onCreate()에서 생성되어 onDestroy()에서 종료될 것이다.
    • 액티비티의 비저블 라이프타임(visibile lifetime)은 onStart()에 대한 호출에서 그에 대응되는 onStop() 호출 사이에서 발생한다. 이 기간 동안 액티비티가 사용자와 상호작용을 하는 포어그라운드foreground 상에 존재하지 않음에도 불구하고, 사용자는 화면 상에서 그 액티비티를 볼 수 있다. 이 두 개의 메쏘드 사이에서, 여러분은 사용자에게 액티비티를 보여주기 위해 필요한 리소스들을 유지할 수 있다. 예를 들어 여러분은 onStart()에서 여러분의 사용자 인터페이스에 영향을 미치는 변화들을 모니터링하기 위해 브로드캐스트 리시버를 등록할 수 있으며, 여러분이 보여주고 있는 것을 더 이상 사용자가 볼 수 없을 때 onStop()에서 그것을 제거할 수 있다. onStart()와 onStop() 메쏘드는 액티비티가 사용자에게 보여지게 되고 숨겨지게 되는 것 사이의 선택적 상황에 따라 여러 번 호출될 수 있다.

    • 액티비티의 포어그라운드 라이프타임(foreground lifetime)은 onResume()의 호출과 그에 대응되는 onPause() 호출 사이에서 발생한다. 이 기간 동안 액티비티는 화면 상의 다른 모든 액티비티들의 앞에 놓이며, 사용자와 상호작용을 하게 된다. 액티비티는 재개resumed 상태와 멈춤paused 상태 사이에서 자주 바뀔 수 있다. 예를 들어 onPause()는 디바이스가 절전상태로 되거나 또는 새로운 액티비티가 시작되었을 때 호출되며, onResume()은 액티비티가 복귀될 때 또는 새로운 인텐트가 도착했을 때 호출된다. 그러므로 이 두 개의 메쏘드 내의 코드는 상당히 가벼워야 한다.

    The following diagram illustrates these loops and the paths an activity may take between states. The colored ovals are major states the activity can be in. The square rectangles represent the callback methods you can implement to perform operations when the activity transitions between states.

    아래의 다이어그램은 이러한 루프들과 하나의 액티비티가 상태들을 이동해 가는 경로를 설명한다. 채색된 타원들은 액티비티가 존재하게 되는 주요 상태들이다. 직사각형들은 액티비티가 상태들 사이를 변화해 갈 때 오퍼레이션들을 수행하기 위해 여러분이 구현할 수 있는 콜백callback 메쏘드를 나타낸다.

    State diagram for an Android activity lifecycle.

    The following table describes each of these methods in more detail and locates it within the activity's overall lifecycle:

    아래의 테이블은 이러한 메쏘드들 각각에 대한 좀 더 자세한 설명하며, 해당 메쏘드들을 전체 액티비티의 생명주기 내에서 배치하고 있다.

    MethodDescriptionKillable?NextonCreate()Called when the activity is first created. This is where you should do all of your normal static set up create views, bind data to lists, and so on. This method is passed a Bundle object containing the activity's previous state, if that state was captured (see Saving Activity State, later).

    Always followed by onStart().

    NoonStart() onRestart()Called after the activity has been stopped, just prior to it being started again.

    Always followed by onStart()

    NoonStart()onStart()Called just before the activity becomes visible to the user.

    Followed by onResume() if the activity comes to the foreground, or onStop() if it becomes hidden.

    NoonResume() 
    or
    onStop() onResume()Called just before the activity starts interacting with the user. At this point the activity is at the top of the activity stack, with user input going to it.

    Always followed by onPause().

    NoonPause()onPause()Called when the system is about to start resuming another activity. This method is typically used to commit unsaved changes to persistent data, stop animations and other things that may be consuming CPU, and so on. It should do whatever it does very quickly, because the next activity will not be resumed until it returns.

    Followed either by onResume() if the activity returns back to the front, or by onStop() if it becomes invisible to the user.

    YesonResume() 
    or
    onStop()onStop()Called when the activity is no longer visible to the user. This may happen because it is being destroyed, or because another activity (either an existing one or a new one) has been resumed and is covering it.

    Followed either by onRestart() if the activity is coming back to interact with the user, or by onDestroy()if this activity is going away.

    YesonRestart()
    or
    onDestroy()onDestroy()Called before the activity is destroyed. This is the final call that the activity will receive. It could be called either because the activity is finishing (someone called finish() on it), or because the system is temporarily destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isFinishing() method.Yesnothing

    Note the Killable column in the table above. It indicates whether or not the system can kill the process hosting the activity at any time after the method returns, without executing another line of the activity's code. Three methods (onPause()onStop(), and onDestroy()) are marked "Yes." Because onPause() is the first of the three, it's the only one that's guaranteed to be called before the process is killed onStop() and onDestroy() may not be. Therefore, you should use onPause() to write any persistent data (such as user edits) to storage.

    위의 테이블에서 “강제종료가능?” 열에 주의하라. 그것은 메쏘드가 리턴된 후 어떤 시점에라도 액티비티 코드의 다른 라인을 실행하지 않고, 시스템이 액티비티를 담고 있는 프로세스를 강제종료할 수 있는지 여부를 가리킨다. 3개의 메쏘드(onPause(), onStop(), 그리고 onDestroy())에는 “예”라고 표시되어 있다. onPause()는 이 3개 중 첫 번째 것이기 때문에, 그것은 프로세스가 강제종료되기 전에 호출되는 것이 보증되어야 하는 유일한 것이다 ? onStop()과 onDestory()는 아닐 수 있다. 그러므로 여러분은 (사용자의 편집과 같은) 임의의 영구 데이터를 저장공간에 쓰기 위해서는 onPause()를 사용해야 한다.

    Methods that are marked "No" in the Killable column protect the process hosting the activity from being killed from the moment they are called. Thus an activity is in a killable state, for example, from the time onPause() returns to the time onResume() is called. It will not again be killable until onPause() again returns.

    “강제종료가능?” 열에 “아니오”라고 표시된 메쏘드들은 그것들이 호출된 순간부터 액티비티를 보유하고 있는 프로세스가 강제종료되지 않도록 보호한다. 따라서, 예를 들어 onPause()가 리턴된 시각부터 onResume()이 호출된 시각까지 액티비티는 강제종료가능 상태에 있다. 그것은 onPause()가 다시 리턴할 때까지는 다시 강제종료가능하지 않을 것이다.

    As noted in a later section, Processes and lifecycle, an activity that's not technically "killable" by this definition might still be killed by the system but that would happen only in extreme and dire circumstances when there is no other recourse.

    나중에 나오는 “프로세스와 생명주기” 섹션에서 언급하듯이, 이 정의에 의해서 기술적으로 “강제종료가능” 하지 않는 액티비티도 시스템에 의해 여전히 강제종료 될 수 있다 ? 하지만 이것은 다른 수단이 없을 때, 극도로 극단적인 상황에서만 발생할 것이다.

    Saving activity state

    When the system, rather than the user, shuts down an activity to conserve memory, the user may expect to return to the activity and find it in its previous state.

    사용자라기 보다는 시스템이 메모리를 절약하기 위해 액티비티를 종료시킬 때 사용자는 액티비티로 돌아가길 원할 수 있고, 그곳에서 액티비티의 이전 상태를 찾을 수도 있다.

    To capture that state before the activity is killed, you can implement an onSaveInstanceState() method for the activity. Android calls this method before making the activity vulnerable to being destroyed that is, before onPause() is called. It passes the method a Bundle object where you can record the dynamic state of the activity as name-value pairs. When the activity is again started, the Bundle is passed both to onCreate() and to a method that's called after onStart()onRestoreInstanceState(), so that either or both of them can recreate the captured state.

    액티비티가 강제종료되기 전의 상태를 보관하기 위해서, 여러분은 액티비티에 대한 onSaveInstanceState() 메쏘드를 구현할 수 있다. 안드로이드는 액티비티가 파괴될 수 있도록 만들기 전에 이 메쏘드를 호출한다 - 즉, onPause()가 호출되기 전에 호출한다. 그것은 여러분이 이름-값의 쌍key-value pair으로 액티비티의 동적 상태를 기록할 수 있는 번들Bundle 오브젝트를 그 메쏘드에 전달한다. 액티비티가 다시 시작될 때, 그 번들Bundle은 onCreate()와 onStart() 이후 호출되는 메쏘드인 onRestoreInstanceState() 메쏘드 둘 다에게 전달된다. 그러므로 그것들 중 하나 또는 둘 모두는 저장된 상태를 다시 만들 수 있다.

    Unlike onPause() and the other methods discussed earlier, onSaveInstanceState() and onRestoreInstanceState() are not lifecycle methods. They are not always called. For example, Android calls onSaveInstanceState() before the activity becomes vulnerable to being destroyed by the system, but does not bother calling it when the instance is actually being destroyed by a user action (such as pressing the BACK key). In that case, the user won't expect to return to the activity, so there's no reason to save its state.

    onPause()와 앞에서 논의되었던 다른 메쏘드들과는 다르게, onSaveInstance State()와 onRestoreInstanceState()는 생명주기 메쏘드가 아니다. 그것들은 항상 호출되지는 않는다. 예를 들어 안드로이드는 액티비티가 시스템에 의해 파괴되는 취약함에 도달하기 전에 onSaveInstanceState()를 호출한다. 그러나 인스턴스가 (BACK 키를 누르는 것 같은) 사용자 액션에 의해 실제로 파괴되고 있을 때에는 그것을 호출하려고 노력하지는 않는다. 그런 경우, 사용자는 그 액티비티로 돌아가는 것을 기대하지 않는다. 그러므로 그 상태를 저장할 이유가 없다.

    Because onSaveInstanceState() is not always called, you should use it only to record the transient state of the activity, not to store persistent data. Use onPause() for that purpose instead.

    onSaveInstanceState()는 언제나 호출되지 않기 때문에, 여러분은 영구적인 데이터를 저장하기 위해서가 아니라 액티비티의 일시적인 상태를 기록하기 위해서만 사용해야 한다. 그런 영구적인 데이터를 저장하는 목적을 위해서는 대신 onPause()를 사용하라.

    Coordinating activities

    When one activity starts another, they both experience lifecycle transitions. One pauses and may stop, while the other starts up. On occasion, you may need to coordinate these activities, one with the other.

    하나의 액티비티가 또 다른 액티비티를 시작할 때, 두 액티비티 모두는 생명주기 변화를 경험하게 된다. 하나는 멈추고pause 정지stop하게 되며, 반면에 다른 하나는 시작start된다. 경우에 따라 여러분은 이 액티비티들을 서로 간에 조화시키는 것이 필요할 수도 있다.

    The order of lifecycle callbacks is well defined, particularly when the two activities are in the same process:

    생명주기 콜백callback의 순서는 특히 두 개의 액티비티가 동일 프로세스 안에 있을 때 잘 정의된다.

    1. The current activity's onPause() method is called.
    2. Next, the starting activity's onCreate()onStart(), and onResume() methods are called in sequence.
    3. Then, if the starting activity is no longer visible on screen, its onStop() method is called.
    1. 현재 액티비티의 onPause() 메쏘드가 호출된다.
    2. 다음번에 시작되는 액티비티의 onCreate(),onStart(),그리고 onResume() 메쏘드가 차례로 호출된다.
    3. 그런 다음에, 만약 시작되는 액티비티가 화면에 더 이상 보이지 않으면, 그것의 onStop() 메쏘드가 호출된다.

    Service lifecycle

    A service can be used in two ways:

    서비스는 두 가지 방법으로 사용될 수 있다.

    • It can be started and allowed to run until someone stops it or it stops itself. In this mode, it's started by calling Context.startService() and stopped by calling Context.stopService(). It can stop itself by calling Service.stopSelf() or Service.stopSelfResult(). Only one stopService() call is needed to stop the service, no matter how many times startService() was called.
    • It can be operated programmatically using an interface that it defines and exports. Clients establish a connection to the Service object and use that connection to call into the service. The connection is established by calling Context.bindService(), and is closed by calling Context.unbindService(). Multiple clients can bind to the same service. If the service has not already been launched, bindService() can optionally launch it.

    • 서비스는 시작될 수 있으며, 누군가가 그것을 중지시키거나 또는 스스로 중지할 때까지 실행되는 것이 가능하다. 이 모드에서 서비스는 Context.startService()와 Context.stopService()의 호출에 의해 시작되고 중지된다. 서비스는 Service.stopSelf()나 Service.stopSelfResult()의 호출에 의해 스스로 중지할 수 있다. startService()가 얼마나 많이 호출되었는지와 상관없이, 오직 한 번의 stopService() 호출만이 그 서비스를 중지하기 위해 필요하다.
    • 서비스는 그것이 정의하고 제시하는 인터페이스를 사용해서 프로그램적으로 움직일 수 있다. 클라이언트는 서비스 오브젝트에 커넥션을 만들고, 서비스 내부를 호출하기 위해 커넥션을 사용한다. 커넥션은 Context.bindService()의 호출에 의해 만들어지며 Context.unbindService()의 호출에 의해 끊긴다. 많은 클라이언트가 동일한 서비스에 바인드 할 수 있다. 만약 서비스가 이미 런치되지 않았다면, bindService()는 선택적으로 그것을 런치할 수 있다.

    The two modes are not entirely separate. You can bind to a service that was started with startService(). For example, a background music service could be started by calling startService()with an Intent object that identifies the music to play. Only later, possibly when the user wants to exercise some control over the player or get information about the current song, would an activity establish a connection to the service by calling bindService(). In cases like this, stopService() will not actually stop the service until the last binding is closed.

    이런 두 가지 모드는 전체적으로 분리되지 않는다. 여러분은 startService()로 시작된 서비스에 바인드할 수 있다. 예를 들어 백그라운드background 뮤직 서비스는 재생할 음악을 식별해주는 인텐트 오브젝트를 파라미터로 가진 startService() 호출에 의해 시작될 수 있다. 그리고 나중에, 아마도 사용자가 플레이어를 약간 제어하려 하거나 또는 현재 재생중인 음악에 대한 정보를 얻고자 할 때, bindService()를 호출함으로써 액티비티가 그 서비스에 대한 커넥션을 만들게 할 수 있다. 이와 같은 경우, stopService()는 마지막 바인딩이 닫힐 때까지 그 서비스를 실제로 중지하지 않을 것이다.

    Like an activity, a service has lifecycle methods that you can implement to monitor changes in its state. But they are fewer than the activity methods only three and they are public, not protected:

    액티비티와 같이 서비스도 여러분이 그것의 상태 변화를 모니터링하기 위해 구현할 수 있는 생명주기 메쏘드를 가지고 있다. 그것은 단지 세 개이며, 프로텍티드protected가 아닌 퍼블릭public이다.

    void onCreate() 
    void onStart(Intent intent) 
    void onDestroy()

    By implementing these methods, you can monitor two nested loops of the service's lifecycle:

    이 메쏘드들을 구현함으로써 여러분은 서비스 생명주기에 있는 두 개의 네스티드 루프nested loop를 모니터링할 수 있다.

    • The entire lifetime of a service happens between the time onCreate() is called and the time onDestroy() returns. Like an activity, a service does its initial setup in onCreate(), and releases all remaining resources in onDestroy(). For example, a music playback service could create the thread where the music will be played in onCreate(), and then stop the thread in onDestroy().
    • The active lifetime of a service begins with a call to onStart(). This method is handed the Intent object that was passed to startService(). The music service would open the Intent to discover which music to play, and begin the playback.

      There's no equivalent callback for when the service stops no onStop() method.

    • 서비스의 인타이어 라이프타임(entire lifetime)은 onCreate()가 호출된 시간으로부터 onDestroy()가 리턴된 시간 사이에서 발생한다. 액티비티처럼, 서비스는 onCreate()에서 초기 설정을 하며 onDestroy()에서 존재하는 모든 리소스를 해제한다. 예를 들어 음악 재생 서비스는 onCreate()에서 재생할 음악이 있는 곳에 쓰레드를 만들며, 그런 다음 onDestroy()에서 해당 쓰레드를 종료시킨다.
    • 서비스의 액티브 라이프타임(active lifetime)은 onStart()를 호출함으로써 시작된다. 이 메쏘드에 startService()에 전달된 인텐트 오브젝트가 전달된다. 뮤직 서비스는 재생할 음악을 찾기 위해 그 인텐트를 오픈할 것이고, 그리고 나서 재생을 시작한다.

      서비스가 중지될 때에 해당되는 콜백, 즉 onStop() 메쏘드같은 것은 없다.

    The onCreate() and onDestroy() methods are called for all services, whether they're started by Context.startService() or Context.bindService(). However, onStart() is called only for services started by startService().

    서비스가 Context.startService() 또는 Context.bindService() 어느 것에 의해 시작되었는지와 상관없이, 모든 서비스에서 onCreate()와 onDestroy() 메쏘드는 호출된다. 하지만 onStart()는 오직 startService()에 의해 시작된 서비스에서만 호출된다.

    If a service permits others to bind to it, there are additional callback methods for it to implement:

    만일 서비스가 다른 것들이 자신에게 바인드하는 것을 허용한다면, 그것을 위해 추가적으로 구현해야 할 콜백 메쏘드들이 존재한다.

    IBinder onBind(Intent intent) 
    boolean onUnbind(Intent intent) 
    void onRebind(Intent intent)

    The onBind() callback is passed the Intent object that was passed to bindService and onUnbind() is handed the intent that was passed to unbindService(). If the service permits the binding,onBind() returns the communications channel that clients use to interact with the service. The onUnbind() method can ask for onRebind() to be called if a new client connects to the service.

    onBind() 콜백에는 bindService()에게 전달되었던 인텐트 오브젝트를 전달되고, onUnbind()에는 unbindService()에 전달되었던 인텐트가 전달된다. 만일 서비스가 바인딩을 허용한다면, onBind()는 클라이언트가 서비스와 상호작용하기 위해 사용할 커뮤니케이션 채널을 리턴한다. 만일 새로운 클라이언트가 서비스로 접속한다면, onUnbind() 메쏘드는 onRebind()가 호출되도록 요청할 수 있다.

    The following diagram illustrates the callback methods for a service. Although, it separates services that are created via startService from those created by bindService(), keep in mind that any service, no matter how it's started, can potentially allow clients to bind to it, so any service may receive onBind() and onUnbind() calls.

    아래의 다이어그램은 서비스에 대한 콜백 메쏘드들을 설명한다. 그것은 startService()에 의해 생생된 서비스와 bindService()에 의해 생성된 서비스를 구분하고 있음에도 불구하고, 서비스가 어떻게 시작되었다 할지라도, 임의의 서비스는 잠재적으로 클라이언트가 서비스에 바인드하는 것을 허용할 수 있다는 것에 유의하기 바란다. 그러므로 어떤 서비스든 onBind() 와 onUnbind() 호출을 받을 수도 있다.

    State diagram for Service callbacks.

    Broadcast receiver lifecycle

    A broadcast receiver has single callback method:

    브로드캐스트 리시버는 하나의 콜백 메쏘드를 가진다.

    void onReceive(Context curContext, Intent broadcastMsg)

    When a broadcast message arrives for the receiver, Android calls its onReceive() method and passes it the Intent object containing the message. The broadcast receiver is considered to be active only while it is executing this method. When onReceive() returns, it is inactive.

    리시버에게 브로드캐스트 메시지가 도착할 때, 안드로이드는 onReceive() 메쏘드를 호출하며 메시지를 포함하고 있는 인텐트 오브젝트를 onReceive() 메쏘드에 전달한다. 브로드캐스트 리시버는 이 메쏘드를 실행하는 동안에만 활성화되는 것으로 간주된다. onReceive()가 리턴될 때, 리시버는 비활성화된다.

    A process with an active broadcast receiver is protected from being killed. But a process with only inactive components can be killed by the system at any time, when the memory it consumes is needed by other processes.

    활성화된 브로드캐스트 리시버를 가지는 프로세스는 강제종료되는 것으로부터 보호된다. 그러나 단지 비활성화된 컴포넌트들을 가지는 프로세스는 그것이 낭비하고 있는 메모리가 다른 프로세스에 의해 필요할 때, 언제든 시스템에 의해 강제종료될 수 있다.

    This presents a problem when the response to a broadcast message is time consuming and, therefore, something that should be done in a separate thread, away from the main thread where other components of the user interface run. If onReceive() spawns the thread and then returns, the entire process, including the new thread, is judged to be inactive (unless other application components are active in the process), putting it in jeopardy of being killed. The solution to this problem is for onReceive() to start a service and let the service do the job, so the system knows that there is still active work being done in the process.

    이것은 브로드캐스트 메시지에 대한 응답이 시간이 소요될 때 문제를 만든다. 그러므로 어떤 것은 사용자 인터페이스에 대한 다른 컴포넌트가 있는 메인 쓰레드를 벗어나 별도의 쓰레드에서 처리되어야 한다. 만약 onReceive()가 쓰레드를 생성하고 그 다음 리턴된다면, 새로운 쓰레드를 포함하는 전체 프로세스는 비활성화(다른 애플리케이션 컴포넌트가 프로세스 안에서 액티브이지 않는 한)로 판정되고, 그것은 강제종료 되는 위험에 놓여진다. 이 문제의 해결책은 시스템이 프로세스 안에서 진행되는 활성화된 작업이 아직도 있다는 것을 알고 있도록, onReceive()에서 서비스를 시작시키고 해당 서비스가 이 작업을 하게끔 하는 것이다.

    The next section has more on the vulnerability of processes to being killed.

    다음 섹션에서 프로세스가 강제 중지되는 취약성에 대해서 더 자세히 다룬다.

    Processes and lifecycles

    The Android system tries to maintain an application process for as long as possible, but eventually it will need to remove old processes when memory runs low. To determine which processes to keep and which to kill, Android places each process into an "importance hierarchy" based on the components running in it and the state of those components. Processes with the lowest importance are eliminated first, then those with the next lowest, and so on. There are five levels in the hierarchy. The following list presents them in order of importance:

    안드로이드 시스템은 가능한 한 오랫동안 애플리케이션 프로세스가 유지될 수 있도록 노력한다. 그러나 메모리가 부족한 상태에 이르면, 결국에는 오래된 프로세스를 제거하는 것이 필요하게 될 것이다. 안드로이드는 어떤 프로세스를 유지하고 어떤 프로세스를 죽일 것인가를 결정하기 위해, 각각의 프로세스를 각각의 프로세스 내에서 실행되는 컴포넌트와 컴포넌트의 상태에 기반하는 “중요성 계층구조(importance hierarchy)” 속에서 유지한다. 가장 낮은 중요성을 가진 프로세스가 첫 번째로 제거되며, 그 다음에는 다음으로 낮은 중요성을 가진 것 순서로 제거된다. 그 계층구조에는 다섯 개의 단계가 존재한다. 아래의 목록은 그것들을 중요성 순서로 보여준다.

    1. foreground process is one that is required for what the user is currently doing. A process is considered to be in the foreground if any of the following conditions hold:
      • It is running an activity that the user is interacting with (the Activity object's onResume() method has been called).
      • It hosts a service that's bound to the activity that the user is interacting with.

      • It has a Service object that's executing one of its lifecycle callbacks (onCreate()onStart(), or onDestroy()).

      • It has a BroadcastReceiver object that's executing its onReceive() method.

      Only a few foreground processes will exist at any given time. They are killed only as a last resort if memory is so low that they cannot all continue to run. Generally, at that point, the device has reached a memory paging state, so killing some foreground processes is required to keep the user interface responsive.

    2. visible process is one that doesn't have any foreground components, but still can affect what the user sees on screen. A process is considered to be visible if either of the following conditions holds:

      • It hosts an activity that is not in the foreground, but is still visible to the user (its onPause() method has been called). This may occur, for example, if the foreground activity is a dialog that allows the previous activity to be seen behind it.
      • It hosts a service that's bound to a visible activity.

      A visible process is considered extremely important and will not be killed unless doing so is required to keep all foreground processes running.

    3. service process is one that is running a service that has been started with the startService() method and that does not fall into either of the two higher categories. Although service processes are not directly tied to anything the user sees, they are generally doing things that the user cares about (such as playing an mp3 in the background or downloading data on the network), so the system keeps them running unless there's not enough memory to retain them along with all foreground and visible processes.

    4. background process is one holding an activity that's not currently visible to the user (the Activity object's onStop() method has been called). These processes have no direct impact on the user experience, and can be killed at any time to reclaim memory for a foreground, visible, or service process. Usually there are many background processes running, so they are kept in an LRU (least recently used) list to ensure that the process with the activity that was most recently seen by the user is the last to be killed. If an activity implements its lifecycle methods correctly, and captures its current state, killing its process will not have a deleterious effect on the user experience.

    5. An empty process is one that doesn't hold any active application components. The only reason to keep such a process around is as a cache to improve startup time the next time a component needs to run in it. The system often kills these processes in order to balance overall system resources between process caches and the underlying kernel caches.

    1. 포어그라운드(foreground) 프로세스는 사용자가 현재 수행하고 있는 것을 위해 요구되는 프로세스이다. 만약 하나의 프로세스가 아래와 같은 조건을 보유하고 있다면, 그것은 포어그라운드 프로세스로 간주된다.
      • 프로세스가 사용자와 상호작용하는 액티비티(액티비티 오브젝트의 onResume() 메쏘드가 호출되었던 적이 있음)를 실행하고 있다.
      • 프로세스가 사용자와 상호작용하고 있는 액티비티에 연결되어진 서비스를 포함하고 있다.

      • 프로세스가 생명주기 콜백(onCreate(), onStart() 또는 onDestroy()) 중 하나를 실행하고 있는 서비스Service 오브젝트를 가지고 있다.

      • 프로세스가 onReceive() 메쏘드를 실행하고 있는 브로드캐스트 리시버BroadcastReceiver 오브젝트를 가지고 있다.

      오직 최소한의 프로세스들이 어떤 주어진 시간에 존재할 것이다. 그것은 그것들을 계속 수행하지 못할 만큼 메모리가 작은 경우와 같은 최후의 상황에서만 강제 종료된다. 일반적으로, 그런 시점에 디바이스는 메모리 페이징 상태에 이르게 되어 사용자 인터페이스에 대한 응답을 유지하기 위해 요구되는 약간의 포어그라운드 프로세스를 강제 종료시킨다.

    2. 비저블(visible) 프로세스는 어떤 포어그라운드foreground 컴포넌트도 보유하지 않은 프로세스이다. 그러나, 그것은 여전히 스크린 상에서 사용자가 보는 것에 영향을 미칠 수 있다. 만약 아래와 같은 조건을 보유하고 있다면 이 프로세스는 비쥬얼한 것으로 간주된다.

      • 프로세스가 포어그라운드가 아니지만 여전히 사용자에게 보이는 액티비티(액티비티의 onPause() 메쏘드가 호출되었던 것)를 보유하고 있다. 예를 들어 만약 포어그라운드 액티비티가 그것의 뒤에 이전 액티비티가 보이는 것을 허용하는 다이얼로그인 경우에 이것은 발생할 수 있다.
      • 프로세스가 비저블 액티비티에 연결된 서비스를 포함하고 있다.

      비저블 프로세스는 매우 중요한 것으로 간주되며, 모든 포어그라운드foreground 프로세스가 계속 실행되도록 유지하기 위해 그것을 죽여야 하지 않는 한 강제 종료되지 않을 것이다.

    3. 서비스(service) 프로세스는 startService() 메쏘드를 사용해서 시작된 서비스를 실행하고 있으면서, 위의 두 개의 카테고리에 속하지 않는 프로세스이다. 비록 서비스 프로세스는 사용자가 보는 어떤 것과도 직접 결부되지는 않지만, 그것들은 일반적으로 사용자가 신경쓰는 (백그라운에서 mp3를 재생하거나 네트워크에서 데이터를 다운로드하는 것 같은) 것들을 하고 있다. 그래서 시스템은 모든 포어그라운드foreground 프로세스와 비저블visible 프로세스를 계속 유지할 정도로 메모리가 충분치 않는 경우를 제외하고는, 이 프로세스를 실행 상태로 유지한다.

    4. 백그라운드(background) 프로세스는 현재 사용자의 눈에 보이지 않는 액티비티(액티비티 오브젝트의 onStop() 메쏘드가 호출되었던 것)를 보유하고 있는 프로세스이다. 이들 프로세스는 직접적으로 사용자의 행위에 영향을 주지 않으며, 포어그라운드foreground, 비저블visible, 서비스service 프로세스를 위한 메모리 재요청을 위해 언제든 강제 종료될 수 있다. 통상적으로 많은 백그라운드background 프로세스가 존재하고 있으며, 그러므로 그것들은 가장 최근에 사용자에게 보여진 액티비티를 가진 프로세스가 가장 최후에 강제 종료될 수 있도록 하기 위한 LRU(Least Recently Used, 최근에 가장 적게 사용된) 목록으로 관리된다. 만약 액티비티가 정확한 생명주기 메쏘드들을 구현하고 있고 그것들의 현재 상태를 정확하게 포착하고 있다면, 그것이 속한 프로세스가 강제종료되는 것은 사용자에게 유해한 영향을 끼치지 않을 것이다.

    5. 엠프티(empty) 프로세스는 어떤 형태의 활성화된 컴포넌트도 보유하고 있지 않는 프로세스이다. 이러한 프로세스를 유지하는 유일한 이유는, 그 안에서 다음 번에 실행되어야 하는 컴포넌트의 구동시간을 개선하기 위한 캐쉬cache로써의 역할 때문이다. 시스템은 프로세스 캐쉬와 하단에 놓여있는 커널 캐쉬 간의 시스템 전역에 걸친 리소스들에 대한 균형을 유지하기 위해 가끔 이런 프로세스를 강제 종료시킨다.

    Android ranks a process at the highest level it can, based upon the importance of the components currently active in the process. For example, if a process hosts a service and a visible activity, the process will be ranked as a visible process, not a service process.

    안드로이드는 프로세스 내에 현재 활성화되어 있는 컴포넌트의 중요성에 기초해서, 가능한 한 가장 높은 등급에 프로세스를 위치지운다. 예를 들어 만약 프로세스가 하나의 서비스와 하나의 비저블visible 액티비티를 보유하고 있다면, 그 프로세스는 서비스 프로세스가 아니라 비저블visible 프로세스로 위치지워질 것이다.

    In addition, a process's ranking may be increased because other processes are dependent on it. A process that is serving another process can never be ranked lower than the process it is serving. For example, if a content provider in process A is serving a client in process B, or if a service in process A is bound to a component in process B, process A will always be considered at least as important as process B.

    추가적으로, 프로세스의 등급은 그것에 관계된 다른 프로세스로 인해서 높여질 수도 있다. 다른 프로세스를 지원하는 프로세스는, 그것이 지원하는 프로세스보다 결코 더 낮은 등급을 가져서는 안된다. 예를 들어 만약 프로세스 A에 속하는 컨텐트 프로바이더가 프로세스 B에 속하는 하나의 클라이언트를 지원하거나, 또는 프로세스 A에 속하는 서비스가 프로세스 B에 속하는 어떤 컴포넌트에 연결되어 있다면 적어도 프로세스 A는 항상 프로세스 B가 만큼 중요하게 간주되어 한다.

    Because a process running a service is ranked higher than one with background activities, an activity that initiates a long-running operation might do well to start a service for that operation, rather than simply spawn a thread particularly if the operation will likely outlast the activity. Examples of this are playing music in the background and uploading a picture taken by the camera to a web site. Using a service guarantees that the operation will have at least "service process" priority, regardless of what happens to the activity. As noted in the Broadcast receiver lifecycle section earlier, this is the same reason that broadcast receivers should employ services rather than simply put time-consuming operations in a thread.

    서비스를 실행하는 프로세스가 백그라운드 액티비티를 보유하고 있는 프로세스보다 더 높은 등급을 보유하기 때문에, 오랜시간 동안 실행되는 오퍼레이션은 (특히 액티비티보다 더 오래 오퍼레이션이 지속될 것이라면) 간단하게 쓰레드를 생성하는 것보다 해당 오퍼레이션을 위한 서비스를 시작하는 것이 더 좋을 수 있다. 이런 예제들에는, 백그라운드background로 음악을 재생하는 것과 카메라로 찍은 사진을 웹 사이트로 업로드하는 것이 있다. 서비스를 사용하는 것은 액티비티에서 일어나는 것과 상관없이 그 오퍼레이션에 최소한 “서비스 프로세스” 우선순위를 보증할 것이다. 앞의 “브로드캐스트 리시버 생명주기” 섹션에서 언급했듯이, 이것이 바로 시간이 걸리는 오퍼레이션을 쓰레드로 구현하기보다는 오히려 서비스를 사용해서 구현해야 하는 같은 이유이다.

    0 0
    原创粉丝点击