• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=プロセスとスレッド
2page.tags=lifecycle,background
3
4@jd:body
5
6<div id="qv-wrapper">
7<div id="qv">
8
9<h2>本書の内容</h2>
10<ol>
11<li><a href="#Processes">プロセス</a>
12  <ol>
13    <li><a href="#Lifecycle">プロセスのライフサイクル</a></li>
14  </ol>
15</li>
16<li><a href="#Threads">スレッド</a>
17  <ol>
18    <li><a href="#WorkerThreads">ワーカー スレッド</a></li>
19    <li><a href="#ThreadSafe">スレッド セーフのメソッド</a></li>
20  </ol>
21</li>
22<li><a href="#IPC">プロセス間通信(IPC)</a></li>
23</ol>
24
25</div>
26</div>
27
28<p>アプリケーション コンポーネントが開始し、アプリケーションに他に実行中のコンポーネントがない場合、Android システムは実行用のシングル スレッドを持つアプリケーション用の新しい Linux プロセスを開始します。
29
30デフォルトでは、同じアプリケーションのすべてのコンポーネントは同じプロセスとスレッド(「メイン」 スレッドと呼ばれます)で実行します。
31アプリケーション コンポーネントが開始したときに、既にそのアプリケーションのプロセスが存在する場合(アプリケーションからの他のコンポーネントが存在するため)、コンポーネントはそのプロセス内で開始し、同じ実行用のスレッドを使用します。
32
33ただし、アプリケーション内の別のコンポーネントを別のプロセスで実行するよう調整でき、あらゆるプロセスに対して追加のスレッドを作成できます。
34
35</p>
36
37<p>このドキュメントでは、Android アプリケーションでプロセスとスレッドがどのように動作するかについて説明します。</p>
38
39
40<h2 id="Processes">プロセス</h2>
41
42<p>デフォルトでは、同じアプリケーションのすべてのコンポーネントは同じプロセスで実行し、ほとんどのアプリケーションでこの動作を変更する必要はありません。
43ただし、特定のコンポーネントが属するプロセスを管理する必要がある場合は、マニフェスト ファイルでそれを行うことができます。
44</p>
45
46<p>コンポーネント要素の各タイプのマニフェスト エントリ(<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
47&lt;activity&gt;}</a>、<a href="{@docRoot}guide/topics/manifest/service-element.html">{@code
48&lt;service&gt;}</a>、<a href="{@docRoot}guide/topics/manifest/receiver-element.html">{@code
49&lt;receiver&gt;}</a>、<a href="{@docRoot}guide/topics/manifest/provider-element.html">{@code
50&lt;provider&gt;}</a>)は、コンポーネントを実行するプロセスを指定できる {@code android:process} 属性をサポートしています。&mdash;
51&mdash;この属性を設定して、各コンポーネントが独自のプロセスで実行するようにしたり、一部のコンポーネントで同じプロセスを共有し、残りのコンポーネントでは別のプロセスを使用するようにしたりできます。
52また、{@code android:process} を設定すると、異なるアプリケーションのコンポーネントを同じプロセスで実行させることもできます。この場合、アプリケーションが同じ Linux ユーザー ID を共有していて、同じ証明書で署名されている必要があります。
53&mdash;
54
55</p>
56
57<p><a href="{@docRoot}guide/topics/manifest/application-element.html">{@code
58&lt;application&gt;}</a> 要素も {@code android:process} 属性をサポートしており、すべてのコンポーネントに適用されるデフォルトの値を設定します。
59</p>
60
61<p>メモリの空きが少なくなり、早急にユーザーに提供する必要のあるプロセスが必要とする場合は、Android がプロセスをどこかの時点でシャットダウンするよう決定する場合があります。
62破棄されたプロセスで実行しているアプリケーション コンポーネントは、結果的に破棄されます。
63プロセスは、それらのコンポーネントの処理が再度発生したときに再開されます。
64</p>
65
66<p>破棄するプロセスを決定する際、Android システムはユーザーへの相対的な重要度を測ります。
67たとえば、画面に見えているアクティビティをホストするプロセスよりも、もう画面に見えていないアクティビティをホストするプロセスの方が先にシャットダウンされることになります。
68そのため、プロセスを停止するかどうかは、そのプロセスで実行しているコンポーネントの状態によって決まります。
69ここから、停止するプロセスを決定する規則について詳しく説明していきます。
70 </p>
71
72
73<h3 id="Lifecycle">プロセスのライフサイクル</h3>
74
75<p>Android システムは、可能な限り長期間アプリケーション プロセスを維持しようとしますが、新たに重要なプロセスが発生した際には、メモリを回収するために古いプロセスをいずれは削除する必要が生じます。
76どのプロセスを維持して、どのプロセスを強制終了するかを決定するため、システムはプロセスで実行しているコンポーネントとコンポーネントの状態に基づいて、各プロセスを「重要度の階層」に位置付けします。
77
78
79まず、重要度の最も低いプロセスが除去され、その後システム リソースを回復できるまで重要度の低い順に除去していきます。
80
81</p>
82
83<p>重要度の階層には 5 つのレベルがあります。次の一覧では、さまざまなプロセスのタイプを重要度の高い順に表しています(1 つ目のプロセスが<em>最も重要度が高く</em>、<em>最後に強制終了</em>されます)。
84
85</p>
86
87<ol>
88  <li><b>フォアグラウンド プロセス</b>
89    <p>ユーザーが現在行っている操作に必要なプロセスです。次の条件のいずれかにあてはまる場合、そのプロセスはフォアグラウンドにあるとみなされます。
90</p>
91
92      <ul>
93        <li>ユーザーが操作している {@link android.app.Activity} のホストになっている({@link
94android.app.Activity} の{@link android.app.Activity#onResume onResume()} メソッドが呼び出された)。
95</li>
96
97        <li>ユーザーが操作しているアクティビティにバインドされている {@link android.app.Service} のホストになっている。
98</li>
99
100        <li>「フォアグラウンド」 で実行中の {@link android.app.Service} のホストになっている(サービスが {@link android.app.Service#startForeground startForeground()} を呼び出した)。&mdash;
101
102
103        <li>{@link android.app.Service#onCreate onCreate()}、{@link android.app.Service#onStart
104onStart()}、{@link android.app.Service#onDestroy onDestroy()} のいずれかのライフサイクル コールバックを実行している {@link android.app.Service} のホストになっている。
105</li>
106
107        <li>{@link
108        android.content.BroadcastReceiver#onReceive onReceive()} メソッドを実行している {@link android.content.BroadcastReceiver} のホストになっている。</li>
109    </ul>
110
111    <p>通常は、2~3 個のフォアグラウンド プロセスが存在します。フォアグラウンド プロセスは、それらすべてを実行できなくなるほどメモリが少なくなると、最終手段として強制終了されます。
112&mdash;通常はその時点で、端末がメモリのページング状態に達しているため、ユーザー インターフェースのレスポンシブを維持するには一部のフォアグラウンド プロセスを強制終了する必要があります。
113
114</p></li>
115
116  <li><b>可視プロセス</b>
117    <p>フォアグラウンド コンポーネントはないものの、ユーザーに対して画面上に表示される内容に影響を与える可能性のあるプロセスです。
118次の条件のいずれかにあてはまる場合、そのプロセスは可視プロセスであるとみなされます。
119</p>
120
121      <ul>
122        <li>フォアグラウンドにないが、ユーザーに表示されている {@link android.app.Activity} のホストになっている({@link android.app.Activity#onPause onPause()} メソッドが呼び出された)。
123たとえば、フォアグラウンドのアクティビティがダイアログを開始したときに、前のアクティビティがその背後に見えている場合などがあります。
124
125</li>
126
127        <li>可視(またはフォアグラウンドの)アクティビティにバインドされている {@link android.app.Service} のホストになっている。
128</li>
129      </ul>
130
131      <p>可視プロセスは非常に重要度が高いため、フォアグラウンド プロセスの実行を維持するのに必要な場合のみ、強制終了されます。
132 </p>
133    </li>
134
135  <li><b>サービス プロセス</b>
136    <p>{@link
137android.content.Context#startService startService()} メソッドで開始されたサービスを実行するプロセスで、上の 2 つのカテゴリに分類されないものです。
138サービス プロセスは、ユーザーに表示される内容には直接関係ありませんが、ユーザーにとって必要な操作を実行している場合が多いため(バックグラウンドで音楽を再生したり、ネットワーク経由でデータをダウンロードしたりなど)、フォアグラウンド プロセスと可視プロセスのすべてと合わせて、それらを継続するのにメモリが不足した場合のみ強制終了されます。
139
140
141 </p>
142  </li>
143
144  <li><b>バックグラウンド プロセス</b>
145    <p>現在ユーザーに表示されていないアクティビティを有するプロセスです(アクティビティの {@link android.app.Activity#onStop onStop()} メソッドが呼び出された)。
146ユーザーの操作性に直接影響を与えるものではなく、フォアグラウンド プロセス、可視プロセス、サービス プロセス用にメモリを回収する必要があればいつでも強制終了されます。
147
148
149通常はバックグラウンドで実行するプロセスは多数あるため、最近ユーザーに表示されたアクティビティのあるプロセスを最後に強制終了するよう、LRU(最小使用頻度)リストに入れられます。
150
151アクティビティがライフサイクル メソッドを正確に実装し、現在の状態を保存する場合は、そのプロセスを強制終了しても、ユーザーがそのアクティビティに戻ったときに、アクティビティがすべての視覚的状態を復元するため、ユーザーの操作性に視覚的な影響はありません
152
153
154。状態の保存と復元の詳細については、「<a href="{@docRoot}guide/components/activities.html#SavingActivityState">Activities</a>」のドキュメントをご覧ください。
155</p>
156  </li>
157
158  <li><b>空のプロセス</b>
159    <p>アクティブなアプリケーション コンポーネントが 1 つも含まれていないプロセスです。このようなプロセスは、プロセスをキャッシュしておくことのみを目的として保持され、次回コンポーネントを実行する際の起動時間を向上させることができます。
160
161システムは、プロセスのキャッシュと下層のカーネル キャッシュとの間の全体的なシステム リソースのバランスを整える目的でこれらのシステムを頻繁に強制終了します。
162</p>
163  </li>
164</ol>
165
166
167  <p>Android では、プロセスで現在アクティブなコンポーネントの重要度に基づいて、あてはまるランクのなかで最も高いランクにプロセスを位置付けます。
168たとえば、サービス アクティビティと可視アクティビティの両方のホストとなっているプロセスは、サービス プロセスではなく、可視プロセスとして位置付けられます。
169</p>
170
171  <p>さらに、他のプロセスから依存されているプロセスの位置付けが上がる場合があります。他のプロセスのために動作しているプロセスは、その対象プロセスよりも下に位置付けられることはありません。
172&mdash;
173たとえば、プロセス A のコンテンツ プロバイダが、プロセス B のクライアントのために動作している場合や、プロセス A のサービスがプロセス B のコンポーネントにバインドされている場合、プロセス A の重要度は常にプロセス B 以上であるとみなされます。
174
175</p>
176
177  <p>サービスを実行するプロセスは、バックグラウンドのアクティビティを持つプロセスよりも上に位置付けされるため、長時間の操作を開始するアクティビティでは、特に、操作がアクティビティよりも長く続く場合、ワーカー スレッドを作成するよりもその操作の<a href="{@docRoot}guide/components/services.html">サービス</a>を開始する方がよいと考えられます。たとえば、ウェブサイトに写真をアップロードするアクティビティでは、ユーザーがアクティビティから離れた後もアップロードをバックグラウンドで続行できるよう、アップロードを実行するサービスを開始することをお勧めします。サービスを使用することで、アクティビティの状況に変わらず、その操作に「サービス プロセス」以上の優先度が保証されることになります。
178
179
180
181
182
183同じ理由から、ブロードキャスト レシーバーでもスレッドに長時間の処理を置くのではなく、サービスを採用するようお勧めします。
184</p>
185
186
187
188
189<h2 id="Threads">スレッド</h2>
190
191<p>アプリケーション起動の際、システムは アプリケーション実行用のスレッドを作成します。これは、「メイン スレッド」と呼ばれます。
192このスレッドは、イベント(描画イベントを含む)を適切なユーザー インターフェース ウィジェットに送信する役割を担うため非常に重要です。
193また、これはアプリケーションが Android UI ツールキット({@link
194android.widget} と {@link android.view} パッケージからのコンポーネント)からのコンポーネントとやり取りをするスレッドでもあります。
195そのため、メイン スレッドは UI スレッドと呼ばれることもあります。
196</p>
197
198<p>コンポーネントのインスタンスごとに別のスレッドが作成されることは<em>ありません</em>。同じプロセスで実行するすべてのコンポーネントは UI スレッドでインスタンス化され、スレッドから送られた各コンポーネントをシステムが呼び出します。
199
200結果的に、システムのコールバック(ユーザー操作を報告する {@link android.view.View#onKeyDown onKeyDown()} やライフサイクル コールバック メソッドなど)に応答するメソッドは常にプロセスの UI スレッドで実行することになります。
201
202</p>
203
204<p>たとえば、ユーザーが画面上のボタンをタッチすると、アプリの UI スレッドがタッチ イベントをウィジェットに送信し、ウィジェットがそのタッチされた状態を設定してイベント キューに無効化の要求を投稿します。
205
206UI スレッドが要求をキューから取り出し、ウィジェットに自身を描画するよう通知します。
207</p>
208
209<p>アプリがユーザー操作に応答して集中的な動作を実行する場合、アプリケーションを正しく実装していない限りこのシングル スレッド モデルではパフォーマンスの低下につながる可能性があります。
210具体的には、すべてが UI スレッドで行われている場合、長ネットワークへのアクセスやデータベースへの問い合わせといった時間のかかる操作を実行すると UI 全体をブロックしてしまいます。スレッドがブロックされると、描画イベントを含むすべてのイベントを送信できなくなります。
211
212
213ユーザー側には、アプリケーションがハングしたように見えます。
214さらには、UI スレッドが数秒以上(現時点では 5 秒以上)ブロックされると、ユーザーに<a href="http://developer.android.com/guide/practices/responsiveness.html">「アプリケーションが応答していません」</a>のダイアログが表示されます。
215
216ユーザーはアプリケーションを停止するか、不快な場合はアンインストールしてしまう可能性があります。
217</p>
218
219<p>また、Android UI ツールキットはスレッド セーフ<em>ではありません</em>。そのため、ワーカー スレッドから UI を操作できません。すべての操作は、UI スレッドから行う必要があります。
220&mdash;
221そのため、Android のシングル スレッド モデルには 2 つの明快なルールがあります。</p>
222
223<ol>
224<li>UI スレッドをブロックしない
225<li>UI スレッド以外から Android UI ツールキットにアクセスしない
226</ol>
227
228<h3 id="WorkerThreads">ワーカー スレッド</h3>
229
230<p>上記で説明したシングル スレッド モデルにより、アプリケーションの UI の応答性のためにも UI スレッドをブロックしないことが不可欠です。
231即座に実行する必要のない操作の場合は、別のスレッド(「バックグラウンド」スレッドや「ワーカー」スレッド)で実行するようにする必要があります。
232
233</p>
234
235<p>例として、別のスレッドから画像をダウンロードして {@link android.widget.ImageView} に表示するクリック リスナのコードの一部を次に示します。
236</p>
237
238<pre>
239public void onClick(View v) {
240    new Thread(new Runnable() {
241        public void run() {
242            Bitmap b = loadImageFromNetwork("http://example.com/image.png");
243            mImageView.setImageBitmap(b);
244        }
245    }).start();
246}
247</pre>
248
249<p>ここでは、ネットワークの操作を処理する新しいスレッドを作成しているため、一見問題ないように見えます。
250ただし、これは<em>UI スレッド以外から Android UI ツールキットにアクセスしない</em>というシングルスレッド モデルの 2 つ目のルールに違反しています。このサンプルは、UI スレッドではなくワーカー スレッドから {@link
251android.widget.ImageView} を変更しています。&mdash;
252結果として、未定義かつ予想外の動作を引き起こし、追跡が難しく時間のかかる作業になってしまいます。
253</p>
254
255<p>この問題を修正するため、Android には UI スレッド以外からのアクセス方法がいくつか用意されています。
256使用できるメソッドは次のとおりです。</p>
257
258<ul>
259<li>{@link android.app.Activity#runOnUiThread(java.lang.Runnable)
260Activity.runOnUiThread(Runnable)}</li>
261<li>{@link android.view.View#post(java.lang.Runnable) View.post(Runnable)}</li>
262<li>{@link android.view.View#postDelayed(java.lang.Runnable, long) View.postDelayed(Runnable,
263long)}</li>
264</ul>
265
266<p>たとえば、上記のコードは {@link
267android.view.View#post(java.lang.Runnable) View.post(Runnable)} メソッドを使用して修正できます。</p>
268
269<pre>
270public void onClick(View v) {
271    new Thread(new Runnable() {
272        public void run() {
273            final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
274            mImageView.post(new Runnable() {
275                public void run() {
276                    mImageView.setImageBitmap(bitmap);
277                }
278            });
279        }
280    }).start();
281}
282</pre>
283
284<p>これで、この実装がスレッドセーフになりました。ネットワーク操作は別のスレッドから実行され、{@link android.widget.ImageView} は UI スレッドから操作されます。
285</p>
286
287<p>ただし、操作が複雑になるにつれて、この種のコードも複雑化してメンテナンスも難しくなります。
288ワーカー スレッドとのより複雑なやり取りを処理するため、ワーカー スレッドで {@link android.os.Handler} を使うと、UI スレッドから配信されたメッセージを処理できます。
289
290ただし、最善なのは{@link android.os.AsyncTask} クラスを拡張することであり、これにより UI を操作する必要のあるワーカー スレッドのタスクの実行を簡素化できます。
291</p>
292
293
294<h4 id="AsyncTask">AsyncTask を使用する</h4>
295
296<p>{@link android.os.AsyncTask} では、ユーザー インターフェースに非同期の処理を実行できます。
297スレッドやハンドラを自身で処理する必要なく、ワーカー スレッドの操作をブロックし、結果を UI スレッドに発行します。
298</p>
299
300<p>これを使用するには、{@link android.os.AsyncTask} をサブクラス化し、バックグラウンド スレッドのプール内で実行する {@link
301android.os.AsyncTask#doInBackground doInBackground()} コールバック メソッドを実装する必要があります。
302UI を更新するには、{@link
303android.os.AsyncTask#onPostExecute onPostExecute()} を実装します。これは {@link
304android.os.AsyncTask#doInBackground doInBackground()} からの結果を配信し、UI スレッド内で実行されるため、UI を安全に更新できます。その後、UI スレッドから {@link android.os.AsyncTask#execute execute()} を呼び出してタスクを実行できます。
305
306</p>
307
308<p>たとえば、次のように {@link android.os.AsyncTask} を使って前出の例を実装できます。
309</p>
310
311<pre>
312public void onClick(View v) {
313    new DownloadImageTask().execute("http://example.com/image.png");
314}
315
316private class DownloadImageTask extends AsyncTask&lt;String, Void, Bitmap&gt; {
317    /** The system calls this to perform work in a worker thread and
318      * delivers it the parameters given to AsyncTask.execute() */
319    protected Bitmap doInBackground(String... urls) {
320        return loadImageFromNetwork(urls[0]);
321    }
322
323    /** The system calls this to perform work in the UI thread and delivers
324      * the result from doInBackground() */
325    protected void onPostExecute(Bitmap result) {
326        mImageView.setImageBitmap(result);
327    }
328}
329</pre>
330
331<p>ワーカー スレッドで処理される作業と、UI スレッドで処理される作業が分けられたため、UI は安全に、コードはシンプルになりました。
332</p>
333
334<p>このクラスの使用方法をより深く理解するには {@link android.os.AsyncTask} に目を通す必要がありますが、ここに、その仕組みについて簡単に挙げておきます。
335</p>
336
337<ul>
338<li>ジェネリックを使ってパラメータのタイプ、進捗の値、タスクの最終値を指定できます
339</li>
340<li>{@link android.os.AsyncTask#doInBackground doInBackground()} メソッドがワーカー スレッド上で自動的に実行されます
341</li>
342<li>{@link android.os.AsyncTask#onPreExecute onPreExecute()}、{@link
343android.os.AsyncTask#onPostExecute onPostExecute()}、{@link
344android.os.AsyncTask#onProgressUpdate onProgressUpdate()}はすべて UI スレッドで呼び出されます</li>
345<li>{@link android.os.AsyncTask#doInBackground doInBackground()} から返される値は、{@link android.os.AsyncTask#onPostExecute onPostExecute()} に送られます
346</li>
347<li>{@link android.os.AsyncTask#publishProgress publishProgress()} は、{@link
348android.os.AsyncTask#doInBackground doInBackground()} でいつでも呼び出すことができます。UI スレッドで {@link
349android.os.AsyncTask#onProgressUpdate onProgressUpdate()} を実行できます</li>
350<li>いつでも、どのスレッドからでもタスクをキャンセルできます</li>
351</ul>
352
353<p class="caution"><strong>警告:</strong> ワーカー スレッドの使用時に発生する可能性のあるもう 1 つの問題として、<a href="{@docRoot}guide/topics/resources/runtime-changes.html">実行時の設定が変更</a>された(ユーザーが画面の向きを変えた場合など)ことによってアクティビティが予期せず再起動され、ワーカー スレッドが破棄されてしまうことがあります。
354
355このような再起動の間タスクを維持する方法、アクティビティが破棄されたときの正しいタスクのキャンセル方法については、<a href="http://code.google.com/p/shelves/">Shelves</a> のサンプル アプリケーションのソース コードをご覧ください。
356
357</p>
358
359
360<h3 id="ThreadSafe">スレッド セーフのメソッド</h3>
361
362<p> 状況によっては、実装したメソッドが複数のスレッドから呼び出されることがあり、その場合はメソッドがスレッドセーフになるよう作成する必要があります。
363 </p>
364
365<p>主に、<a href="{@docRoot}guide/components/bound-services.html">バインドされたサービス</a>のメソッドなど、リモートで呼び出されるメソッドなどがこれに該当します。&mdash;{@link android.os.IBinder} に実装されたメソッドへの呼び出しが、{@link android.os.IBinder IBinder} を実行しているプロセスと同じプロセスで発生した場合、メソッドは呼び出し側のスレッドで実行されます。ただし、呼び出しが別のプロセスで起こった場合は、メソッドはシステムが {@link android.os.IBinder
366IBinder} と同じプロセスに保持するスレッドのプールから選ばれたスレッドで実行されます(プロセスの UI スレッドでは実行されません)。
367
368
369
370たとえば、サービスの {@link android.app.Service#onBind onBind()} メソッドがサービスのプロセスの UI スレッドから呼び出されるのに対して、{@link android.app.Service#onBind
371onBind()} が返すオブジェクトで実装されたメソッド(RPC メソッドを実装するサブクラスなど)は、プール内のスレッドから呼び出されます。
372
373
374サービスは複数のクライアントを持てるため、複数のプール スレッドが同じ {@link android.os.IBinder IBinder} メソッドを同時に動かすことができます。このため、{@link android.os.IBinder
375IBinder} メソッドはスレッドセーフになるよう実装する必要があります。
376</p>
377
378<p> 同様に、コンテンツ プロバイダは他のプロセスから送られたデータ要求を受け取ることができます。{@link android.content.ContentResolver} クラスと {@link android.content.ContentProvider} クラスによってプロセス間通信がどのように管理されているかが見えなくなりますが、それらの要求に応答する {@link
379android.content.ContentProvider} メソッド({@link
380android.content.ContentProvider#query query()}、 {@link android.content.ContentProvider#insert
381insert()}、{@link android.content.ContentProvider#delete delete()}、{@link
382android.content.ContentProvider#update update()}、{@link android.content.ContentProvider#getType
383getType()})は、プロセスの UI スレッドではなく、コンテンツ プロバイダのプロセスにあるスレッドのプールから呼び出されます。
384
385
386&mdash;&mdash;これらのメソッドは同時に複数のスレッドから呼び出される可能性があるため、先ほどと同様にスレッドセーフになるよう実装する必要があります。
387 </p>
388
389
390<h2 id="IPC">プロセス間通信(IPC)</h2>
391
392<p>Android では、リモート プロシージャ コール(RPC)を使ったプロセス間通信のメカニズムを備えており、メソッドはアクティビティや他のアプリケーション コンポーネントから呼び出された後に、リモート(別のプロセス)で実行され、結果を呼び出し側に返します。
393
394
395これにより、メソッドの呼び出しとそのデータをオペレーティング システムが理解できるレベルまで分解し、ローカル プロセスとアドレス空間からリモート プロセスとアドレス空間にそれを送信して、そこで呼び出しが再度組み立てて、再現します。
396
397その後、戻り値が逆方向に伝達されます。
398Android ではこれらの IPC トランザクションを実行するためのすべてのコードが用意されているため、開発者は RPC のプログラミング インターフェースの定義と実装に集中できます。
399 </p>
400
401<p>IPC を実行するには、アプリケーションが {@link
402android.content.Context#bindService bindService()} を使ってサービスにバインドされている必要があります。詳細については、デベロッパー ガイドの「<a href="{@docRoot}guide/components/services.html">サービス</a>」をご覧ください。</p>
403
404
405<!--
406<h2>Beginner's Path</h2>
407
408<p>For information about how to perform work in the background for an indefinite period of time
409(without a user interface), continue with the <b><a
410href="{@docRoot}guide/components/services.html">Services</a></b> document.</p>
411-->
412