Exploring Android Processes

数週間前、私は Android Studio でバグを修正していて、「android:process」タグに出会いました。 (私は Google の Android Studio チームで働いています。) このタグにより、android コンポーネントが実行されるプロセスを指定できることは知っていました。 しかし、Androidプロセスの背後にある細かい詳細と理由の多くは、私にとって未知のものでした。

Android プロセスの概要

Android は Linux に基づいているため、「Android システムは、アプリケーションに対して 1 つの実行スレッドで新しい Linux プロセスを開始します。 デフォルトでは、同じアプリケーションのすべてのコンポーネントは、同じプロセスとスレッド(「メイン」スレッドと呼ばれます)で実行されます。” (From: Process and Threads Overview)

一般に「メイン」スレッドは「UI」スレッドまたは「イベント」スレッドでもあり、UI の変更やイベント処理はすべてこのスレッドで行われるからです。 (例外: y̵o̵̵u ̵a̵̵e̵̵ ̵t̵h̵i̵̵̵ ̵b̵y̵̵ ̵u̵r̵e̵a̵d̵̵ ̵A̵n̵o̵t̵i̵o̵n̵s̵.̵ は、システムアプリでだけ、異なる MainThread と UIThread を持つことが可能だと勘違いしてたんだけど。 “ビルドツールは @MainThread@UiThread のアノテーションを互換性のあるものとして扱うので、@MainThread メソッドから @UiThread メソッドを呼び出すことも、その逆も可能です。 ただし、異なるスレッドに複数のビューを持つシステム アプリの場合、UI スレッドがメイン スレッドと異なる可能性があります。”)

デフォルトでは、メイン プロセス (とそれが起動するメイン スレッド) はアプリケーションの applicationId と同じプロセス名 (アプリの build.gradle で宣言) を使用して実行されます。 したがって、Android Studio でデフォルトのプロジェクトを作成すると、スレッド com.example.<username>.myapplication で実行される Android アプリと、コードに一致するデフォルト パッケージが得られます。

“android:process” タグは何をするか

デフォルトでは Android アプリには 1 つのプロセスのみが存在します。 すべてのコンポーネントは同じプロセス上で実行されます。 アプリケーションのマニフェストで新しいコンポーネントを宣言するとき、「android:process」タグを使用して、このコンポーネントの新しいプロセスを宣言することができます。 318>

<activity
android:name=".SettingsActivity"
android:process=":setting"
android:label="@string/title_activity_settings">
</activity>

上記のスニペットでは、ローカルの com.example.kelvinma.myapplication:setting プロセスで実行される SettingActivity を宣言しています。 (android:process」タグは4つのandroidコンポーネント(

  • Activity
  • Service
  • Receiver
  • Provider

アプリケーションタグ)に適用可能です。 Application タグに適用すると、アプリケーションのコンポーネントも、独自の android:process タグで上書きされない限り、android:process を継承します。

ApplicationId を変更するだけで済むのに、アプリケーション宣言にこのタグを使用する使用例がよく分かりません。

A short visual example

マルチプロセス アプリケーションを説明するために、私が Pomodoro アプリケーションでデフォルトのアクティビティを開始し、上記のスニペットを使用して、別のプロセスで実行するように SettingsActivity を変更したと仮定します。

$ ./adb shell ps | grep kelvin
u0_a61 32175 1669 1292180 47600 SyS_epoll_ b738f2b5 S com.example.kelvinhanma.pomodoro
u0_a61 32223 1669 1284796 43736 SyS_epoll_ b738f2b5 S com.example.kelvinhanma.pomodoro:setting

しかし、process タグで指定しない限り、すべてのコンポーネントはデフォルト プロセスで暗黙的に実行されます。 したがって、デフォルトのアクティビティに android:process=":setting" を追加し、別のアクティビティを開始すると、アプリには 2 つのプロセスがあります。

com.example.kelvinhanma.pomodoro:setting
com.example.kelvinhanma.pomodoro

開始したアクティビティにはプロセス タグが設定されていないため、デフォルト プロセスで開始されるため。

  1. アプリに独立して実行する必要がある個別のアクションがある場合。一般的な例としては、音楽再生アプリでは、デフォルト プロセスで UI を処理し、別のプロセスで音楽再生を処理します。 Android では、プロセスごとに RAM 使用量を制限しています。 そのため、複数のプロセスを実行することで、アプリの合計 RAM 制限を増やすことができます。 しかし、プロセスはメモリを共有しないため、プロセス間でシングルトンを共有することはできません。

Local vs Global process

プロセスのタイプは、プロセス タグに入力した値によって決まります。 コロン (“:”) で始まる場合、プロセスはアプリケーションに非公開のローカルなものです (完全なプロセス名は applicationId:processName となります)。 小文字で始まる場合は、グローバル プロセスです。

グローバル プロセスは、アプリケーション間で共有することができます。 多くの場合、ライブラリはグローバルプロセス上で実行されるので、複数のアプリケーションがプロセスを共有してメモリ使用量を削減できます。

android:process quiz

最後にいくつかのシナリオで、答えを予測できるかどうかを確認します。 android:process="com.example.kelvinhanma.pomodoro"

A: あなたのプロセスは変更されないので、これは許可されています。 無意味で愚かなことですが。

Q: 自分のプロセスを他のアプリのパッケージに設定するためにそれを使用した場合はどうなりますか? 私の端末でcom.example.kelvinhanma.pomodoroが動作しているとします。

同名のプロセスが 2 つできてしまいます。

./adb shell ps | grep kelvin
u0_a181 28008 630 4324212 66060 SyS_epoll_wait 0 S com.example.kelvinhanma.pomodoro
u0_a179 28287 630 4327384 66200 SyS_epoll_wait 0 S com.example.kelvinhanma.pomodoro

でも大丈夫です。 プロセス名は一意である必要はないのです。 ユーザーが異なり (u0_a181, u0_a179) 、プロセス ID が一意であることに注目してください。

この記事を楽しみ、何かを学んでいただけたなら幸いです。 何かが間違っていたら、遠慮なく教えてください!