Google Play でのビジネス拡大に役立つ無料のウェブセミナーにぜひご参加ください。今すぐ登録

非 SDK インターフェースの制限

Android 9(API レベル 28)から、アプリで使用できる非 SDK インターフェースが制限されています。この制限は、アプリが非 SDK インターフェースを参照する場合や、リフレクションまたは JNI を使用してハンドルを取得しようとする場合に適用されます。この制限が導入されたことで、ユーザーやデベロッパーのエクスペリエンスが改善されたほか、ユーザーはクラッシュのリスクを、デベロッパーは緊急リリースを配布するリスクを低減できるようになっています。この意思決定について詳しくは、非 SDK インターフェースの使用頻度を減らすことで安定性を向上させる方法に関するブログ記事をご覧ください。

SDK インターフェースと非 SDK インターフェースの違い

パブリック SDK インターフェースとは一般に、Android フレームワークのパッケージ インデックスに記述されているインターフェースです。非 SDK インターフェースを使用するということは、API によって抽象化されている詳細を実装することです。そのため、非 SDK インターフェースは予告なく変更されることがあります。

クラッシュや予期しない動作が発生しないようにするには、アプリで SDK のクラスを使う場合に、正式に文書化されている部分のみを使用するようにします。つまり、リフレクションなどのメカニズムを介してクラスを使用する場合は、SDK に記述されていないメソッドやフィールドにアクセスしてはなりません。

ブラックリスト、グレーリスト、ホワイトリスト

Android の各リリースでは今後、追加の非 SDK インターフェースは制限されます。この制限によってリリース ワークフローに影響が及ぶ可能性があるため、非 SDK インターフェースの使用を検出するツールを用意し、Google にフィードバックを提供できるようにしてください。また、時間を取って計画を立て、新しいポリシーに適応できるようにしてください。

非 SDK インターフェースの制限が開発ワークフローに及ぼす影響を最小限に抑えるには、対象 API レベルに応じて非 SDK インターフェースの使用をどの程度制限するかを定義するリストに非 SDK インターフェースを分類します。次の表で、その各リストについて説明します。

リスト 説明
ブラックリスト アプリの対象 API レベルに関係なく使用できない非 SDK インターフェース。アプリがこのインターフェースのいずれかにアクセスしようとすると、システムによってエラーがスローされます。
グレーリスト アプリの対象 API レベルで制限されていなければ使用できる非 SDK インターフェース。

Android 9(API レベル 28)から、各 API レベルで使用できる非 SDK インターフェースが制限されています。制限付きグレーリストの API へのアクセスは、API レベルがアプリの対象 API レベルより下の場合は可能ですが、対象 API レベルで制限されている非 SDK インターフェースにアプリがアクセスしようとすると、システムは API がブラックリストに登録されている場合と同じように動作します。

注: Android 9(API レベル 28)では、非制限付きグレーリストの非 SDK インターフェースは「ライトグレー リスト」、制限付きグレーリストの非 SDK インターフェースは「ダークグレー リスト」と呼ばれていました。

ホワイトリスト 正式に文書化されている Android フレームワークのパッケージ インデックスの一部としてサポートされている、自由に使用できるインターフェース。

現在、グレーリストに登録されている非 SDK インターフェースは、アプリの対象 API レベルによっては使用できるものもありますが、非 SDK インターフェースのメソッドやフィールドを使用すると、アプリが機能しなくなるリスクが高くなります。アプリの非 SDK インターフェースの依存度が高い場合は、SDK インターフェースまたは別の手段への移行を計画してください。アプリの機能で非 SDK インターフェースを使用しない方法が見つからない場合は、新しい公開 API をリクエストしてください。

インターフェースが属しているリストの特定

非 SDK インターフェースのリストはプラットフォームの一部として作成されています。

Android 9(API レベル 28)の場合、このテキスト ファイルには、グレーリストに登録されている制限されていない API のリストが含まれています。ブラックリストと制限付きグレーリストはビルド時に抽出されます。AOSP には、リストを生成するビルドルールがあります。AOSP のリストは Android 9 のリストと同じではありませんが、かなりの部分が重複しています。また、AOSP をダウンロードしてから次のコマンドを実行すると、ブラックリストを自分で生成できます。

    make hiddenapi-aosp-blacklist
    

ファイルは次の場所に生成されます。

out/target/common/obj/PACKAGING/hiddenapi-aosp-blacklist.txt
    

制限付きの非 SDK インターフェースにアクセスした場合に想定される動作

次の表は、ブラックリストに登録されている非 SDK インターフェースにアプリがアクセスしようとした場合に想定される動作を示したものです。

アクセス方法 結果
Dalvik 命令によるフィールドの参照 NoSuchFieldError がスローされる
Dalvik 命令によるメソッドの参照 NoSuchMethodError がスローされる
Class.getDeclaredField() または Class.getField() によるリフレクション NoSuchFieldException がスローされる
Class.getDeclaredMethod()Class.getMethod() によるリフレクション NoSuchMethodException がスローされる
Class.getDeclaredFields()Class.getFields() によるリフレクション 非 SDK メンバーが結果に含まれない
Class.getDeclaredMethods()Class.getMethods() によるリフレクション 非 SDK メンバーが結果に含まれない
env->GetFieldID() による JNI の呼び出し NULL が返され、NoSuchFieldError がスローされる
env->GetMethodID() による JNI の呼び出し NULL が返され、NoSuchMethodError がスローされる

非 SDK インターフェースのテスト

アプリ内の非 SDK インターフェースのテスト方法をいくつか紹介します。

デバッグ可能なアプリを使用したテスト

デバッグ可能なアプリを作成して、Android 9(API レベル 28)以上が搭載されているデバイスまたはエミュレータで実行することにより、非 SDK インターフェースのテストを実行できます。使用するデバイスまたはエミュレータがアプリの対象 API レベルと一致していることを確認してください。

テストの実行中にアプリが特定の非 SDK インターフェースにアクセスすると、システムによってログメッセージが出力されます。このログメッセージで以下の詳細情報を確認できます。

  • 宣言するクラス、名前、タイプ(Android ランタイムで使用されている形式)。
  • アクセス手段(リンク、リフレクション、JNI のいずれか)。
  • 非 SDK インターフェースが属しているリスト。

adb logcat を使用すると、これらのログメッセージにアクセスできます(実行中のアプリの PID の下に表示されます)。ログ内のエントリの例を以下に示します。

Accessing hidden field Landroid/os/Message;->flags:I (light greylist, JNI)
    

StrictMode API を使用したテスト

StrictMode を使用して非 SDK インターフェースのテストを実行することもできます。この API を有効にするには、detectNonSdkApiUsage メソッドを使用します。StrictMode API を有効にすると、カスタム処理を実装可能な penaltyListener を使用して、非 SDK インターフェースを使用するたびにコールバックを受信できるようになります。コールバックで提供される ViolationThrowable の派生オブジェクトで、埋め込まれているスタック トレースから使用状況がわかります。

veridex ツールを使用したテスト

APK の静的解析ツール veridex を実行することもできます。veridex ツールは APK のコードベース(サードパーティ ライブラリを含む)全体をスキャンして、検出した非 SDK インターフェースの使用状況をレポートします。

veridex ツールには以下の制限事項があります。

  • JNI を介した呼び出しは検出できません。
  • リフレクションを介した呼び出しのサブセットのみを検出できます。
  • 非アクティブなコードパスの解析は API レベルのチェックに制限されています。

Windows

ネイティブ Windows バイナリは提供されていませんが、Linux 用 Windows サブシステム(WSL)を使用して Linux バイナリを実行することで、Windows で veridex ツールを実行できます。WSL をインストールして、Linux ディストリビューションとして Ubuntu を選択してから、このセクションの手順を行ってください。

Ubuntu をインストール後、Ubuntu ターミナルを起動し、次の手順を行います。

  1. Android ランタイム ビルド済みリポジトリから veridex ツールをダウンロードします。
  2. appcompat.tar.gz ファイルの内容を抽出します。
  3. 抽出したフォルダ内にある veridex-linux.zip ファイルを見つけて解凍します。
  4. 解凍したフォルダに移動して、次のコマンドを実行します。your-app.apk には、テストしたい APK を指定します。

        ./appcompat.sh --dex-file=your-app.apk
        

Mac OS

Mac OS で veridex ツールを実行する方法は次のとおりです。

  1. Android ランタイム ビルド済みリポジトリから veridex ツールをダウンロードします。
  2. appcompat.tar.gz ファイルの内容を抽出します。
  3. 抽出したフォルダ内にある veridex-mac.zip ファイルを見つけて解凍します。
  4. 解凍したフォルダに移動して、次のコマンドを実行します。your-app.apk には、テストしたい APK を指定します。

        ./appcompat.sh --dex-file=your-app.apk
        

Linux

Linux で veridex ツールを実行する方法は次のとおりです。

  1. Android ランタイム ビルド済みリポジトリから veridex ツールをダウンロードします。
  2. appcompat.tar.gz ファイルの内容を抽出します。
  3. 抽出したフォルダ内にある veridex-linux.zip ファイルを見つけて解凍します。
  4. 解凍したフォルダに移動して、次のコマンドを実行します。your-app.apk には、テストしたい APK を指定します。

        ./appcompat.sh --dex-file=your-app.apk
        

Android Studio の lint ツールを使用したテスト

Android Studio でアプリをビルドするたびに、lint ツールはコードの潜在的な問題を検査します。非 SDK インターフェースを使用しているアプリでは、そのインターフェースがブラックリストまたはグレーリストに含まれている場合、ビルドエラーや警告が表示されることがあります。

コマンドラインから lint ツールを実行するか、特定のプロジェクト、フォルダ、ファイルで検査を手動で実行することもできます。

Play Console を使用したテスト

アプリを Play Console のテストトラックにアップロードすると、自動的にテストが行われて潜在的な問題がチェックされ、リリース前レポートが生成されます。非 SDK インターフェースを使用しているアプリでは、そのインターフェースがブラックリストまたはグレーリストに含まれている場合、ビルドエラーや警告がリリース前レポートに表示されることがあります。

詳しくは、リリース前レポートを使って問題を特定するの Android の互換性に関するセクションをご覧ください。

新しい公開 API のリクエスト

アプリの機能で非 SDK インターフェースを使用しない方法が見つからない場合は、新しい公開 API を SDK に追加するよう求める機能リクエストを作成できます。

機能リクエストを作成する場合は、以下の情報を提供します。

  • グレーリストに登録されていて、現在使用している API(Accessing hidden ... logcat メッセージに表示される完全な記述子を含む)。
  • 新しい公開 API を使用する必要がある理由(低レベルの機能の詳細情報だけでなく、API が必要な高レベルの機能の詳細情報を含む)。
  • 関連する公開 SDK API では目的を果たせない理由。
  • 試してみた他の方法と、それらがうまくいかなかった理由。

機能リクエストでこれらの詳細情報を提供すると、新しい公開 API が認められる可能性が高くなります。

その他の質問

このセクションでは、デベロッパーからよく寄せられるその他の質問に対する回答を紹介します。

一般的な質問

Google では今後、あらゆるアプリに関するニーズを公開バグトラッカーで収集するそうですが、それはどのようにして行うのですか?

Google では、以下の方法によって強化されたアプリの静的解析を利用して、Android 9(API レベル 28)向けの最初のリストを作成しました。

  • 主要な Play アプリと Play 以外のアプリの手動によるテスト
  • 内部レポート
  • 内部ユーザーからの自動データ収集
  • デベロッパーのプレビュー レポート
  • 誤適用が増えないように設計されたその他の静的解析

Google では新しいリリースごとにリストを評価しており、その際、公開バグトラッカーからのデベロッパー フィードバックだけでなく、API の使用状況も考慮します。

非 SDK インターフェースへのアクセスを有効にするにはどうすればよいですか?

以下の adb コマンドを使用して API 適用ポリシーを変更することで、開発デバイスで非 SDK インターフェースへのアクセスを有効にすることができます。

adb shell settings put global hidden_api_policy_pre_p_apps  1
    adb shell settings put global hidden_api_policy_p_apps 1
    

API 適用ポリシーをデフォルトの設定に戻すには、以下のコマンドを使用します。

adb shell settings delete global hidden_api_policy_pre_p_apps
    adb shell settings delete global hidden_api_policy_p_apps
    

これらのコマンドの実行にあたり、ユーザーにルート権限のあるデバイスは必要ありません。

API 適用ポリシーの整数は以下のいずれかの値に設定できます。

  • 0: 非 SDK インターフェースの検出をすべて無効にします。この設定にすると、非 SDK インターフェースの使用を表すログメッセージがすべて無効になり、StrictMode API を使用してアプリをテストすることができなくなります。この設定は推奨されません。
  • 1: すべての非 SDK インターフェースへのアクセスが有効になりますが、非 SDK インターフェースの使用について警告するログメッセージが出力されます。この設定であれば、StrictMode API を使用してアプリをテストすることもできます。
  • 2: ブラックリストまたはグレーリストに登録されている非 SDK インターフェースと、対象 API レベルで制限されている非 SDK インターフェースを使用できないようにします。
  • 3: ブラックリストに登録されている非 SDK インターフェースを使用できないようにします。ただし、グレーリストに登録されているインターフェースと、対象 API レベルで制限されているインターフェースの使用は許可します。

非 SDK インターフェースのリストに関する質問

ブラックリストとグレーリストはシステム イメージのどこにありますか?

これらのリストは、プラットフォームの dex ファイル内にあるフィールドとメソッドのアクセス フラグビットにエンコードされています。システム イメージ内には、これらのリストが格納されている個別のファイルはありません。

異なる OEM デバイスでも、Android バージョンが同じであれば、ブラックリストとグレーリストは同じですか?

OEM は独自のインターフェースをブラックリストに追加できますが、AOSP のブラックリストまたはグレーリストからインターフェースを削除することはできません。CDD を使用すると、こうした変更を防止できます。Android ランタイムがリストを適用しているかどうかは CTS テストで確認できます。

ネイティブ コードには、非 NDK インターフェースに関する制限はありますか?

Android SDK には Java インターフェースが含まれています。Android 7(API レベル 26)において、ネイティブ C/C++ コードの非 NDK インターフェースへのアクセス制限を開始しました。詳しくは、Android N でのプライベート C/C++ シンボルの制限による安定性の向上に関するブログ記事をご覧ください。

dex2oat または DEX ファイルの操作を制限する計画はありますか?

dex2oat バイナリへのアクセスを制限するアクティブな計画はありませんが、Dalvik 実行可能形式で公に指定されている部分を越えて DEX ファイル形式を安定バージョンまたは公開インターフェースにする予定はありません。Google は、dex2oat と、DEX 形式の未指定の部分をいつでも変更または削除する権利を有しています。また、dex2oat によって生成されたODEX(別名 OAT)、VDEX、CDEX などの派生ファイルはすべて、未指定の形式であることに注意してください。

重要なサードパーティ SDK(難読化ツールなど)で非 SDK インターフェースを使用する必要がある場合、今後 Android バージョンとの互換性を維持するにはどうすればよいですか?この場合、Android の互換性要件を放棄できますか?

SDK ごとに互換性要件を放棄する予定はありません。互換性を維持するかどうかの現在の基準が、グレーリストに登録されているインターフェースのみに依存している場合、SDK デベロッパーは SDK インターフェース、または別の手段への移行を計画する必要があります。また、非 SDK インターフェースを使用しない代替方法が見つからない場合は、新しい公開 API をリクエストする必要があります。

非 SDK インターフェースの制限はすべてのアプリ(サードパーティのアプリだけでなく、システムアプリやファースト パーティのアプリを含む)に適用されますか?

はい、すべてのアプリに適用されます。ただし、プラットフォーム鍵で署名されたアプリは除きます。また、一部のシステム イメージ アプリを対象としたパッケージ ホワイトリストも用意しています。この除外は、システム イメージに含まれているアプリ(または更新対象のシステム イメージ アプリ)にのみ適用されます。リストの対象となるアプリは、SDK API ではなくプライベート プラットフォーム API(LOCAL_PRIVATE_PLATFORM_APIS := true)に対して作成されたアプリのみです。