Device Trust from Android Enterprise - Panduan integrasi

Dokumen ini harus menjadi panduan utama Anda untuk penggunaan AMAPI SDK untuk tujuan menerima sinyal kepercayaan perangkat.

AMAPI SDK memungkinkan aplikasi Anda (yang terkadang kami sebut sebagai aplikasi "Pendamping") mengakses sinyal kepercayaan perangkat dari aplikasi ADP (Android Device Policy). Aplikasi Anda kemudian dapat menggunakan sinyal ini untuk menghitung status kepercayaan perangkat dan menerapkan logika bisnis sesuai pilihan.

Prasyarat

  • Akses ke sinyal kepercayaan perangkat dibatasi untuk mencegah penggunaan yang tidak sah. Untuk mengetahui informasi tentang cara menerapkan, buka halaman akses sinyal kepercayaan perangkat.
  • Android Enterprise merekomendasikan pengintegrasian rangkaian API Play Integrity ke dalam aplikasi klien Anda dan merujuk ke hasilnya sebelum membaca dan mengandalkan sinyal kepercayaan perangkat. Perangkat yang gagal dalam pemeriksaan Play Integrity API tidak boleh dipercaya, begitu juga sinyal apa pun yang berasal dari perangkat yang digunakan untuk membuat penentuan postur kepercayaan. Anda dapat melihat dokumentasi Play Integrity untuk mengetahui detail selengkapnya.

Mengintegrasikan dengan AMAPI SDK di aplikasi Anda

Untuk mengakses sinyal kepercayaan perangkat, aplikasi Anda harus terintegrasi dengan AMAPI SDK. Anda dapat menemukan informasi selengkapnya tentang library ini dan cara menambahkannya ke aplikasi Anda di panduan integrasi AMAPI SDK.

Tambahkan izin yang diperlukan

Beberapa sinyal yang ditampilkan dari API Kepercayaan Perangkat dari Android Enterprise mengharuskan aplikasi mendeklarasikan izin yang sama yang akan diperlukan untuk mengakses informasi ini sejak awal, khususnya:

Sinyal Izin yang diperlukan
Status Jaringan ACCESS_NETWORK_STATE
Kompleksitas kunci layar REQUEST_PASSWORD_COMPLEXITY

Jika izin ini tidak disertakan dalam AndroidManifest.xml aplikasi, Device Trust dari Android Enterprise API akan menampilkan PERMISSION_ISSUE dalam metadata sinyal terkait:

internalDeviceSettings=DeviceSettings{
  screenLockComplexity=COMPLEXITY_UNSPECIFIED,
  internalScreenLockComplexityMetadata=Metadata{
    dataIssues=[
      DataIssue{
        issueType=PERMISSION_ISSUE,
        issueLevel=WARNING,
        issueDetails=IssueDetailsCase{none}
      }
    ]
  },

Untuk mengetahui detail tambahan, lihat daftar sinyal kepercayaan perangkat yang tersedia.

Langkah-langkah untuk mengakses sinyal kepercayaan perangkat

Aplikasi yang ingin mengakses sinyal kepercayaan perangkat diwajibkan untuk memverifikasi bahwa lingkungan klien sudah diupdate dan memperbaruinya jika perlu.

Langkah-langkah untuk mengakses sinyal kepercayaan perangkat adalah:

Langkah-langkah untuk mengakses sinyal kepercayaan perangkat

Memverifikasi lingkungan klien

Contoh kode berikut menunjukkan cara menggunakan getEnvironment untuk membaca status aplikasi ADP saat ini. Aplikasi Anda kemudian dapat membuat deviceClient untuk mengakses sinyal kepercayaan perangkat jika lingkungan siap dan terbaru (lihat Mengakses sinyal kepercayaan perangkat).

Kotlin

import com.google.android.managementapi.common.model.Role
import com.google.android.managementapi.device.DeviceClient
import com.google.android.managementapi.device.DeviceClientFactory
import com.google.android.managementapi.device.model.GetDeviceRequest
import com.google.android.managementapi.environment.EnvironmentClient
import com.google.android.managementapi.environment.EnvironmentClientFactory
import com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.INSTALLED
import com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.NOT_INSTALLED
import com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.READY
import com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.Version.UP_TO_DATE
import com.google.android.managementapi.environment.model.GetEnvironmentRequest
import com.google.android.managementapi.environment.model.PrepareEnvironmentRequest

try {
    val context = applicationContext

    val roles = listOf(Role.builder().setRoleType(Role.RoleType.IDENTITY_PROVIDER).build())
    val request = GetEnvironmentRequest.builder().setRoles(roles).build()
    val environmentClient = EnvironmentClientFactory.create(context)
    val environmentResponse = environmentClient.getEnvironment(request)

    if (environmentResponse.hasAndroidDevicePolicyEnvironment()) {
        val adpEnvironment = environmentResponse.androidDevicePolicyEnvironment

        if (adpEnvironment.state == READY && adpEnvironment.version == UP_TO_DATE) {
            // AMAPI Environment State OK, Version OK.  Requesting Device signals..
            checkDevice(deviceClient = DeviceClientFactory.create(context))
        } else if (adpEnvironment.state == INSTALLED) {
            // prepareEnvironment should be called, calling
            // prepareEnvironment won't show the UI
            prepareEnvironment(context, environmentClient)
        } else if (adpEnvironment.state == NOT_INSTALLED) {
            // prepareEnvironment should be called, calling
            // prepareEnvironment will show the UI
            prepareEnvironment(context, environmentClient)
        }
    }
} catch (e: Exception) {
    Log.e(TAG, "Exception", e)
}

Java

import static com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.INSTALLED;
import static com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.NOT_INSTALLED;
import static com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.READY;
import static com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.Version.UP_TO_DATE;

import com.google.android.managementapi.common.model.Role;
import com.google.android.managementapi.device.DeviceClient;
import com.google.android.managementapi.device.DeviceClientFactory;
import com.google.android.managementapi.device.model.Device;
import com.google.android.managementapi.device.model.GetDeviceRequest;
import com.google.android.managementapi.environment.EnvironmentClient;
import com.google.android.managementapi.environment.EnvironmentClientFactory;
import com.google.android.managementapi.environment.model.Environment;
import com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment;
import com.google.android.managementapi.environment.model.GetEnvironmentRequest;
import com.google.android.managementapi.environment.model.PrepareEnvironmentRequest;
import com.google.android.managementapi.environment.model.PrepareEnvironmentResponse;

try {
    Context context = getApplicationContext();

    ImmutableList roles = new ImmutableList.Builder()
            .add(Role.builder()
                    .setRoleType(Role.RoleType.IDENTITY_PROVIDER)
                    .build())
            .build();

    EnvironmentClient environmentClient = EnvironmentClientFactory.create(context);
    GetEnvironmentRequest request = GetEnvironmentRequest.builder()
            .setRoles(roles)
            .build();

    ListenableFuture getEnvironmentFuture = environmentClient.getEnvironmentAsync(request);
    Futures.addCallback(getEnvironmentFuture, new FutureCallback<>() {
        @Override
        public void onSuccess(Environment environment) {
            AndroidDevicePolicyEnvironment adpEnvironment = environment.getAndroidDevicePolicyEnvironment();

            AndroidDevicePolicyEnvironment.State state = adpEnvironment.getState();
            AndroidDevicePolicyEnvironment.Version version = adpEnvironment.getVersion();
            if (state == READY && version == UP_TO_DATE) {
                // AMAPI Environment State OK, Version OK.  Requesting Device signals..
                DeviceClient deviceClient = DeviceClientFactory.create(context);
                checkDevice(deviceClient);
            } else if (state == INSTALLED) {
                // prepareEnvironment should be called, calling
                // prepareEnvironment won't show the UI
                prepareEnvironment(context, environmentClient);
            } else if (state == NOT_INSTALLED) {
                // prepareEnvironment should be called, calling
                // prepareEnvironment will show the UI
                prepareEnvironment(context, environmentClient);
            }
        }

        @Override
        public void onFailure(Throwable t) {
            Log.d(TAG, t.toString());
        }
    }, MoreExecutors.directExecutor());
} catch (Exception e) {
    Log.d(TAG, e.toString());
}

Jika aplikasi ADP diinstal tetapi tidak diupdate, aplikasi Anda harus memanggil prepareEnvironment untuk mengupdate aplikasi ADP secara diam-diam tanpa intervensi pengguna.

Jika aplikasi ADP tidak diinstal, aplikasi Anda dapat memanggil prepareEnvironment untuk meminta pengguna menginstal aplikasi ADP. Lihat Menyiapkan lingkungan klien.

Menyiapkan lingkungan klien

  • Jika aplikasi ADP sudah diinstal, API akan mengupdatenya secara diam-diam tanpa intervensi pengguna.

  • Jika aplikasi ADP tidak diinstal, API akan meminta pengguna untuk menyetujui penginstalan aplikasi ADP.

Instal Android Device Policy

Anda dapat mendaftarkan callback untuk memantau pilihan pengguna. Lihat Melacak interaksi pengguna selama penginstalan aplikasi ADP untuk mengetahui detail tambahan.

Sebaiknya panggilan prepareEnvironment dilakukan dari proses latar depan, selama alur UX orientasi untuk menghindari kejutan bagi pengguna dengan dialog modal Instal Android Device Policy. Jika panggilan dari proses latar depan tidak memungkinkan, karena ini adalah alur Web dan komponen Android tidak memiliki UI, panggilan dari latar belakang diizinkan dengan persyaratan bahwa hal ini terjadi selama alur UX orientasi.

Setelah lingkungan disiapkan dengan benar, Anda dapat mengakses Sinyal kepercayaan perangkat. Lihat Mengakses sinyal kepercayaan perangkat.

Kotlin

try {
    val myNotificationReceiverService = ComponentName(
        context, MyNotificationReceiverService::class.java
    )

    val roles = listOf(Role.builder().setRoleType(Role.RoleType.IDENTITY_PROVIDER).build())
    val request = PrepareEnvironmentRequest.builder().setRoles(roles).build()

    val response =
        environmentClient.prepareEnvironment(request, myNotificationReceiverService)

    val environment = response.environment
    val adpEnvironment = environment.androidDevicePolicyEnvironment

    val state = adpEnvironment.state
    val version = adpEnvironment.version
    if (state == READY && version == UP_TO_DATE) {
        // Environment is prepared, access device posture signals using
        // DeviceClient.
        checkDevice(deviceClient = DeviceClientFactory.create(context))
    } else {
        // The prepareEnvironment call failed to prepare
        Log.w(
            TAG, "AMAPI environment was not ready: " + state + " - " + version
        )
    }

} catch (e: java.lang.Exception) {
    Log.d(TAG, e.toString())
}

Java

try {
    ComponentName myNotificationReceiverService = new ComponentName(
            context,
            MyNotificationReceiverService.class
    );

    ImmutableList roles = new ImmutableList.Builder()
            .add(Role.builder()
                    .setRoleType(Role.RoleType.IDENTITY_PROVIDER)
                    .build())
            .build();


    PrepareEnvironmentRequest request = PrepareEnvironmentRequest.builder()
            .setRoles(roles)
            .build();

    ListenableFuture environmentFuture =
            environmentClient.prepareEnvironmentAsync(
                    request,
                    myNotificationReceiverService
            );

    Futures.addCallback(environmentFuture, new FutureCallback<>() {
        @Override
        public void onSuccess(PrepareEnvironmentResponse response) {
            Environment environment = response.getEnvironment();
            AndroidDevicePolicyEnvironment adpEnvironment = environment.getAndroidDevicePolicyEnvironment();

            AndroidDevicePolicyEnvironment.State state = adpEnvironment.getState();
            AndroidDevicePolicyEnvironment.Version version = adpEnvironment.getVersion();
            if (state == READY && version == UP_TO_DATE) {
                // AMAPI Environment State OK, Version OK.  Requesting Device signals..
                DeviceClient deviceClient = DeviceClientFactory.create(context);
                checkDevice(deviceClient);
            } else {
                // The prepareEnvironment call failed to prepare
                Log.w(
                        TAG, "AMAPI environment was not ready: "
                        + adpEnvironment.getState() + " - " + adpEnvironment.getVersion()
                );
            }
        }

        @Override
        public void onFailure(@NonNull Throwable t) {
            // Handle the error
            Log.d(TAG, "AMAPI response did not contain an ADP environment");
        }
    }, MoreExecutors.directExecutor());
} catch (Exception e) {
    Log.d(TAG, e.toString());
}

Mengakses sinyal kepercayaan perangkat

Untuk Mengakses sinyal kepercayaan perangkat yang Anda minati, Anda dapat menggunakan instance deviceClient yang terlihat pada langkah sebelumnya untuk meminta objek Device.

Kotlin

try {
    kotlin.runCatching {
        deviceClient.getDeviceAwait(GetDeviceRequest.getDefaultInstance())
    }.onFailure { t ->
        Log.d(TAG, t.toString())
    }.onSuccess { device ->
        // Access device posture signals available in device
        val deviceString = device.toString()
        Log.d(TAG, deviceString)
    }
} catch (e: java.lang.Exception) {
    Log.d(TAG, e.toString())
}

Java

try {
    ListenableFuture deviceFuture =
            deviceClient.getDevice(GetDeviceRequest.getDefaultInstance());

    Futures.addCallback(deviceFuture, new FutureCallback() {
        @Override
        public void onSuccess(Device device) {
            // Access device posture signals available in device
            String deviceString = device.toString();
            Log.d(TAG, deviceString);
        }

        @Override
        public void onFailure(Throwable t) {
            Log.d(TAG, Log.d(TAG, t.toString());
        }
    }, MoreExecutors.directExecutor());
} catch (Exception e) {
    Log.d(TAG, e.toString());
}

Melacak interaksi pengguna selama penginstalan aplikasi ADP

Jika perangkat perlu menginstal aplikasi ADP selama prepareEnvironment, aplikasi Anda dapat melacak interaksi pengguna dengan menerapkan NotificationReceiverService untuk menerima notifikasi yang menggantikan getPrepareEnvironmentListener:

Kotlin

import android.util.Log
import com.google.android.managementapi.environment.EnvironmentListener
import com.google.android.managementapi.environment.model.EnvironmentEvent.EventCase.Kind.ANDROID_DEVICE_POLICY_INSTALL_CONSENT_ACCEPTED
import com.google.android.managementapi.environment.model.EnvironmentEvent
import com.google.android.managementapi.notification.NotificationReceiverService

class MyNotificationReceiverService : NotificationReceiverService() {
    override fun getPrepareEnvironmentListener(): EnvironmentListener {
        return MyEnvironmentListener()
    }
}

class MyEnvironmentListener : EnvironmentListener {
    override fun onEnvironmentEvent(
        event: EnvironmentEvent
    ) {
        if (event.event.kind == ANDROID_DEVICE_POLICY_INSTALL_CONSENT_ACCEPTED) {
            Log.d(TAG, "User provided install consent")
        } else {
            Log.d(TAG, "User rejected install consent")
        }
    }

    companion object {
        private val TAG: String = MyEnvironmentListener::class.java.simpleName
    }
}

Java

import static com.google.android.managementapi.environment.model.EnvironmentEvent.EventCase.Kind.ANDROID_DEVICE_POLICY_INSTALL_CONSENT_ACCEPTED;

import android.util.Log;
import androidx.annotation.NonNull;
import com.google.android.managementapi.environment.EnvironmentListener;
import com.google.android.managementapi.environment.model.EnvironmentEvent;
import com.google.android.managementapi.notification.NotificationReceiverService;

class MyNotificationReceiverService extends NotificationReceiverService {
    @NonNull
    @Override
    protected EnvironmentListener getPrepareEnvironmentListener() {
        return new MyEnvironmentListener();
    }
}
class MyEnvironmentListener implements EnvironmentListener {
    final private String TAG = MyEnvironmentListener.class.getSimpleName();

    @Override
    public void onEnvironmentEvent(EnvironmentEvent event) {
        if (event.getEvent().getKind() == ANDROID_DEVICE_POLICY_INSTALL_CONSENT_ACCEPTED)
        {
            Log.d(TAG, "User provided install consent");
        } else {
            Log.d(TAG, "User rejected install consent");
        }
    }
}

Masalah umum

Saat ini tidak ada masalah umum.