アプリの基礎

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

各 Android アプリはそれぞれのセキュリティ サンドボックス内で動作し、以下の Android のセキュリティ機能により保護されています。

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

Android システムには「最小権限の原則」が適用されています。つまり、デフォルトでは各アプリにコンポーネントの動作に必要な分だけのアクセス権が与えられます。これにより、パーミッションの与えられていないシステムの部分にアプリはアクセスできないという非常に安全性の高い環境が作り出されます。ただし、次のように、アプリが他のアプリとデータを共有したり、システムのサービスにアクセスしたりするための方法はあります。

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

続いて、このドキュメントでは次のコンセプトについて説明します。

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

アプリのコンポーネント

アプリのコンポーネントは Android アプリに不可欠な構成要素です。各コンポーネントは、システムやユーザーがアプリに入るエントリ ポイントになります。一部のコンポーネントは他のコンポーネントに依存しています。

アプリのコンポーネントには 4 つのタイプがあります。

  • アクティビティ
  • サービス
  • ブロードキャスト レシーバ
  • コンテンツ プロバイダ

各タイプは異なる目的を果たし、コンポーネントの作成方法や破棄方法を定義するライフサイクルもそれぞれ異なります。これら 4 つのタイプのアプリ コンポーネントについては、以降のセクションで説明します。

アクティビティ
アクティビティは、ユーザーとやり取りするためのエントリ ポイントです。これは、1 つのユーザー インターフェースを持つ 1 つの画面で表されます。たとえば、メールアプリには、新着メールの一覧を表示するアクティビティ、メールを作成するアクティビティ、そしてメールを閲覧するアクティビティがあります。メールアプリでは、これらの複数のアクティビティが一体となって 1 つのユーザー エクスペリエンスを形成しますが、それぞれのアクティビティは他のものから独立しています。したがって、これらのアクティビティのいずれかを、別のアプリから開始することができます(メールアプリが許可している場合)。たとえば、カメラアプリからメールアプリの新規メールを作成するアクティビティを開始できます。そのようにして、ユーザーが写真をメールで共有できるようにします。アクティビティは、システムとアプリ間における次の重要なインタラクションを行えるようにします。
  • アクティビティをホストしているプロセスを継続的に実行するために、ユーザーの現在の操作内容(画面の表示)を追跡。
  • 以前に使用されたプロセス(停止されたアクティビティ)のうち、ユーザーが再度アクセスする可能性があるものを検知し、それらの優先順位を上げてプロセスを維持。
  • アプリがプロセスを強制終了した場合に、ユーザーが以前の状態を復元したアクティビティに戻れるように支援。
  • アプリ間でのユーザーフローをアプリが実装する手段と、システムがそれらのフローを連携させるための手段を提供(ここでは最も一般的な例を説明します)。

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

サービス
サービスは、さまざまな理由によりアプリをバックグラウンドで実行し続けるための汎用エントリ ポイントです。長期間の操作やリモート プロセスを処理するためにバックグラウンドで実行されるコンポーネントです。サービスにはユーザー インターフェースがありません。たとえば、サービスはユーザーが別のアプリを使用している間にバックグラウンドで音楽を再生したり、ユーザーが別のアクティビティを操作している間にそれを妨げることなくネットワークからデータを取得したりします。アクティビティなどの他のコンポーネントが、サービスを開始して実行したり、サービスとやり取りするためにサービスにバインドしたりすることができます。アプリの管理方法についてサービスがシステムに通知するセマンティクスは 2 つあり、それぞれ異なる意味を持っています。開始されたサービスが、作業が終了するまで自身の実行を維持するようシステムに指示します。これにより、ユーザーがアプリから離れても、バックグラウンドでデータを同期したり、音楽を再生したりできます。バックグラウンドでのデータの同期や音楽の再生は、開始されたサービスとしてはそれぞれ異なるタイプと認識され、システムがそれらのサービスに対して行う処理もそれぞれ異なります。
  • 音楽の再生はユーザーが直接意識しているものなので、アプリはフォアグラウンドになりたいことをユーザーに通知で知らせることで、システムにそれを指示します。この場合、システムはそのサービス プロセスの実行を維持するよう最善を尽くします。このプロセスが終了するとユーザーが不満を覚えるからです。
  • 通常のバックグラウンド サービスは、その実行をユーザーが直接意識していません。したがって、システムはより柔軟にそのプロセスを管理できます。ユーザーにとってより緊急な課題を処理するために RAM が必要となった場合には、プロセスを強制終了し、後から再開できます。
他のアプリ(またはシステム)がサービスを利用することを明示しているなら、バインドされたサービスが実行されます。これは基本的に、別のプロセスに API を提供するサービスです。これにより、これらのプロセス間に依存関係があることをシステムは認識します。プロセス A がプロセス B のサービスにバインドされている場合に、システムはプロセス B とそのサービスの実行を A のために維持する必要があることを認識します。さらに、プロセス A がユーザーにとって優先度が高い場合は、プロセス B もユーザーにとって重要であるとみなされます。サービスは良くも悪くもその柔軟性から、さまざまな上位レベルのシステム コンセプトにおいて、非常に有用な構成要素となってきました。ライブ壁紙、通知リスナー、スクリーン セーバー、入力方法、ユーザー補助機能サービス、その他多くの主要なシステム機能はすべて、アプリが実行するサービスとしてビルドされ、その実行時にシステムによりバインドされます。

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

注:あなたのアプリが Android 5.0(API レベル 21)以降を対象としている場合は、アクションのスケジュール設定に JobScheduler クラスを使用してください。JobScheduler によりジョブのスケジュール設定が最適化され、また Doze API と連携することにより、電池の消費が抑えられます。このクラスの使用方法については、JobScheduler のリファレンス資料をご覧ください。

ブロードキャスト レシーバ
ブロードキャスト レシーバは、通常のユーザーフローを外れて、システムがアプリにイベントを配信できるようにするコンポーネントです。これにより、アプリはシステム全体のブロードキャスト アナウンスに応答できます。ブロードキャスト レシーバは明確に定義されたアプリへのエントリであるため、システムは実行中でないアプリに対してもブロードキャストを配信できます。したがってアプリが、たとえば、近づいているイベントについてユーザーに知らせる通知を投稿するためのアラームをスケジューリングすることができます。アプリの BroadcastReceiver にアラームを配信することにより、そのアラームが作動するまでアプリの実行を維持する必要がなくなります。多くのブロードキャストの発信源はシステムです — たとえば、画面がオフになったことを通知するブロードキャスト、電池が残り少ないことを通知するブロードキャスト、画像がキャプチャされたことを通知するブロードキャストなどです。アプリから発信されるブロードキャストもあります — たとえば、端末にデータがダウンロードされ使用できることを他のアプリに知らせる場合などです。ブロードキャスト レシーバがユーザー インターフェースを表示することはありませんが、ステータスバー通知を作成して、ブロードキャスト イベントの発生時にユーザーにアラートできます。一般的には、ブロードキャスト レシーバは他のコンポーネントへの単なるゲートウェイであり、最小限の作業を行うことが前提となっています。たとえば、JobScheduler を使用してイベントに基づいた何らかの作業を実行する JobService をスケジュール設定する場合などです。

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

コンテンツ プロバイダ
コンテンツ プロバイダは、ファイル システム、SQLite データベース、ウェブ、またはアプリからアクセス可能な他の永続的なストレージの場所に保存できるアプリデータの共有されている部分を管理します。コンテンツ プロバイダを介して、他のアプリがデータをクエリしたり、修正したりできます(コンテンツ プロバイダが許可している場合)。たとえば、Android システムはユーザーの連絡先情報を管理するコンテンツ プロバイダを提供しています。したがって、適切なパーミッションさえあれば、アプリからコンテンツ プロバイダに ContactsContract.Data などをクエリして、特定の人物に関する情報を読み取ったり書き込んだりできます。このような一般的なケースのために多くの API やサポートが組み込まれているため、コンテンツ プロバイダをデータベースの抽象化として考えたくなるかもしれません。しかし、システム設計の観点では、コンテンツ プロバイダには別の目的があります。システムから見て、コンテンツ プロバイダは、URI スキームにより識別される名前付きデータ項目を公開するための、アプリへのエントリ ポイントです。したがって、アプリは自身が保有するデータを URI 名前空間にどのようにマッピングし、その URI を他のエンティティに渡してデータにアクセスできるようにするかを決めることができます。アプリの管理に関して、システムでは以下が実行できます。
  • URI の割り当てはアプリが実行中であるかどうかには影響されないため、その URI を所有しているアプリが終了していても URI は維持されます。システムが確認する必要があるのは、該当 URI からアプリのデータを取得する必要があるときに、所有しているアプリが実行中であることだけです。
  • URI は重要で詳細なセキュリティ モデルも提供します。たとえば、アプリは画像の URI をクリップボードに配置することができますが、他のアプリが自由にアクセスできないようにコンテンツ プロバイダをロックしたままにできます。別のアプリがクリップボードのその URI にアクセスしようとした場合には、システムが一時的な URI パーミッションを付与して、その URI にあるデータのみにアクセスすることを許可します。その他のデータにはアクセスできません。

コンテンツ プロバイダは、アプリだけに公開されている、他で共有されていないデータを閲覧したり書き込んだりする場合にも役立ちます。

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

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

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

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

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

4 タイプあるコンポーネントのうちの 3 タイプ — アクティビティ、サービス、ブロードキャスト レシーバ — は、インテントと呼ばれる非同期メッセージによりアクティベートされます。インテントは個々のコンポーネントをランタイム時に互いにバインドします。コンポーネントが属しているアプリが何であるかにかかわらず、他のコンポーネントからのアクションをリクエストするメッセンジャーとみなすことができます。

インテントは Intent オブジェクトを使用して作成されます。これで、特定のコンポーネント(明示的インテント)、もしくは特定のタイプのコンポーネント(暗黙的インテント)をアクティベートするメッセージを定義します。

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

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

アクティビティ、サービス、ブロードキャスト レシーバとは異なり、コンテンツ プロバイダはインテントではアクティベートされません。ContentResolver からのリクエストにより指定された場合にアクティベートされます。コンテンツ リゾルバが、コンテンツ プロバイダを使ってすべてのトランザクションを直接処理することで、プロバイダを使ってトランザクションを実行しているコンポーネントによる処理が不要になり、代わりに ContentResolver オブジェクトのメソッドを呼び出します。これによりコンテンツ プロバイダと情報をリクエストしているコンポーネントとの間に(セキュリティ目的で)抽象的な層ができます。

それぞれのタイプのコンポーネントをアクティベートする個別のメソッドがあります。

  • アクティビティを開始する、または新しい作業を与える場合は、IntentstartActivity() または startActivityForResult()(アクティビティから結果を取得する場合)に渡します。
  • Android 5.0(API レベル 21)以降では、JobScheduler クラスを使用してアクションをスケジュール設定できます。それより前のバージョンの Android の場合、サービスを開始する(または続行中のサービスに新しい指示を与える)には、IntentstartService() に渡します。サービスにバインドするには、IntentbindService() に渡します。
  • ブロードキャストを開始するには、Intent を、sendBroadcast()sendOrderedBroadcast()sendStickyBroadcast() などのメソッドに渡します。
  • コンテンツ プロバイダにクエリを実行するには、ContentResolverquery() を呼び出します。

インテントの使用に関する詳細については、インテントとインテント フィルタのドキュメントをご覧ください。特定のコンポーネントのアクティベートについての詳しい情報は、以下のドキュメントを参照してください:アクティビティサービス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() を呼び出すことでシステムに登録することもできます。

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

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

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

注意:インテントを使用して Service を開始する場合には、アプリのセキュリティを維持するために明示的インテントを使用します。暗黙的インテントを使ってサービスを開始すると、どのサービスがインテントに応答するかを把握できず、ユーザーにはどのサービスが開始するのかがわからないため、セキュリティ上の危険が伴います。Android 5.0(API レベル 21)以降では、暗黙的インテントで bindService() を呼び出すと、システムから例外がスローされます。サービスに関してはインテント フィルタを宣言しないでください。

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

アプリのマニフェストでアクティビティを宣言するときに、任意でアクティビティの機能を宣言するインテント フィルタを含めて、他のアプリからのインテントに応答できるようにできます。<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 を生成します。この ID はアプリに固有の整数にマップされます。これを使用して画像を参照したり、ユーザー インターフェースに挿入したりできます。

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

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

アプリに含めることのできるリソースの種類や、異なる端末構成用の代替リソースを作成する方法については、リソースの提供をご覧ください。ベスト プラクティスと製品レベル品質の堅牢なアプリの設計については、アプリのアーキテクチャ ガイドをご覧ください。

参考資料

動画やコードのチュートリアルによる学習を希望する場合は、Udacity コースの Kotlin による Android アプリの開発を受講するか、このオンライン ガイドの他のページにアクセスしてください。

こちらもご覧ください。

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

関連ドキュメント

端末の互換性
さまざまなタイプの端末で Android がどのように動作するかについて、および各端末に合わせてアプリを最適化したり、異なる端末でのアプリの利用可能性を制限したりする方法について説明しています。
システム パーミッション
アプリが特定の API を使用するためにユーザーの同意を必要とするパーミッション システムを使用して、アプリから特定の API へのアクセスを Android が制限する仕組みについて説明しています。