アプリケーションの基礎

Android アプリは Java プログラミング言語で記述されています。Android SDK ツールは、データやリソース ファイルとともに、コードを APK(Android パッケージ)にコンパイルします。これは、.apk という接尾語の付いたアーカイブ ファイルです。 1 つの APK ファイルにはAndroid アプリのすべてのコンテンツが含まれており、Android 端末はアプリをインストールする際にこのファイルを使用します。

端末にインストールすると、各 Android アプリはそれぞれのセキュリティ サンドボックス内で動作します。

  • Android オペレーティング システムはマルチユーザーの Linux システムであり、各アプリが異なるユーザーになります。
  • デフォルトで、システムは各アプリに一意の Linux ユーザー ID を割り当てます(ID はシステムのみが使用し、アプリは ID を関知しません)。 アプリが割り当てられたユーザー ID のみがアプリ内のすべてのファイルにアクセスできるよう、システムがパーミッションを設定します。
  • 各プロセスにはそれぞれ独自の仮想マシン(VM)があるため、アプリのコードは他のアプリとは分離して実行します。
  • デフォルトで、すべてのアプリは独自の Linux プロセス上で実行します。Android はアプリのコンポーネントのいずれかを実行する必要があるときにプロセスを開始し、それが必要なくなったときや、システムが他のアプリ用にメモリを回復させる必要があるときにプロセスをシャットダウンします。

このようにして、Android システムは最小権限の原則を実装しています。つまり、デフォルトでは各アプリにはコンポーネントの動作に必要な分だけのアクセス権が与えられます。 これにより、パーミッションの与えられていないシステムの一部にアプリはアクセスできないという非常に安全性の高い環境が作り出されます。

ただし、アプリが他のアプリとデータを共有したり、システムのサービスにアクセスしたりする方法もあります。

  • 2 つのアプリで同一の Linux ユーザー ID を共有して、お互いのファイルにアクセスできるようにすることも可能です。 システム リソースを節約するため、同じユーザー ID を持つアプリを同じ Linux プロセス上で実行し、同じ VM を共有するよう設定することもできます(アプリを同じ証明書で署名する必要があります)。
  • アプリから、ユーザーの連絡先、SMS メッセージ、マウント可能なストレージ(SD カード)、カメラ、Bluetooth といった端末データにアクセスするためのパーミッションを要求できます。 ユーザーはこれらのパーミッションを明示的に付与する必要があります。 詳細については、システム パーミッションの使用をご覧ください。

以上が、システム内の Android アプリの基本的な仕組みです。続いて、このドキュメントでは次の内容について説明します。

  • アプリを定義するコア フレームワーク コンポーネント。
  • コンポーネントを宣言し、アプリの端末機能に必要なマニフェスト ファイル。
  • アプリでさまざまな端末構成の動作を最適化できるようにする、アプリコードから分離されたリソース。

アプリのコンポーネント

アプリのコンポーネントは、Android アプリに不可欠な構成要素です。各コンポーネントは、システムがアプリにアクセスするためのさまざまなエントリ ポイントになります。 すべてのコンポーネントがユーザーの実際のエントリ ポイントになるわけではなく、中にはお互いに依存関係にあるものもありますが、それぞれが独自のエンティティとして存在し、特定の役割を担っています。各コンポーネントはアプリの全体的な動作を定義する固有の構成要素です。

アプリのコンポーネントには、4 つのタイプがあります。それぞれのタイプは、まったく異なる目的を果たし、コンポーネントの作成や破棄方法を定義するライフサイクルもそれぞれ異なります。

アプリのコンポーネントのタイプは次の 4 つです。

アクティビティ
アクティビティは 1 つのユーザー インターフェースで 1 つの画面を表すものです。たとえば、メール アプリには新着メールの一覧を表示する 1 つのアクティビティと、メールを作成するアクティビティ、メールを閲覧するアクティビティがそれぞれ別にあります。 メールアプリでは、複数のアクティビティが一体となって結合したユーザー操作を実現しますが、それぞれは他のものから独立しています。 それにより、別のアプリで複数のアクティビティの中から、1 つのアクティビティを開始できるようになります(メールアプリが許可している場合)。 たとえば、カメラアプリでは写真を他のユーザーと共有するために、メール アプリの新規メールを作成するアクティビティを開始できます。

アクティビティは Activity のサブクラスとして実装されます。詳細については、デベロッパー ガイドのアクティビティをご覧ください。

サービス
サービスは、長期間の操作やリモート プロセスを処理するためにバックグラウンドで動作するコンポーネントです。 サービスは、ユーザー インターフェースを提供しません。 たとえば、サービスはユーザーが別のアプリを使用している間にバックグラウンドで音楽を再生したり、ユーザーが別のアクティビティを操作している間にそれを妨げることなくネットワークからデータを取得したりします。 アクティビティなどの別のコンポーネントは、サービスを開始して実行したり、それをバインドしたりして操作することもできます。

サービスは Service のサブクラスとして実装されます。詳細については、デベロッパー ガイドのサービスをご覧ください。

コンテンツ プロバイダ
コンテンツ プロバイダは、共有されているアプリデータを管理します。データは、ファイル システム、SQLite データベース、ウェブ、アプリがアクセスできる、あらゆる永続性のストレージに保存できます。 コンテンツ プロバイダを介して、他のアプリがデータをクエリしたり、修正したりすることもできます(コンテンツ プロバイダが許可している場合)。 たとえば、Android システムではユーザーの連絡先情報を管理するコンテンツ プロバイダを提供しています。 このように、適切なパーミッションさえあれば、アプリからコンテンツ プロバイダの一部(ContactsContract.Data など)に問い合わせて、特定の人物に関する情報を読み取ったり書き込んだりできます。

コンテンツ プロバイダは、アプリで非公開扱いの共有されていないデータを閲覧したり書き込んだりする場合にも役立ちます。 たとえば、Note Pad のサンプル アプリでは、コンテンツ プロバイダを使用してメモを保存します。

コンテンツ プロバイダは ContentProvider のサブクラスとして実装され、他のアプリがトランザクションを実行できるようにする API の標準セットを実装する必要があります。 詳細については、デベロッパー ガイドのコンテンツ プロバイダをご覧ください。

ブロードキャスト レシーバー
ブロードキャスト レシーバーは、システム全体のブロードキャスト アナウンスに応答するコンポーネントです。 たとえば、画面がオフになった、バッテリ残量が低い、写真が撮影されたなど、システムに起因するブロードキャストはたくさんあります。アプリでもブロードキャストを開始でき、たとえば他のアプリに、一部のデータが端末にダウンロードされ、利用可能になったことを伝えることもできます。 ブロードキャスト レシーバーがユーザー インターフェースを表示することはありませんが、ステータスバー通知を作成して、ブロードキャスト イベントの発生時にユーザーに警告できます。 一般的には、ブロードキャスト レシーバーは他のコンポーネントへの単なる「入り口」であり、最小限の操作を行うことが前提となっています。 たとえば、イベントに基づいた何らかの作業を実行するサービスを開始する場合などに適しています。

ブロードキャスト レシーバーは、BroadcastReceiver のサブクラスとして実装され、各ブロードキャストは Intent オブジェクトとして配信されます。 詳細については、BroadcastReceiver クラスをご覧ください。

Android ならではのシステムデザインによって、どのアプリケーションからでも別のアプリケーションを開始できます。 たとえば、ユーザーが端末のカメラで写真を撮影できるようにする場合、既にその機能を備えた別のアプリがあることを想定して、写真を撮影するアクティビティを自身で開発する代わりに、アプリがそれを使用できます。 カメラアプリを組み込んだり、コードにリンクしたりする必要もなく、単純に写真を撮影するカメラアプリのアクティビティを開始するだけです。 完了後、写真はアプリに戻り、それを使用することもできます。ユーザー側には、カメラがアプリの一部であるかのように見えます。

システムがコンポーネントを開始すると、そのアプリのプロセスを開始し(まだ実行していない場合)、コンポーネントが必要とするクラスをインスタンス化します。 たとえば、写真を撮影するカメラアプリのアクティビティをアプリで開始すると、そのアクティビティはアプリのプロセスではなく、カメラアプリのプロセスで実行します。そのため、他のシステムのアプリとは異なり、Android アプリのエントリ ポイントは 1 つではありません(たとえば、main() 関数はありません)。

システムは、他のアプリへのアクセスを制限するファイル許可を使用して各アプリを別々のプロセスで実行するため、アプリから他のアプリのコンポーネントを直接アクティベートできませんが、 Android システムはそれが可能です。そのため、他のアプリのコンポーネントをアクティベートするには、特定のコンポーネントを開始するインテントを指定するメッセージをシステムに配信する必要があります。 その後、システムが代わりにコンポーネントをアクティベートします。

コンポーネントをアクティベートする

4 つのコンポーネント タイプのなかで、アクティビティ、サービス、ブロードキャスト レシーバーの 3 つは、インテントと呼ばれる非同期メッセージによってアクティベートされます。コンポーネントがアプリに属していても他のものに属していても、インテントにより実行時に個別のコンポーネントがお互いに結び付けられます(他のコンポーネントからのアクションを要求するメッセンジャーのようなものです)。

インテントは Intent オブジェクトを使用して作成されます。このオブジェクトは特定のコンポーネントや特定のタイプのコンポーネントをアクティベートするようにメッセージを定義します。インテントはそれぞれ明示的、暗黙的のいずれかになります。

アクティビティとサービスでは、インテントが実行するアクション(「閲覧」したり「送信」したりする)を定義し、操作に使うデータ(特に、開始されるコンポーネントが知っておく必要があるデータ)の URI を指定することもできます。 たとえば、インテントはアクティビティに画像を表示したり、ウェブページを開いたりするアクティビティに対して要求を伝達します。 場合によっては、結果を受け取るアクティビティを開始でき、この場合にアクティビティが返す結果も Intent になります(たとえば、ユーザーが個人の連絡先を取り出し、それを返してくれるインテントを発行できます。返されたインテントには選択された連絡先を指す URI が含まれています)。

ブロードキャスト レシーバーの場合、インテントは単純にブロードキャストするアナウンスを定義します(たとえば、端末のバッテリ残量が少ないことを示すブロードキャストには、「バッテリが少ない」ことを示す既知のアクション文字列が含まれます)。

他のコンポーネント タイプであるコンテンツ プロバイダは、インテントではアクティベートされず、ContentResolver からの要求の対象となったときにアクティベートされます。 コンテンツ リゾルバが、コンテンツ プロバイダを使ってすべてのトランザクションを直接処理することで、プロバイダを使ってトランザクションを実行しているコンポーネントは処理する必要がなくなり、代わりに ContentResolver オブジェクトのメソッドを呼び出します。 これによりコンテンツ プロバイダと情報を要求しているコンポーネントとの間に(セキュリティ目的で)抽象的な層ができます。

各コンポーネント タイプのアクティベート用に、個別のメソッドが用意されています。

インテントの使用に関する詳細については、インテントとインテント フィルタのドキュメントをご覧ください。 特定のコンポーネントのアクティベートの詳細については、 アクティビティサービスBroadcastReceiverコンテンツ プロバイダのドキュメントでも説明しています。

マニフェスト ファイル

Android システムがコンポーネントを開始する前に、システムはアプリの AndroidManifest.xml ファイル(「マニフェスト」ファイル)を読み取って、コンポーネントの存在を認識する必要があります。 アプリはこのファイルですべてのコンポーネントを宣言し、このファイルはアプリ プロジェクトのディレクトリのルートに置く必要があります。

マニフェストはアプリのコンポーネントを宣言する他にも、次のようにさまざまな役割があります。

  • インターネット アクセスや、ユーザーの連絡先への読み取りアクセスなど、アプリに必要なユーザー パーミッションを識別する。
  • アプリが使用する API に基づいた、アプリが必要とする最小 API レベルを宣言する。
  • カメラ、Bluetooth サービス、マルチタッチ スクリーンなど、アプリで使用されるか必要とされるハードウェア機能やソフトウェア機能を宣言する。
  • Google マップ ライブラリなど、アプリにリンクする必要のある API ライブラリ(Android フレームワーク API は除く)。
  • その他の役割

コンポーネントを宣言する

マニフェストの主なタスクは、システムにアプリ コンポーネントに関する情報を与えることです。たとえば、マニフェスト ファイルではアクティビティを次のように宣言できます。

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

<application> 要素では、android:icon 属性でアプリを特定するアイコンのリソースを指します。

<activity> 要素では、android:name 属性で Activity サブクラスの完全修飾クラス名を指定し、android:label 属性でアクティビティのユーザーに表示するラベルとして使用する文字列を指定しています。

すべてのアプリ コンポーネントは、次の方法で宣言する必要があります。

  • <activity> アクティビティ用の要素
  • <service> サービス用の要素
  • <receiver> ブロードキャスト レシーバー用の要素
  • <provider> コンテンツ プロバイダ用の要素

ソースに含まれていながら、マニフェスト ファイルでは定義されていないアクティビティ、サービス、コンテンツ プロバイダはシステムには見えないため、実行されることはありません。 ただし、ブロードキャスト レシーバーはマニフェストで宣言するか、コードで動的に作成(BroadcastReceiver オブジェクトとして)して registerReceiver() を呼び出すことでシステムに登録できます。

アプリのマニフェスト ファイルの構築方法の詳細については、The AndroidManifest.xml File のドキュメントをご覧ください。

コンポーネントの機能を宣言する

コンポーネントをアクティベートするで説明したように、Intent を使用してアクティビティ、サービス、ブロードキャスト レシーバーを開始できます。 開始するには、インテントでターゲットのコンポーネントの名前を(コンポーネントのクラス名を使って)明示的に指定する必要があります。 ただし、インテントの本来の能力は、暗黙的インテントの概念にあります。 暗黙的インテントは、単に実行するアクションのタイプを記述し(どのデータ上でアクションを実行するかも任意で記述できます)、それによりシステムがそのアクションを実行できる端末上のコンポーネントを見つけて開始できます。 インテントで記述されたアクションを実行できるコンポーネントが複数ある場合は、使用するコンポーネントを 1 つ選択できます。

システムは、端末の他のアプリのマニフェスト ファイルに提供されたインテント フィルタが受け取ったインテントを比較して、インテントに応答できるコンポーネントを識別します。

アプリのマニフェストでアクティビティを宣言するとき、任意でアクティビティの機能を宣言するインテント フィルタを含めて、他のアプリからのインテントに応答できるようにできます。 <intent-filter> 要素を、コンポーネントを宣言している要素の子として追加することで、コンポーネントのインテント フィルタを宣言できます。

たとえば、新規メールを作成するアクティビティを持つメールアプリをビルドした場合、次のように「送信」インテント(新規メールを送信するための)に応答するインテント フィルタを宣言できます。

<manifest ... >
    ...
    <application ... >
        <activity android:name="com.example.project.ComposeEmailActivity">
            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <data android:type="*/*" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>
</manifest>

次に、別のアプリが ACTION_SEND アクションを持つインテントを作成し、startActivity() に渡す場合、ユーザーがメールを下書きして送信できるよう、システムがアクティビティを開始する場合があります。

インテント フィルタの作成の詳細については、インテントとインテント フィルタのドキュメントをご覧ください。

アプリの要件を宣言する

Android が搭載された端末は数多くありますが、すべての端末が同じ機能や性能を備えているわけではありません。 アプリに必要な機能を搭載していない端末にアプリをインストールしてしまわないよう、アプリがサポートする端末のタイプについてプロファイルで明確に定義し、マニフェスト ファイルで端末の要件やソフトウェア要件を宣言しておくことが重要です。 これらの宣言のほとんどはただの情報で、システムがそれを読み取ることはありませんが、Google Play などの外部サービスはそれを読み取って、ユーザーが端末からアプリを検索したときにフィルタを提供します。

たとえば、アプリでカメラを使用する必要があり、Android 2.1 で採用された API(API レベル 7)を使用する場合、次のようにマニフェスト ファイルでそれを要件として宣言する必要があります。

<manifest ... >
    <uses-feature android:name="android.hardware.camera.any"
                  android:required="true" />
    <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" />
    ...
</manifest>

カメラのない端末で、Android バージョンが 2.1 以下の場合は、Google Play からアプリをインストールできません。

ただし、アプリでカメラを使用するが、それが必須ではないということを宣言することもできます。 この場合、アプリで required 属性を "false" に設定し、端末にカメラがあるかどうかを実行時に確認して、必要に応じてすべてのカメラ機能を無効にする必要があります。

異なる端末でのアプリの互換性を管理する方法については、端末の互換性をご覧ください。

アプリのリソース

Android アプリは、コードだけで構成されているわけではありません。ソースコードから分離された画像、オーディオ ファイル、その他アプリの外観に関連するあらゆるリソースが必要です。 たとえば、アクティビティのアニメーション、メニュー、スタイル、色、レイアウトなどを XML ファイルで定義する必要があります。 アプリのリソースを使用すると、コードを修正することなく別のリソースセットを提供することにより、アプリのあらゆる特性を簡単にアップデートできるようになります。これにより、さまざまな端末の設定用(別の言語や画面サイズなど)にアプリを最適化できます。

Android プロジェクトに含めるすべてのリソースに対し、SDK ビルド ツールが一意の整数 ID を定義し、アプリコードや XML で定義された他のリソースからリソースにそれを使って参照できます。 たとえば、アプリに logo.png という名前の画像ファイルがある場合(res/drawable/ ディレクトリ内に保存)、SDK ツールが R.drawable.logo という名前のリソース ID を生成し、これを使って画像を参照してユーザー インターフェースに挿入できます。

リソースとソース コードを分離して提供する方法の最も重要な側面は、さまざまな端末設定に合わせて別のリソースを提供できるという点です。 たとえば、XML で UI 文字列を定義することで、その文字列を他の言語に翻訳して、それらの文字列を別のファイルに保存しておくことができます。 それを、リソースのディレクトリ名に付けた言語の修飾子(フランス語の文字列値なら res/values-fr/ のように)とユーザーの言語設定に基づいて、Android システムによって UI に適切な言語の文字列が適用されます。

Android では代替リソース用に多様な修飾子をサポートしています。修飾子は、リソースのディレクトリ名に含める短い文字列で、そのリソースを使用する端末構成を定義するものです。 例をもう 1 つ挙げると、端末の画面の向きやサイズによって、アクティビティのレイアウトを複数作成する必要があります。 たとえば、端末が縦方向(縦長)の場合、ボタンの付いたレイアウトを縦に並べ、端末が横方向(横長)の場合はボタンを横並びにする、といった場合です。 画面の方向によってレイアウトを変更するには、2 つの異なるレイアウトを定義して、それぞれのレイアウトのディレクトリ名に適切な修飾子を適用します。 そうすることで、現在の端末の向きによってシステムが自動的に適切なレイアウトを適用できます。

アプリケーションに含めることのできるリソースの種類や、異なる端末設定用の代替リソースの作成方法については、リソースの提供をご覧ください。

こちらもご覧ください。

インテントとインテント フィルタ
Intent API を使用して、アクティビティやサービスなどのアプリのコンポーネントをアクティベートする方法や、アプリのコンポーネントを他のアプリで利用できるようにする方法について説明しています。
アクティビティ
ユーザー インターフェースを使って独特のアプリケーション画面を提供する Activity クラスのインスタンスの作成方法について説明しています。
リソースの提供
特定の端末構成に対して代替リソースを提供する方法など、Android アプリでアプリのリソースをアプリコードから分離する仕組みについて説明しています。

関連ドキュメント

端末の互換性
あらゆるタイプの端末での Android の動作と、端末ごとにアプリを最適化したり、別の端末でのアプリの利用を制限したりする方法について説明しています。
システム パーミッション
アプリが特定の API を使用するのにユーザーの同意を必要とするパーミッション システムを使用して、アプリから特定の API へのアクセスを Android が制限する仕組みについて説明しています。