SafetyNet Verify Apps API

SafetyNet Verify Apps API は Google Play 開発者サービスによるライブラリで、アプリがプログラムでデバイス上のアプリの確認機能を操作し、有害な可能性があるアプリからデバイスを保護します。

アプリが財務情報などの重要なユーザーデータを扱う場合、ユーザーのデバイスが悪意のあるアプリから保護されており、アプリのなりすましなどの悪意のあるアクションを実行するアプリがないことを確認する必要があります。デバイスで最低限のセキュリティ対策が実施されていない場合は、アプリ内の機能を無効にして、ユーザーへの危険性を軽減できます。

Google は Android エコシステムを可能な限り安全にするという継続的な取り組みの一環として、Android アプリの動作を監視し鑑定します。アプリの確認機能で有害な可能性があるアプリが検出されると、アプリをインストールしたすべてのユーザーに通知され、すぐにそのアプリをアンインストールするように促されます。このプロセスにより、ユーザーのセキュリティとプライバシーが保護されます。

SafetyNet Verify Apps API を使用すると、この機能を活用してアプリのデータを保護できます。この API を使用すると、ユーザーのデバイスがアプリの確認機能で保護されているかどうかを判定し、この機能を使用していないユーザーにデバイスの保護を有効にするように促すことにより、デバイスにインストールされている既知の有害な可能性があるアプリを特定できます。

追加利用規約

SafetyNet API にアクセスするか、これを使用すると、Google API 利用規約と、以下の Verify Apps API 利用規約に同意したことになります。適用されるすべての利用規約とポリシーを確認し、理解したうえで API にアクセスしてください。

Verify Apps API 利用規約

有害な可能性があるアプリを特定するアプリの分析では、偽陽性と偽陰性の両方が発生する可能性があります。この API スイートが返す結果(またはその欠如)では、把握できる限りの情報が示されます。この SafetyNet API スイートによって返される結果が常に正確であるとは限らないことを了承し、理解するものとします。

SafetyNet API の依存関係を追加する

Verify Apps API を使用する前に、SafetyNet API をプロジェクトに追加します。Android Studio を使用している場合は、アプリレベルの Gradle ファイルにこの依存関係を追加します。詳しくは、SafetyNet API の設定をご覧ください。

アプリの確認を有効にする

SafetyNet Verify Apps API には、アプリの確認機能を有効化する 2 つのメソッドがあります。isVerifyAppsEnabled() を使用するとアプリの確認が有効になっているかどうかを判定でき、enableVerifyApps() を使用するとアプリの確認の有効化をリクエストできます。

2 つのメソッドの違いは、isVerifyAppsEnabled() がアプリの確認機能の現在のステータスを報告するのに対して、enableVerifyApps() はユーザーに対してこの機能を使用する許可を明示的に求めることです。セキュリティに基づく決定をするために、アプリでこの機能のステータスを知る必要があるだけの場合は、isVerifyAppsEnabled() を呼び出します。これに対して、アプリで有害な可能性があるインストール済みのアプリを列挙できるようにするには、enableVerifyApps() を呼び出す必要があります。

アプリの確認が有効になっているかどうかを確認する

非同期の isVerifyAppsEnabled() メソッドを使用すると、ユーザーがアプリの確認機能を有効にしているかを判断できます。このメソッドは VerifyAppsUserResponse オブジェクトを返します。このオブジェクトには、有効化などのアプリの確認機能に関連してユーザーが行ったすべてのアクションの情報が含まれています。

このメソッドに関連付けられたコールバックを作成する方法を、次のコード スニペットに示します。

Kotlin

SafetyNet.getClient(this)
        .isVerifyAppsEnabled
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                if (task.result.isVerifyAppsEnabled) {
                    Log.d("MY_APP_TAG", "The Verify Apps feature is enabled.")
                } else {
                    Log.d("MY_APP_TAG", "The Verify Apps feature is disabled.")
                }
            } else {
                Log.e("MY_APP_TAG", "A general error occurred.")
            }
        }

Java

SafetyNet.getClient(this)
    .isVerifyAppsEnabled()
    .addOnCompleteListener(new OnCompleteListener<VerifyAppsUserResponse>() {
        @Override
        public void onComplete(Task<VerifyAppsUserResponse> task) {
            if (task.isSuccessful()) {
                VerifyAppsUserResponse result = task.getResult();
                if (result.isVerifyAppsEnabled()) {
                    Log.d("MY_APP_TAG", "The Verify Apps feature is enabled.");
                } else {
                    Log.d("MY_APP_TAG", "The Verify Apps feature is disabled.");
                }
            } else {
                Log.e("MY_APP_TAG", "A general error occurred.");
            }
        }
    });

アプリの確認の有効化をリクエストする

非同期の enableVerifyApps() メソッドを使用すると、ユーザーにアプリの確認機能を有効にするよう求めるダイアログをアプリから呼び出せます。このメソッドは VerifyAppsUserResponse オブジェクトを返します。このオブジェクトには、このオブジェクトには、有効化に同意したかなど、アプリの確認機能に関連してユーザーが行ったすべてのアクションの情報が含まれています。

このメソッドに関連付けられたコールバックを作成する方法を、次のコード スニペットに示します。

Kotlin

SafetyNet.getClient(this)
        .enableVerifyApps()
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                if (task.result.isVerifyAppsEnabled) {
                    Log.d("MY_APP_TAG", "The user gave consent to enable the Verify Apps feature.")
                } else {
                    Log.d(
                            "MY_APP_TAG",
                            "The user didn't give consent to enable the Verify Apps feature."
                    )
                }
            } else {
                Log.e("MY_APP_TAG", "A general error occurred.")
            }
        }

Java

SafetyNet.getClient(this)
    .enableVerifyApps()
    .addOnCompleteListener(new OnCompleteListener<VerifyAppsUserResponse>() {
        @Override
        public void onComplete(Task<VerifyAppsUserResponse> task) {
            if (task.isSuccessful()) {
                VerifyAppsUserResponse result = task.getResult();
                if (result.isVerifyAppsEnabled()) {
                    Log.d("MY_APP_TAG", "The user gave consent " +
                          "to enable the Verify Apps feature.");
                } else {
                    Log.d("MY_APP_TAG", "The user didn't give consent " +
                          "to enable the Verify Apps feature.");
                }
            } else {
                Log.e("MY_APP_TAG", "A general error occurred.");
            }
        }
    });

このメソッドを使用したときに、通常とは異なる次のような状況が発生する可能性があります。

  • アプリの確認機能がすでに有効になっている場合、ダイアログは表示されず、API はユーザーがこの機能の有効化に同意したかのように動作します。
  • ユーザーがダイアログから移動した場合、ダイアログは破棄され、API はユーザーがこの機能の有効化に同意しなかったと見なします。
  • 自分のアプリと別のアプリが同時にこのメソッドを呼び出した場合、ダイアログは 1 つのみ表示され、どちらのアプリも同じ戻り値をメソッドから受け取ります。

有害な可能性があるインストール済みアプリを列挙する

非同期の listHarmfulApps() メソッドを使用すると、ユーザーがデバイスにインストールした既知の有害な可能性があるアプリのリストを取得できます。このリストには、特定された有害な可能性があるアプリのカテゴリが含まれ、アプリが適切な対応をとれるようになっています。

このメソッドに関連付けられたコールバックを作成する方法を、次のコード スニペットに示します。

Kotlin

SafetyNet.getClient(this)
        .listHarmfulApps()
        .addOnCompleteListener { task ->
            Log.d(TAG, "Received listHarmfulApps() result")

            if (task.isSuccessful) {
                val result = task.result
                val scanTimeMs = result.lastScanTimeMs

                val appList = result.harmfulAppsList
                if (appList?.isNotEmpty() == true) {
                    Log.e("MY_APP_TAG", "Potentially harmful apps are installed!")

                    for (harmfulApp in appList) {
                        Log.e("MY_APP_TAG", "Information about a harmful app:")
                        Log.e("MY_APP_TAG", "  APK: ${harmfulApp.apkPackageName}")
                        Log.e("MY_APP_TAG", "  SHA-256: ${harmfulApp.apkSha256}")

                        // Categories are defined in VerifyAppsConstants.
                        Log.e("MY_APP_TAG", "  Category: ${harmfulApp.apkCategory}")
                    }
                } else {
                    Log.d("MY_APP_TAG", "There are no known potentially harmful apps installed.")
                }
            } else {
                Log.d(
                        "MY_APP_TAG",
                        "An error occurred. Call isVerifyAppsEnabled() to ensure that the user "
                                + "has consented."
                )
            }
        }

Java

SafetyNet.getClient(this)
    .listHarmfulApps()
    .addOnCompleteListener(new OnCompleteListener<HarmfulAppsResponse>() {
        @Override
        public void onComplete(Task<HarmfulAppsResponse> task) {
            Log.d(TAG, "Received listHarmfulApps() result");

            if (task.isSuccessful()) {
                HarmfulAppsResponse result = task.getResult();
                long scanTimeMs = result.getLastScanTimeMs();

                List<HarmfulAppsData> appList = result.getHarmfulAppsList();
                if (appList.isEmpty()) {
                    Log.d("MY_APP_TAG", "There are no known " +
                          "potentially harmful apps installed.");
                } else {
                    Log.e("MY_APP_TAG",
                          "Potentially harmful apps are installed!");

                    for (HarmfulAppsData harmfulApp : appList) {
                        Log.e("MY_APP_TAG", "Information about a harmful app:");
                        Log.e("MY_APP_TAG",
                              "  APK: " + harmfulApp.apkPackageName);
                        Log.e("MY_APP_TAG",
                              "  SHA-256: " + harmfulApp.apkSha256);

                        // Categories are defined in VerifyAppsConstants.
                        Log.e("MY_APP_TAG",
                              "  Category: " + harmfulApp.apkCategory);
                    }
                }
            } else {
                Log.d("MY_APP_TAG", "An error occurred. " +
                      "Call isVerifyAppsEnabled() to ensure " +
                      "that the user has consented.");
            }
        }
    });