diff options
author | Trevor Johns <trevorjohns@google.com> | 2016-04-05 19:43:35 -0700 |
---|---|---|
committer | Trevor Johns <trevorjohns@google.com> | 2016-04-05 20:32:07 -0700 |
commit | a5060ee80dbb48bd7fc545d2aeeeb657b79893ea (patch) | |
tree | 842bb82e198dccade4bfb3ceafcc01f96083cd34 /docs/html-intl/intl/ko/guide/components/bound-services.jd | |
parent | ebf3261aa6d80ad4ca1df0fd0509961ff7a1914e (diff) | |
parent | 9577d31b10aa654d3ba63947e7733945a358395e (diff) |
Merge branch 'mnc-mr-docs' into mnc-ub-dev
Large merge to reconnect automerger for docs branch to mainline.
Conflicts:
docs/html-intl/intl/es/index.jd
docs/html-intl/intl/es/preview/download.jd
docs/html-intl/intl/es/preview/index.jd
docs/html-intl/intl/ja/index.jd
docs/html-intl/intl/ja/preview/download.jd
docs/html-intl/intl/ja/preview/index.jd
docs/html-intl/intl/ko/index.jd
docs/html-intl/intl/ko/preview/download.jd
docs/html-intl/intl/ko/preview/index.jd
docs/html-intl/intl/pt-br/index.jd
docs/html-intl/intl/pt-br/preview/download.jd
docs/html-intl/intl/pt-br/preview/index.jd
docs/html-intl/intl/ru/index.jd
docs/html-intl/intl/ru/preview/download.jd
docs/html-intl/intl/ru/preview/index.jd
docs/html-intl/intl/zh-cn/index.jd
docs/html-intl/intl/zh-cn/preview/download.jd
docs/html-intl/intl/zh-cn/preview/index.jd
docs/html-intl/intl/zh-tw/index.jd
docs/html-intl/intl/zh-tw/preview/download.jd
docs/html-intl/intl/zh-tw/preview/index.jd
docs/html/guide/topics/manifest/compatible-screens-element.jd
docs/html/guide/topics/manifest/uses-feature-element.jd
docs/html/preview/download.jd
docs/html/preview/features/runtime-permissions.jd
docs/html/sdk/index.jd
docs/html/tools/revisions/studio.jd
docs/html/tools/sdk/eclipse-adt.jd
docs/html/tools/support-library/features.jd
telephony/java/android/telephony/TelephonyManager.java
Bug: 28000173
Change-Id: Iacab0481175f1b32e0ac3bab98cde9e994100e94
Diffstat (limited to 'docs/html-intl/intl/ko/guide/components/bound-services.jd')
-rw-r--r-- | docs/html-intl/intl/ko/guide/components/bound-services.jd | 658 |
1 files changed, 658 insertions, 0 deletions
diff --git a/docs/html-intl/intl/ko/guide/components/bound-services.jd b/docs/html-intl/intl/ko/guide/components/bound-services.jd new file mode 100644 index 000000000000..bf97b260a7da --- /dev/null +++ b/docs/html-intl/intl/ko/guide/components/bound-services.jd @@ -0,0 +1,658 @@ +page.title=바인딩된 서비스 +parent.title=서비스 +parent.link=services.html +@jd:body + + +<div id="qv-wrapper"> +<ol id="qv"> +<h2>이 문서의 내용</h2> +<ol> + <li><a href="#Basics">기본 정보</a></li> + <li><a href="#Creating">바인딩된 서비스 생성</a> + <ol> + <li><a href="#Binder">바인더 클래스 확장</a></li> + <li><a href="#Messenger">메신저 사용</a></li> + </ol> + </li> + <li><a href="#Binding">서비스에 바인딩</a></li> + <li><a href="#Lifecycle">바인딩된 서비스 수명 주기 관리</a></li> +</ol> + +<h2>Key 클래스</h2> +<ol> + <li>{@link android.app.Service}</li> + <li>{@link android.content.ServiceConnection}</li> + <li>{@link android.os.IBinder}</li> +</ol> + +<h2>샘플</h2> +<ol> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code + RemoteService}</a></li> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code + LocalService}</a></li> +</ol> + +<h2>참고 항목</h2> +<ol> + <li><a href="{@docRoot}guide/components/services.html">서비스</a></li> +</ol> +</div> + + +<p>바인딩된 서비스란 클라이언트 서버 인터페이스 안의 서버를 말합니다. 바인딩된 서비스를 사용하면 구성 요소(활동 등)를 +서비스에 바인딩되게 하거나, 요청을 보내고 응답을 수신하며 심지어는 +프로세스간 통신(IPC)까지 수행할 수 있게 됩니다. 일반적으로 바인딩된 서비스는 다른 애플리케이션 +구성 요소를 도울 때까지만 살고 배경에서 무한히 실행되지 않습니다.</p> + +<p>이 문서는 다른 애플리케이션 구성 요소의 +서비스에 바인딩하는 방법을 포함하여 바인딩된 서비스를 만드는 방법을 보여줍니다. 하지만 일반적인 서비스에 관한 정보도 알아두는 것이 좋습니다. +서비스에서 알림을 전달하는 방법이나 서비스를 전경에서 실행되도록 설정하는 방법 등 여러 가지 +추가 정보를 알아보려면 <a href="{@docRoot}guide/components/services.html">서비스</a> 문서를 참조하십시오.</p> + + +<h2 id="Basics">기본 정보</h2> + +<p>바인딩된 서비스란 일종의 {@link android.app.Service} 클래스 구현으로, +이를 통해 다른 애플리케이션이 이 서비스에 바인딩하여 상호 작용할 수 있도록 해주는 것입니다. 한 서비스에 대한 바인딩을 제공하려면, +{@link android.app.Service#onBind onBind()} 콜백 메서드를 구현해야 합니다. +이 메서드는 클라이언트가 서비스와 상호 작용하는 데 사용하는 프로그래밍 인터페이스를 정의하는 {@link android.os.IBinder} 개체를 +반환합니다.</p> + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h3>시작된 서비스에 바인딩</h3> + +<p><a href="{@docRoot}guide/components/services.html">서비스</a> +문서에서 논의된 바와 같이, 시작되었으면서도 바인딩된 서비스를 만들 수 있습니다. 다시 말해, +{@link android.content.Context#startService startService()}를 호출하여 서비스를 시작할 수 있으며 +이를 통해 서비스가 무한히 실행되도록 할 수 있으며, {@link +android.content.Context#bindService bindService()}를 호출하면 클라이언트가 해당 서비스에 바인딩되도록 할 수 있다는 것입니다. + <p>서비스를 시작되고 바인딩되도록 허용한 다음 서비스가 시작되면 +시스템은 클라이언트가 모두 바인딩을 해제해도 서비스를 소멸시키지 <em>않습니다</em>. 대신, +직접 서비스를 확실히 중단시켜야 합니다. 그러려면 {@link android.app.Service#stopSelf stopSelf()} 또는 {@link +android.content.Context#stopService stopService()}를 호출하면 됩니다.</p> + +<p>보통은 {@link android.app.Service#onBind onBind()} +<em>또는</em> {@link android.app.Service#onStartCommand onStartCommand()} +중 한 가지만 구현하지만, 둘 모두 구현해야 할 때도 있습니다. 예를 들어, 음악 플레이어의 경우 서비스를 무한히 실행하면서 +바인딩도 제공하도록 허용하는 것이 유용하다는 결론을 내릴 수 있습니다. 이렇게 하면, 한 액티비티가 서비스로 하여금 음악을 재생하도록 +시작한 다음 사용자가 애플리케이션을 떠나더라도 음악을 계속 재생하도록 할 수 있습니다. 그런 다음, 사용자가 애플리케이션으로 +다시 돌아오면 이 액티비티가 서비스를 바인딩하여 재생 제어권을 다시 획득할 수 있습니다.</p> + +<p><a href="#Lifecycle">바인딩된 서비스 수명 주기 관리 +</a> 관련 섹션을 꼭 읽어보십시오. 시작된 서비스에 바인딩을 +추가할 때 서비스 수명 주기에 관한 자세한 정보를 얻을 수 있습니다.</p> +</div> +</div> + +<p>클라이언트가 서비스에 바인딩하려면 {@link android.content.Context#bindService +bindService()}를 호출하면 됩니다. 이 때, 반드시 {@link +android.content.ServiceConnection}의 구현을 제공해야 하며 이것이 서비스와의 연결을 모니터링합니다. {@link +android.content.Context#bindService bindService()} 메서드는 값 없이 즉시 반환됩니다. +그러나 Android 시스템이 클라이언트와 서비스 사이의 +연결을 만드는 경우, 시스템은 {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()}를 {@link +android.content.ServiceConnection}에서 호출하여 클라이언트가 서비스와 통신하는 데 사용할 수 있도록 {@link android.os.IBinder}를 +전달하게 됩니다.</p> + +<p>여러 클라이언트가 한 번에 서비스에 연결될 수 있습니다. 그러나, 시스템이 서비스의 +{@link android.app.Service#onBind onBind()} 메서드를 호출하여 {@link android.os.IBinder}를 검색하는 경우는 첫 번째 클라이언트가 +바인딩되는 경우뿐입니다. 시스템은 그 후 같은 {@link android.os.IBinder}를 바인딩되는 추가 +클라이언트 모두에 전달하며 이때는 {@link android.app.Service#onBind onBind()}를 다시 호출하지 않습니다.</p> + +<p>마지막 클라이언트가 서비스에서 바인딩을 해제하면 시스템은 서비스를 소멸시킵니다( +{@link android.content.Context#startService startService()}가 서비스를 시작했을 경우 제외).</p> + +<p>바인딩된 서비스를 구현할 때 가장 중요한 부분은 +{@link android.app.Service#onBind onBind()} 콜백 메서드가 반환하는 인터페이스를 정의하는 것입니다. +서비스의 {@link android.os.IBinder} 인터페이스를 정의하는 방법에는 몇 가지가 있고, 다음 +섹션에서는 각 기법에 관해 논의합니다.</p> + + + +<h2 id="Creating">바인딩된 서비스 생성</h2> + +<p>바인딩을 제공하는 서비스를 생성할 때는 클라이언트가 서비스와 상호 작용하는 데 사용할 수 있는 프로그래밍 인터페이스를 제공하는 {@link android.os.IBinder} +를 제공해야 합니다. +인터페이스를 정의하는 방법은 세 가지가 있습니다.</p> + +<dl> + <dt><a href="#Binder">바인더 클래스 확장</a></dt> + <dd>서비스가 본인의 애플리케이션 전용이며 클라이언트와 같은 과정으로 실행되는 +경우(이런 경우가 흔함), 인터페이스를 생성할 때 {@link android.os.Binder} 클래스를 + 확장하고 그 인스턴스를 +{@link android.app.Service#onBind onBind()}에서 반환하는 방식을 사용해야 합니다. 클라이언트가 {@link android.os.Binder}를 받으며, +이를 사용하여 {@link android.os.Binder} 구현 또는 심지어 {@link android.app.Service}에서 +사용할 수 있는 공개 메서드에 직접 액세스할 수 있습니다. + <p>이것은 서비스가 본인의 애플리케이션을 위해 단순히 배경에서 작동하는 요소에 그치는 경우 +선호되는 기법입니다. 인터페이스를 생성할 때 이 방식을 사용하지 않는 유일한 이유는 +서비스를 다른 애플리케이션에서나 별도의 프로세스에 걸쳐 사용하고 있는 경우뿐입니다.</dd> + + <dt><a href="#Messenger">메신저 사용</a></dt> + <dd>인터페이스를 여러 프로세스에 걸쳐 적용되도록 해야 하는 경우, 서비스에 대한 +인터페이스를 {@link android.os.Messenger}로 생성할 수 있습니다. +이 방식을 사용하면 서비스가 여러 가지 유형의 {@link +android.os.Message} 개체에 응답하는 {@link android.os.Handler}를 정의합니다. 이 {@link android.os.Handler} +가 {@link android.os.Messenger}의 기초이며, 이를 통해 클라이언트와 함께 {@link android.os.IBinder} +를 공유할 수 있게 되어 클라이언트가 {@link +android.os.Message} 개체를 사용해 서비스에 명령을 보낼 수 있게 해줍니다. 이외에도, 클라이언트가 자체적으로 {@link android.os.Messenger}를 +정의하여 서비스가 메시지를 돌려보낼 수 있도록 할 수도 있습니다. + <p>이것이 프로세스간 통신(IPC)을 수행하는 가장 간단한 방법입니다. {@link +android.os.Messenger}가 모든 요청을 단일 스레드에 대기하게 해서, 서비스를 스레드로부터 안전하게 +설계하지 않아도 되기 때문입니다.</p> + </dd> + + <dt>AIDL 사용하기</dt> + <dd>AIDL(Android Interface Definition Language)은 개체를 운영 체제가 이해할 수 있는 +원시 데이터로 구성 해제한 다음 여러 프로세스에 걸쳐 집결하여 IPC를 수행하기 위해 +필요한 모든 작업을 수행합니다. 이전 기법은 {@link android.os.Messenger}를 사용했는데, +사실 그 기본 구조가 AIDL을 기반으로 하고 있는 것입니다. 위에서 언급한 바와 같이 {@link android.os.Messenger}는 단일 스레드에 모든 클라이언트 요청 +대기열을 생성하므로 서비스는 한 번에 요청을 하나씩 수신합니다. 그러나, +서비스가 동시에 여러 요청을 처리하도록 하고 싶은 경우에는 AIDL을 직접 사용해도 +됩니다. 이 경우, 서비스가 다중 스레딩을 할 수 있어야 하며 스레드로부터 안전하게 구축되었어야 합니다. + <p>AIDL을 직접 사용하려면 +프로그래밍 인터페이스를 정의하는 {@code .aidl} 파일을 생성해야 합니다. Android SDK 도구는 +이 파일을 사용하여 인터페이스를 구현하고 IPC를 처리하는 추상 클래스를 생성하고, +그러면 개발자가 직접 이것을 서비스 내에서 확장하면 됩니다.</p> + </dd> +</dl> + + <p class="note"><strong>참고:</strong> 대부분의 애플리케이션의 경우, +바인딩된 서비스를 생성하기 위해 AIDL를 사용해서는 <strong>안 됩니다</strong>. +그러려면 다중 스레딩 기능이 필요할 수 있고, 따라서 더 복잡한 구현을 초래할 수 있기 때문입니다. 따라서 AIDL은 +대부분의 애플리케이션에 적합하지 않으므로 이 문서에서는 여러분의 서비스에 이를 이용하는 방법에 대해 다루지 않습니다. AIDL을 직접 사용해야 한다는 확신이 드는 경우, +<a href="{@docRoot}guide/components/aidl.html">AIDL</a> 문서를 참조하십시오. +</p> + + + + +<h3 id="Binder">바인더 클래스 확장</h3> + +<p>서비스를 사용하는 것이 로컬 애플리케이션뿐이고 여러 프로세스에 걸쳐 작동할 필요가 없는 경우, +나름의 {@link android.os.Binder} 클래스를 구현하여 +클라이언트로 하여금 서비스 내의 공개 메서드에 직접 액세스할 수 있도록 할 수도 있습니다.</p> + +<p class="note"><strong>참고:</strong> 이것은 클라이언트와 서비스가 +같은 애플리케이션 및 프로세스에 있는 경우에만 통하며, 이 경우가 가장 보편적입니다. 이 방식이 잘 통하는 경우를 예로 들면, +음악 애플리케이션에서 자체 서비스에 액티비티를 바인딩하여 배경에서 음악을 재생하도록 해야 하는 +경우가 있습니다.</p> + +<p>이렇게 설정하는 방법은 다음과 같습니다.</p> +<ol> + <li>서비스에서 다음 중 한 가지에 해당하는 {@link android.os.Binder}의 인스턴스를 생성합니다. + <ul> + <li>클라이언트가 호출할 수 있는 공개 메서드 포함</li> + <li>클라이언트가 호출할 수 있는 공개 메서드가 있는 현재{@link android.app.Service} +인스턴스를 반환</li> + <li>클라이언트가 호출할 수 있는 공개 메서드가 포함된 서비스가 호스팅하는 다른 클래스의 인스턴스를 반환 +</li> + </ul> + <li>{@link +android.app.Service#onBind onBind()} 콜백 메서드에서 이 {@link android.os.Binder}의 인스턴스를 반환합니다.</li> + <li>클라이언트의 경우, {@link android.os.Binder}를 {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} +콜백 메서드에서 받아 제공된 메서드를 사용해 서비스를 바인딩하기 위해 호출합니다.</li> +</ol> + +<p class="note"><strong>참고:</strong> 서비스와 클라이언트가 같은 애플리케이션에 +있어야 하는 것은 그래야만 클라이언트가 반환된 개체를 캐스팅하여 해당 API를 적절하게 호출할 수 있기 때문입니다. 또한 +서비스와 클라이언트는 같은 프로세스에 있어야 하기도 합니다. 이 기법에서는 +여러 프로세스에 걸친 집결 작업을 전혀 수행하지 않기 때문입니다.</p> + +<p>예컨대, 어떤 서비스가 클라이언트에게 {@link android.os.Binder} 구현을 통해 서비스 내의 +메서드에 액세스할 수 있도록 한다고 합시다.</p> + +<pre> +public class LocalService extends Service { + // Binder given to clients + private final IBinder mBinder = new LocalBinder(); + // Random number generator + private final Random mGenerator = new Random(); + + /** + * Class used for the client Binder. Because we know this service always + * runs in the same process as its clients, we don't need to deal with IPC. + */ + public class LocalBinder extends Binder { + LocalService getService() { + // Return this instance of LocalService so clients can call public methods + return LocalService.this; + } + } + + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + + /** method for clients */ + public int getRandomNumber() { + return mGenerator.nextInt(100); + } +} +</pre> + +<p>{@code LocalBinder}는 클라이언트에게 {@code LocalService}의 현재 인스턴스를 검색하기 위한 {@code getService()} 메서드 +를 제공합니다. 이렇게 하면 클라이언트가 서비스 내의 공개 메서드를 호출할 수 있습니다. + 클라이언트는 예컨대 서비스에서 {@code getRandomNumber()}를 호출할 수 있습니다.</p> + +<p>다음은 버튼을 클릭했을 때 {@code LocalService}에 바인딩되며 {@code getRandomNumber()} +를 호출하는 액티비티를 나타낸 것입니다.</p> + +<pre> +public class BindingActivity extends Activity { + LocalService mService; + boolean mBound = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + } + + @Override + protected void onStart() { + super.onStart(); + // Bind to LocalService + Intent intent = new Intent(this, LocalService.class); + bindService(intent, mConnection, Context.BIND_AUTO_CREATE); + } + + @Override + protected void onStop() { + super.onStop(); + // Unbind from the service + if (mBound) { + unbindService(mConnection); + mBound = false; + } + } + + /** Called when a button is clicked (the button in the layout file attaches to + * this method with the android:onClick attribute) */ + public void onButtonClick(View v) { + if (mBound) { + // Call a method from the LocalService. + // However, if this call were something that might hang, then this request should + // occur in a separate thread to avoid slowing down the activity performance. + int num = mService.getRandomNumber(); + Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show(); + } + } + + /** Defines callbacks for service binding, passed to bindService() */ + private ServiceConnection mConnection = new ServiceConnection() { + + @Override + public void onServiceConnected(ComponentName className, + IBinder service) { + // We've bound to LocalService, cast the IBinder and get LocalService instance + LocalBinder binder = (LocalBinder) service; + mService = binder.getService(); + mBound = true; + } + + @Override + public void onServiceDisconnected(ComponentName arg0) { + mBound = false; + } + }; +} +</pre> + +<p>위 예시는 클라이언트가 +{@link android.content.ServiceConnection} 구현과 {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} 콜백을 사용하여 서비스에 바인딩하는 방법을 보여줍니다. 다음 +섹션에서는 서비스에 바인딩하는 이러한 과정에 대해 좀 더 자세한 정보를 제공합니다.</p> + +<p class="note"><strong>참고:</strong> 위 예시에서는 서비스에서 분명히 바인딩을 해제하지는 않습니다. +그러나 모든 클라이언트는 적절한 시점에 바인딩을 해제해야 합니다(액티비티가 일시 중지될 때 등).</p> + +<p>더 많은 샘플 코드를 보려면 <a href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>에서 <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code +LocalService.java}</a> 클래스와 <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.html">{@code +LocalServiceActivities.java}</a> 클래스를 참조하십시오.</p> + + + + + +<h3 id="Messenger">메신저 사용</h3> + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h4>AIDL과 비교</h4> + <p>IPC를 수행해야 할 경우, 인터페이스에 대해 {@link android.os.Messenger}를 사용하는 것이 +AIDL로 구현하는 것보다 간단합니다. 왜냐하면 {@link android.os.Messenger}는 +모든 호출을 서비스에 대기시키지만 순수한 AIDL 인터페이스는 +서비스에 동시에 요청을 전송하여 다중 스레딩을 처리해야 하기 때문입니다.</p> + <p>대부분의 애플리이션에서는 서비스가 다중 스레딩을 수행할 필요가 없으므로 {@link +android.os.Messenger}를 사용하면 호출을 한 번에 하나씩 처리할 수 있습니다. 서비스가 +다중 스레딩되는 것이 중요한 경우, 인터페이스를 정의하는 데 <a href="{@docRoot}guide/components/aidl.html">AIDL</a>을 사용해야 합니다.</p> +</div> +</div> + +<p>서비스가 원격 프로세스와 통신해야 한다면 서비스에 인터페이스를 제공하는 데 +{@link android.os.Messenger}를 사용하면 됩니다. 이 기법을 사용하면 +AIDL을 쓰지 않고도 프로세스간 통신(IPC)을 수행할 수 있게 해줍니다.</p> + +<p>다음은 {@link android.os.Messenger} 사용 방법을 간략하게 요약한 것입니다.</p> + +<ul> + <li>서비스가 클라이언트로부터 각 호출에 대해 콜백을 받는 {@link android.os.Handler}를 +구현합니다.</li> + <li>{@link android.os.Handler}를 사용하여 {@link android.os.Messenger} 개체를 생성합니다 +(이것은 {@link android.os.Handler}에 대한 참조입니다).</li> + <li>{@link android.os.Messenger}가 {@link android.os.IBinder}를 생성하여 서비스가 +{@link android.app.Service#onBind onBind()}로부터 클라이언트에게 반환하도록 합니다.</li> + <li>클라이언트는 {@link android.os.IBinder}를 사용하여 {@link android.os.Messenger} +(서비스의 {@link android.os.Handler}를 참조)를 인스턴트화하고, 이를 이용하여 +{@link android.os.Message} 개체를 서비스에 전송합니다.</li> + <li>서비스가 각 {@link android.os.Message}를 {@link +android.os.Handler}로 수신합니다. 구체적으로는 {@link android.os.Handler#handleMessage +handleMessage()} 메서드를 사용합니다.</li> +</ul> + + +<p>이렇게 하면, 클라이언트가 서비스에서 호출할 "메서드"가 없습니다. 대신 클라이언트는 +"메시지"({@link android.os.Message} 개체)를 전달하여 서비스가 +{@link android.os.Handler}로 받을 수 있도록 합니다.</p> + +<p>다음은 {@link android.os.Messenger} 인터페이스를 사용하는 간단한 예시 서비스입니다.</p> + +<pre> +public class MessengerService extends Service { + /** Command to the service to display a message */ + static final int MSG_SAY_HELLO = 1; + + /** + * Handler of incoming messages from clients. + */ + class IncomingHandler extends Handler { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_SAY_HELLO: + Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show(); + break; + default: + super.handleMessage(msg); + } + } + } + + /** + * Target we publish for clients to send messages to IncomingHandler. + */ + final Messenger mMessenger = new Messenger(new IncomingHandler()); + + /** + * When binding to the service, we return an interface to our messenger + * for sending messages to the service. + */ + @Override + public IBinder onBind(Intent intent) { + Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show(); + return mMessenger.getBinder(); + } +} +</pre> + +<p>{@link android.os.Handler}의 {@link android.os.Handler#handleMessage handleMessage()} 메서드에서 +서비스가 수신되는 {@link android.os.Message}를 받고 +{@link android.os.Message#what} 구성원에 기초하여 무엇을 할지 결정한다는 점을 눈여겨 보십시오.</p> + +<p>클라이언트는 서비스가 반환한 {@link +android.os.IBinder}에 기초하여 {@link android.os.Messenger}를 생성하고 {@link +android.os.Messenger#send send()}로 메시지를 전송하기만 하면 됩니다. 예를 들어, 다음은 +서비스에 바인딩하여 {@code MSG_SAY_HELLO} 메시지를 서비스에 전달하는 간단한 액티비티입니다.</p> + +<pre> +public class ActivityMessenger extends Activity { + /** Messenger for communicating with the service. */ + Messenger mService = null; + + /** Flag indicating whether we have called bind on the service. */ + boolean mBound; + + /** + * Class for interacting with the main interface of the service. + */ + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + // This is called when the connection with the service has been + // established, giving us the object we can use to + // interact with the service. We are communicating with the + // service using a Messenger, so here we get a client-side + // representation of that from the raw IBinder object. + mService = new Messenger(service); + mBound = true; + } + + public void onServiceDisconnected(ComponentName className) { + // This is called when the connection with the service has been + // unexpectedly disconnected -- that is, its process crashed. + mService = null; + mBound = false; + } + }; + + public void sayHello(View v) { + if (!mBound) return; + // Create and send a message to the service, using a supported 'what' value + Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0); + try { + mService.send(msg); + } catch (RemoteException e) { + e.printStackTrace(); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + } + + @Override + protected void onStart() { + super.onStart(); + // Bind to the service + bindService(new Intent(this, MessengerService.class), mConnection, + Context.BIND_AUTO_CREATE); + } + + @Override + protected void onStop() { + super.onStop(); + // Unbind from the service + if (mBound) { + unbindService(mConnection); + mBound = false; + } + } +} +</pre> + +<p>이 예시에는 서비스가 클라이언트에 응답하는 방식이 나타나 있지 않다는 것을 유념하십시오. 서비스가 응답하게 하려면 + 클라이언트에도 {@link android.os.Messenger}를 생성해야 합니다. +클라이언트가 {@link android.content.ServiceConnection#onServiceConnected +onServiceConnected()} 콜백을 받으면 {@link android.os.Messenger#send send()}메서드의 {@link android.os.Message#replyTo} 매개변수에서 클라이언트의 {@link android.os.Messenger}를 포함하는 {@link android.os.Message}를 +서비스에 전송합니다. +</p> + +<p>양방향 메시지를 제공하는 방법의 예시는 <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.html">{@code +MessengerService.java}</a>(서비스) 및 <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.html">{@code +MessengerServiceActivities.java}</a>(클라이언트) 예시를 참조하십시오.</p> + + + + + +<h2 id="Binding">서비스에 바인딩</h2> + +<p>애플리케이션 구성 요소(클라이언트)를 서비스에 바인딩하려면 +{@link android.content.Context#bindService bindService()}를 호출하면 됩니다. 그러면 Android +system이 서비스의 {@link android.app.Service#onBind +onBind()} 메서드를 호출하고, 이는 서비스와의 상호 작용을 위해 {@link android.os.IBinder}를 반환합니다.</p> + +<p>바인딩은 비동기식입니다. {@link android.content.Context#bindService +bindService()}는 즉시 반환하고 클라이언트에게 {@link android.os.IBinder}를 반환하지 <em>않습니다</em>. + {@link android.os.IBinder}를 수신하려면 클라이언트는 {@link +android.content.ServiceConnection}의 인스턴스를 생성하여 이를 {@link android.content.Context#bindService +bindService()}에 전달해야 합니다. {@link android.content.ServiceConnection}에는 +{@link android.os.IBinder}를 전달하기 위해 시스템이 호출하는 콜백 메서드가 포함됩니다.</p> + +<p class="note"><strong>참고:</strong> 서비스에 바인딩할 수 있는 것은 액티비티, 서비스 및 +콘텐츠 제공자뿐입니다. 브로드캐스트 수신자로부터는 서비스에 바인딩할 수 <strong>없습니다</strong>.</p> + +<p>따라서, 클라이언트로부터 서비스에 바인딩하려면 다음과 같이 해야 합니다. </p> +<ol> + <li>{@link android.content.ServiceConnection}을 구현합니다. + <p>이 구현으로 두 가지 콜백 메서드를 재정의해야 합니다.</p> + <dl> + <dt>{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()}</dt> + <dd>시스템이 이것을 호출하여 서비스의 +{@link android.app.Service#onBind onBind()} 메서드가 반환한 {@link android.os.IBinder}를 전달합니다.</dd> + <dt>{@link android.content.ServiceConnection#onServiceDisconnected +onServiceDisconnected()}</dt> + <dd>Android 시스템이 이것을 호출하는 경우는 서비스로의 연결이 +예기치 못하게 끊어졌을 때, 즉 서비스가 충돌했거나 중단되었을 때 등입니다. +클라이언트가 바인딩을 해제한다고 이것이 호출되지는 <em>않습니다</em>.</dd> + </dl> + </li> + <li>{@link +android.content.Context#bindService bindService()}를 호출하고 {@link +android.content.ServiceConnection} 구현을 전달합니다. </li> + <li>시스템이 {@link android.content.ServiceConnection#onServiceConnected +onServiceConnected()} 콜백 메서드를 호출하면, 인터페이스가 정의한 메서드를 사용하여 +서비스에 호출을 시작해도 됩니다.</li> + <li>서비스로부터 연결을 해제하려면 {@link +android.content.Context#unbindService unbindService()}를 호출합니다. + <p>클라이언트가 소멸되면 이는 서비스에서 바인딩을 해제하게 되지만, +서비스와 상호 작용을 마쳤을 때 또는 액티비티가 일시 중지되었을 때에는 항상 바인딩을 해제해야 합니다. +이렇게 해야 서비스가 사용 중이 아닐 때에는 중지할 수 있습니다 +(바인딩과 바인딩 해제의 적절한 시기는 아래에서 좀 더 논의합니다).</p> + </li> +</ol> + +<p>예를 들어, 다음 코드 조각은 위와 같이 +<a href="#Binder">바인더 클래스를 확장해서</a> 생성한 서비스와 클라이언트를 연결합니다. 그러므로 이것이 해야 하는 일은 반환된 +{@link android.os.IBinder}를 {@code LocalService} 클래스에 캐스팅하고 {@code +LocalService} 인스턴스를 요청하는 것뿐입니다.</p> + +<pre> +LocalService mService; +private ServiceConnection mConnection = new ServiceConnection() { + // Called when the connection with the service is established + public void onServiceConnected(ComponentName className, IBinder service) { + // Because we have bound to an explicit + // service that is running in our own process, we can + // cast its IBinder to a concrete class and directly access it. + LocalBinder binder = (LocalBinder) service; + mService = binder.getService(); + mBound = true; + } + + // Called when the connection with the service disconnects unexpectedly + public void onServiceDisconnected(ComponentName className) { + Log.e(TAG, "onServiceDisconnected"); + mBound = false; + } +}; +</pre> + +<p>이 {@link android.content.ServiceConnection}이 있으면 클라이언트는 +이것을 {@link android.content.Context#bindService bindService()}에 전달하여 서비스에 바인딩할 수 있습니다. 예:</p> + +<pre> +Intent intent = new Intent(this, LocalService.class); +bindService(intent, mConnection, Context.BIND_AUTO_CREATE); +</pre> + +<ul> + <li>{@link android.content.Context#bindService bindService()}의 첫 번째 매개변수는 바인딩할 서비스를 명시적으로 명명하는 +{@link android.content.Intent}입니다(인텐트는 +암시적일 수 있음).</li> +<li>두 번째 매개변수는 {@link android.content.ServiceConnection} 개체입니다.</li> +<li>세 번째 매개변수는 바인딩 옵션을 나타내는 플래그입니다. 서비스를 생성하기 위해 보통은 {@link +android.content.Context#BIND_AUTO_CREATE}를 사용합니다(이미 살아 있는 상태가 아닌 경우). +가능한 기타 값은 {@link android.content.Context#BIND_DEBUG_UNBIND} + 및 {@link android.content.Context#BIND_NOT_FOREGROUND}, 또는 값이 없는 경우 {@code 0}입니다.</li> +</ul> + + +<h3>추가 참고 사항</h3> + +<p>다음은 서비스에 바인딩하는 데 관한 몇 가지 중요한 참고 사항입니다.</p> +<ul> + <li>항상 {@link android.os.DeadObjectException} 예외를 트래핑해야 합니다. +이것은 연결이 끊어지면 발생합니다. 원격 메서드에 의해 발생하는 예외는 이것뿐입니다.</li> + <li>개체는 여러 프로세스에 걸쳐 감안된 참조입니다. </li> + <li>일반적으로, 클라이언트의 수명 주기를 +결합하고 분해하는 순간을 일치시키면서 바인딩과 바인딩 해제를 페어링해야 합니다. 예: + <ul> + <li>액티비티가 눈에 보이는 동안에만 서비스와 상호 작용해야 한다면 +{@link android.app.Activity#onStart onStart()}에는 바인딩하고 {@link +android.app.Activity#onStop onStop()}에는 바인딩을 해제해야 합니다.</li> + <li> +배경에서 중단되었을 때도 액티비티가 응답을 받게 하고 싶다면 {@link android.app.Activity#onCreate onCreate()}에는 바인딩하고 +{@link android.app.Activity#onDestroy onDestroy()} 중에는 바인딩을 해제합니다. +이때, 사용자의 액티비티가 서비스가 실행되는 시간 전체에서(배경에서라도) 서비스를 사용한다는 것을 유념해야 합니다. +서비스가 다른 프로세스에 있을 경우, 사용자가 프로세스의 가중치를 높이면 시스템이 +이를 중단할 가능성이 높아집니다.</li> + </ul> + <p class="note"><strong>참고:</strong> 일반적으로는, 액티비티의 {@link android.app.Activity#onResume onResume()}와 {@link +android.app.Activity#onPause onPause()}에는 바인딩하거나 바인딩을 해제하지 <strong>말아야</strong> 합니다. 이러한 콜백은 모든 수명 주기 전환에서 발생하고 +이런 전환에서 발생하는 처리는 +최소한으로 유지해야 하기 때문입니다. 또한, +사용자 애플리케이션의 여러 액티비티가 동일한 서비스에 바인딩되었고 +두 액티비티 사이에 전환이 있을 경우, 현재 액티비티의 바인딩이 해제된 후(일시중지 중) 다음 액티비티가 바인딩하기 전(재개 중)에 +서비스가 제거되었다가 다시 생성될 수 있습니다 (수명 주기를 조절하기 위한 이러한 액티비티 전환은 +<a href="{@docRoot}guide/components/activities.html#CoordinatingActivities">액티비티</a> +문서에 설명되어 있습니다).</p> +</ul> + +<p>더 많은 샘플 코드를 보려면 <a href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>의 <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code +RemoteService.java}</a> 클래스를 참조하십시오.</p> + + + + + +<h2 id="Lifecycle">바인딩된 서비스 수명 주기 관리</h2> + +<p>서비스가 모든 클라이언트로부터 바인딩 해제되면, Android 시스템이 이를 소멸시킵니다(다만 +{@link android.app.Service#onStartCommand onStartCommand()}와도 함께 시작된 경우는 예외). +따라서, 서비스가 순전히 바인딩된 서비스일 경우에는 해당 서비스의 수명 주기를 관리하지 않아도 됩니다. +클라이언트에 바인딩되었는지를 근거로 Android 시스템이 대신 관리해주기 때문입니다.</p> + +<p>그러나 {@link android.app.Service#onStartCommand +onStartCommand()} 콜백 메서드를 구현하기로 선택하는 경우라면 서비스를 확실히 중지해야 합니다. +서비스가 현재 <em>시작된 것</em>으로 간주되기 때문입니다. 이런 경우, 서비스는 클라이언트에 바인딩되었는지 여부와 관계없이 +{@link android.app.Service#stopSelf()}와 함께 스스로 중단되거나 다른 구성 요소가{@link +android.content.Context#stopService stopService()}를 호출할 때까지 실행됩니다. +</p> + +<p>또한, 서비스가 시작되고 바인딩을 허용할 경우 시스템이 +{@link android.app.Service#onUnbind onUnbind()} 메서드를 호출하면 +{@code true}를 선택적으로 반환할 수 있습니다. 다음에 클라이언트가 서비스에 바인딩할 때({@link +android.app.Service#onBind onBind()}에 대한 호출을 수신하지 않고) {@link android.app.Service#onRebind +onRebind()}에 대한 호출을 받을지 여부에 따라 결정됩니다. {@link android.app.Service#onRebind +onRebind()}가 void를 반환하였지만 클라이언트가 +{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()} 콜백에서 {@link android.os.IBinder}를 여전히 수신합니다. +아래 그림 1은 이런 수명 주기의 논리를 나타냅니다.</p> + + +<img src="{@docRoot}images/fundamentals/service_binding_tree_lifecycle.png" alt="" /> +<p class="img-caption"><strong>그림 1.</strong> 시작되었으며 바인딩도 허용하는 서비스의 수명 주기입니다. +</p> + + +<p>시작된 서비스의 수명 주기에 관한 자세한 정보는 <a href="{@docRoot}guide/components/services.html#Lifecycle">서비스</a> 문서를 참조하십시오.</p> + + + + |