6 月 3 日の「#Android11: The Beta Launch Show」にぜひご参加ください。

カスタムアプリの権限を定義する

このドキュメントでは、アプリのデベロッパーが Android のセキュリティ機能を使用して、独自の権限を定義する方法について説明します。カスタム権限を定義することで、アプリは他のアプリとリソースや機能を共有できます。権限の詳細については、権限の概要をご覧ください。

背景

Android は、権限が分離されたオペレーティング システムで、各アプリは個別のシステム ID(Linux ユーザー ID とグループ ID)で実行されます。システムの一部は、個別の ID にも分割されます。 これにより、Linux はアプリ同士やシステム間でアプリを分離します。

アプリは、他のアプリが要求できる権限を定義して、アプリの機能を他のアプリに対して公開できます。また、同じ証明書で署名された他のアプリで自動的に使用できるようになる権限も定義できます。

アプリの署名

すべての APK は、デベロッパーが秘密鍵を保持する証明書で署名される必要があります。この証明書は、アプリの作成者を識別します。証明書は、認証局による署名を必要としません。Android アプリでは通常、自己署名証明書を使用することが問題なく許可されます。Android における証明書の目的は、アプリの作成者を区別することです。これにより、システムはアプリに対して署名レベルの権限へのアクセスを許可または拒否し、別のアプリと同じ Linux ID の付与に関するリクエストを許可または拒否できます。

ユーザー ID とファイル アクセス

インストール時に、Android は各パッケージに個別の Linux ユーザー ID を付与します。ID は、そのデバイスのパッケージの有効期間中は変わりません。別のデバイスでは、同じパッケージの UID が異なる場合があります。重要なのは、各パッケージが特定のデバイスで識別できる UID を持つことです

セキュリティの適用はプロセスレベルで行われるため、2 つのパッケージのコードは通常、異なる Linux ユーザーとして実行する必要があることから、同じプロセスでは実行できません。 各パッケージで AndroidManifest.xmlmanifest タグの sharedUserId 属性を使用して、同じユーザー ID を割り当てることができます。これにより、セキュリティ上、2 つのパッケージは、同じユーザー ID とファイル権限を持つ同じアプリとして扱われます。セキュリティを維持するため、同じ署名で署名され(同じ sharedUserId をリクエストする)2 つのアプリのみが、同じユーザー ID を付与される点に留意してください。

アプリによって保存されたデータには、そのアプリのユーザー ID が割り当てられ、通常は他のパッケージからはアクセスできません。

Android のセキュリティ モデルの詳細については、Android のセキュリティの概要をご覧ください。

権限の定義と適用を行う

独自の権限を適用するには、まず AndroidManifest.xml で 1 つ以上の <permission> 要素を使用して、その権限を宣言する必要があります。

たとえば、誰がアクティビティの 1 つを開始できるかを制御する必要があるアプリでは、このオペレーションの権限を次のように宣言できます。

    <manifest
      xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.example.myapp" >
        
        <permission
          android:name="com.example.myapp.permission.DEADLY_ACTIVITY"
          android:label="@string/permlab_deadlyActivity"
          android:description="@string/permdesc_deadlyActivity"
          android:permissionGroup="android.permission-group.COST_MONEY"
          android:protectionLevel="dangerous" />
        ...
    </manifest>
    

注: すべてのパッケージが同じ証明書で署名されていない限り、システムは複数のパッケージが同じ名前で権限を宣言することを許可しません。パッケージが権限を宣言すると、システムはパッケージが 1 つ目のパッケージと同じ証明書で署名されていない限り、ユーザーが同じ権限名を持つ他のパッケージをインストールすることを許可しません。名前の競合を回避するには、カスタムの権限にリバースドメイン形式の名前を使用することをおすすめします。たとえば、com.example.myapp.ENGAGE_HYPERSPACE が考えられます。

リンク先のドキュメントに記載されているように、権限が必要なアプリについてユーザーに通知する方法や、誰がその権限を持つことを許可されるのかについてシステムに指示する protectionLevel 属性が必要です。

android:permissionGroup 属性はオプションで、システムがユーザーに権限を表示できるようにするためにのみ使用されます。ご自分でグループを定義できますが、ほとんどの場合、この属性を標準システム グループ(android.Manifest.permission_group で一覧表示)に設定する必要があります。 ユーザーに表示される権限 UI が簡略化されることから、既存のグループの使用をおすすめします。

権限のラベルと説明の両方を指定する必要があります。これらの文字列リソースは、ユーザーが権限のリスト(android:label)または、1 つの権限の詳細(android:description)を表示しているときに表示できます。ラベルは短くする必要があり、数個の単語を使用して権限が保護している重要な機能を説明するようにします。説明には、権限が所有者に実行を許可する内容を説明する数組の文を用います。通常は 2 つの文で説明します。1 文目は、権限について説明し、2 文目はアプリケーションに権限が付与された場合に、発生する可能性があるエラーの種類についてユーザーに警告します。

以下に CALL_PHONE 権限のラベルと説明の例を示します。

    <string name="permlab_callPhone">directly call phone numbers</string>
    <string name="permdesc_callPhone">Allows the app to call
        phone numbers without your intervention. Malicious apps may
        cause unexpected calls on your phone bill. Note that this does not
        allow the app to call emergency numbers.</string>
    

権限グループを作成する

前のセクションで説明したように、android:permissionGroup 属性を使用して、システムがユーザーに権限を説明するようにできます。ほとんどの場合、標準のシステム グループ(android.Manifest.permission_group に一覧表示)に設定することをおすすめしますが、<permission-group> を使用して独自のグループを定義することもできます。

<permission-group> の要素は、<permission> の要素を使用してマニフェストで宣言されている権限と、その他の場所で宣言されている権限の両方の権限セットのラベルを定義します。これは、ユーザーに表示された際の権限のグループ化の方法にのみ影響します。<permission-group> の要素は、グループに属する権限を指定しませんが、グループに名前を付与します。

グループに権限を割り当てるには、グループ名を <permission> の要素の permissionGroup 属性に割り当てます。

<permission-tree> の要素は、コードで定義されている権限のグループの名前空間を宣言します。

カスタム権限についての推奨事項

アプリは独自のカスタム権限を定義し、<uses-permission> の要素を定義することによって他のアプリのカスタム権限をリクエストできます。 ただし、アプリがリクエストすることが必要かどうかを慎重に判断する必要があります。

  • 互いに機能を公開する一連のアプリを設計する場合は、それぞれの権限が 1 回のみ定義されるようにアプリを設計するようにしてください。アプリがすべて同じ証明書で署名されていない場合は、このようにする必要があります。すべてのアプリが同じ証明書で署名されていても、各権限を 1 回のみ定義することをおすすめします。
  • 機能が、提供元アプリと同じ署名で署名されたアプリでのみ使用できる場合は、署名チェック機能を使用してカスタム権限を定義せずに済ませることができます。いずれかのアプリが別のアプリのリクエストを行うと、2 つ目のアプリはリクエストに応える前に両方のアプリが同じ証明書で署名されていることを確認できます。

続きを読む:

<uses-permission>
アプリが必要とするシステム権限を宣言するマニフェスト タグの API リファレンス。

その他の情報:

Android のセキュリティの概要
Android プラットフォームのセキュリティ モデルに関する詳細な説明です。