パッケージの公開設定を管理する

アプリを作成する際は、アプリがアクセスする予定の、デバイスにインストール済みの他のアプリを表すパッケージのセットを考慮することが重要です。Android 11(API レベル 30)以降をターゲットとするアプリの場合、システムによっていくつかのアプリは自動的に公開されますが、他のアプリはデフォルトでは公開されません。一部のアプリをデフォルトで非表示にすることで、他のどのアプリをアクセス可能にするかをシステムに通知することになり、最小権限の原則が促進されます。また、Google Play などのアプリストアで、アプリがユーザーに提供するプライバシーとセキュリティを評価するために役立ちます。

こうしたアプリの公開設定の違いは、queryIntentActivities() など、他のアプリに関する情報を提供するメソッドの戻り値に影響します。公開設定の違いによって、他のアプリとの明示的な連携(別のアプリのサービスを起動するなど)にも影響します。

このガイドでは、自動的に公開される一連のアプリや、他のアプリをアクセス可能にする方法について説明します。また、他のアプリの公開設定がアプリに及ぼす影響を判断するためにログメッセージを設定する方法についても説明します。

自動的に公開されるアプリ

一部のアプリはシステムによって自動的に公開されており、アプリで <queries> 要素を宣言しなくても連携できます。この動作は、基本的な機能と一般的なユースケースのサポートに役立ちます。

特に、Android 11(API レベル 30)以降をターゲットとしているアプリに対しても、次のタイプのアプリは常に公開されます。

さらに、他のアプリが自分のアプリに公開されているかどうかにかかわらず、暗黙的インテントまたは明示的インテントを使用して、別のアプリのアクティビティを開始できます。

自動的に公開されるシステム パッケージ

Android のコア機能を実装する一部のシステム パッケージは、Android 11(API レベル 30)以降をターゲットとしているアプリの場合でも自動的に公開されます。特定のパッケージのセットは、アプリを実行するデバイスによって異なります。

特定のデバイスのパッケージの完全なリストを表示するには、開発マシンのターミナルで次のコマンドを実行します。

adb shell dumpsys package queries

コマンド出力で、forceQueryable セクションを見つけます。このセクションには、自分のアプリに対しデバイスが自動的に公開するパッケージのリストが含まれます。

アプリが特定の他のアプリと連携することを宣言する

Android 11(API レベル 30)以降をターゲットとするアプリで、自動的に公開されるアプリ以外のアプリとの連携が必要な場合は、アプリのマニフェスト ファイルに <queries> 要素を追加します。次のセクションで説明するように、<queries> 要素内では、パッケージ名インテント シグネチャ、またはプロバイダ オーソリティによって、他のアプリを指定できます。

特定のパッケージに対するクエリと操作

別のアプリを自分のアプリに統合する場合や、自分のアプリで別のアプリのサービスを使用する場合など、アプリがクエリや操作を行う特定のアプリのセットについて把握している場合は、そのパッケージ名を指定した <package> 要素のセットを <queries> 要素に含めます。

<manifest package="com.example.game">
    <queries>
        <package android:name="com.example.store" />
        <package android:name="com.example.services" />
    </queries>
    ...
</manifest>

インテント フィルタが指定されたアプリに対するクエリと操作

アプリが特定の目的を果たすアプリのセットに対してクエリや操作を行う必要があっても、指定するその個々のパッケージ名がわからない場合があります。その場合は、インテント フィルタのシグネチャのリストを <queries> 要素に指定できます。それにより、アプリは一致する <intent-filter> 要素を持つアプリを見つけることができます。

次の例では、JPEG 画像の共有をサポートするインストール済みのアプリを見つけることができます。

<manifest package="com.example.game">
    <queries>
        <intent>
            <action android:name="android.intent.action.SEND" />
            <data android:mimeType="image/jpeg" />
        </intent>
    </queries>
    ...
</manifest>

<intent> 要素には以下のような制限があります。

  • <action> 要素は 1 つだけ含める必要があります。
  • <data> 要素内で pathpathPrefixpathPatternport の各属性を使用することはできません。各属性の値を汎用のワイルドカード文字(*)に設定した場合と同じように動作することになります。
  • <data> 要素の mimeGroup 属性は使用できません。
  • 1 つの <intent> 要素の複数の <data> 要素にわたって、以下の各属性を 1 回だけ使用できます。

    • mimeType
    • scheme
    • host

    これらの属性は複数の <data> 要素に分散させることも、1 つの <data> 要素で使用することもできます。

<intent> 要素は、属性の値として以下の汎用のワイルドカード文字(*)をサポートしています。

  • <action> 要素の name 属性。
  • <data> 要素の mimeType 属性のサブタイプ(image/*)。
  • <data> 要素の mimeType 属性のタイプとサブタイプ(*/*)。
  • <data> 要素の scheme 属性。
  • <data> 要素の host 属性。

前のリストで特に指定されていない限り、システムはテキストとワイルドカード文字(prefix* など)の組み合わせに対応していません。

プロバイダ オーソリティが指定されたアプリに対するクエリと操作

コンテンツ プロバイダにクエリする必要があるものの、具体的なパッケージ名がわからない場合は、次のスニペットに示すように、<provider> 要素でプロバイダ オーソリティを宣言できます。

<manifest package="com.example.suite.enterprise">
    <queries>
        <provider android:authorities="com.example.settings.files" />
    </queries>
    ...
</manifest>

複数のプロバイダ オーソリティを 1 つの <queries> 要素で宣言できます。そのためには、次のいずれかを行います。

  • 単一の <provider> 要素で、セミコロン区切りのオーソリティのリストを宣言します。
  • 複数の <provider> 要素をすべて同じ <queries> 要素内に含めます。各 <provider> 要素で、1 つのオーソリティ、またはセミコロン区切りのオーソリティのリストを宣言します。

すべてのアプリに対するクエリと操作

まれなケースですが、アプリがデバイス上のインストール済みのアプリの「すべて」に対して、各アプリに含まれるコンポーネントによらず、クエリや操作を行うことが必要になる場合があります。アプリがインストール済みの他のすべてのアプリを見つけられるように、QUERY_ALL_PACKAGES 権限が用意されています。

QUERY_ALL_PACKAGES 権限を含めたほうがよいユースケースの例を以下に示します。

  • ランチャー アプリ
  • ユーザー補助機能を利用できるアプリ
  • ブラウザ
  • ピアツーピア(P2P)共有アプリ
  • デバイス管理アプリ
  • セキュリティ アプリ

ただしほとんどの場合、自動的に公開される一連のアプリと連携し、マニフェスト ファイルでアプリがアクセスする必要のある他のアプリを宣言することで、アプリのユースケースを満たすことができます。ユーザーのプライバシーを尊重し、アプリの動作に最低限必要な範囲で、パッケージへのアクセスをリクエストしてください。

今後のポリシー更新では、QUERY_ALL_PACKAGES 権限を必要とするアプリのガイドラインを Google Play で提供する予定です。

パッケージ フィルタリングのログメッセージ

アプリのデフォルトの公開設定がアプリに及ぼす影響の詳細を確認するには、パッケージ フィルタリングのログメッセージを有効にします。Android Studio でテストアプリやデバッグ可能なアプリを開発している場合は、この機能は自動的に有効になります。それ以外の場合は、ターミナル ウィンドウで次のコマンドを実行すると、手動で有効にできます。

adb shell pm log-visibility --enable PACKAGE_NAME

その後で、パッケージが PackageManager オブジェクトの戻り値からフィルタされるたびに、Logcat に次のようなメッセージが表示されます。

I/AppsFilter: interaction: PackageSetting{7654321 \
  com.example.myapp/12345} -> PackageSetting{...} BLOCKED