Android Enterprise'dan Device Trust - Entegrasyon rehberi

Bu belge, cihaz güven sinyallerini almak amacıyla AMAPI SDK'sının kullanımıyla ilgili birincil kılavuzunuz olmalıdır.

AMAPI SDK, uygulamanızın (bazen "eşlikçi" uygulama olarak da adlandırabiliriz) ADP (Android Device Policy) uygulamasından cihaz güven sinyallerine erişmesini sağlar. Uygulamanız daha sonra bu sinyalleri kullanarak cihazın güven durumunu hesaplayabilir ve seçilen iş mantığını uygulayabilir.

Ön koşullar

  • Cihaz güven sinyallerine erişim, yetkisiz kullanımı önlemek için kısıtlanmıştır. Başvuru süreci hakkında bilgi edinmek için cihaz güven sinyallerine erişim sayfasına gidin.
  • Android Enterprise, Play Integrity API paketini istemci uygulamanıza entegre etmenizi ve cihaz güven sinyallerini okuyup bunlara güvenmeden önce sonucu referans almanızı önerir. Play Integrity API kontrollerinde başarısız olan cihazlara ve güven durumu belirlemeleri yapmak için kullanılan cihazdan elde edilen sinyallere güvenilmemelidir. Daha fazla bilgi için Play Integrity'nin belgelerini inceleyebilirsiniz.

Uygulamanızda AMAPI SDK'sı ile entegrasyon yapma

Uygulamanızın cihaz güven sinyallerine erişebilmesi için AMAPI SDK ile entegre olması gerekir. Bu kitaplık ve uygulamaya nasıl ekleneceği hakkında daha fazla bilgiyi AMAPI SDK'sı entegrasyon kılavuzunda bulabilirsiniz.

Gerekli izinleri ekleme

Android Enterprise'dan Cihaz Güveni API'sinden döndürülen sinyallerden bazıları, uygulamanın bu bilgilere erişmek için gereken izni bildirmesini gerektirir. Özellikle:

Sinyal Gerekli izin
Ağ Durumu ACCESS_NETWORK_STATE
Ekran kilidi karmaşıklığı REQUEST_PASSWORD_COMPLEXITY

Bu izinler uygulamanın AndroidManifest.xml içinde yer almıyorsa Android Enterprise API'den Cihaz Güveni, ilgili sinyalin meta verilerinde PERMISSION_ISSUE değerini döndürür:

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

Daha fazla bilgi için kullanılabilir cihaz güveni sinyalleri listesine bakın.

Cihaz güven sinyallerine erişme adımları

Cihaz güven sinyallerine erişmek isteyen uygulamaların, istemci ortamının güncel olduğunu doğrulaması ve gerekirse güncellemesi gerekir.

Cihaz güven sinyallerine erişmek için aşağıdaki adımları uygulayın:

Cihaz güven sinyallerine erişme adımları

Müşteri ortamını doğrulama

Aşağıdaki kod örneğinde, ADP uygulamasının mevcut durumunu okumak için getEnvironment nasıl kullanılacağı gösterilmektedir. Ardından, ortam hazır ve güncelse uygulamanız cihaz güven sinyallerine erişmek için deviceClient oluşturabilir (Cihaz güven sinyallerine erişme bölümüne bakın).

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());
}

ADP uygulaması yüklüyse ancak güncel değilse uygulamanız, kullanıcı müdahalesi olmadan ADP uygulamasını sessizce güncellemek için prepareEnvironment işlevini çağırmalıdır.

ADP uygulaması yüklü değilse uygulamanız, kullanıcıdan ADP uygulamasını yüklemesini istemek için prepareEnvironment işlevini çağırabilir. İstemci ortamını hazırlama başlıklı makaleye bakın.

İstemci ortamını hazırlama

  • ADP uygulaması zaten yüklüyse API, kullanıcı müdahalesi olmadan uygulamayı sessizce günceller.

  • ADP uygulaması yüklü değilse API, kullanıcıdan ADP uygulamasının yüklenmesini kabul etmesini ister.

Android Device Policy&#39;yi yükle

Kullanıcı seçimini izlemek için geri arama kaydetmek mümkündür. Ek ayrıntılar için ADP uygulamasının yüklenmesi sırasında kullanıcı etkileşimini izleme başlıklı makaleyi inceleyin.

Kullanıcıyı Android Device Policy'yi yükleyin modal iletişim kutusuyla şaşırtmamak için prepareEnvironment çağrısının, ilk katılım kullanıcı deneyimi akışı sırasında ön plandaki bir işlemden yapılmasını öneririz. Bunun bir web akışı olması ve Android bileşeninde kullanıcı arayüzü bulunmaması nedeniyle ön plan işleminden arama yapmak mümkün değilse arka plandan arama yapılmasına izin verilir. Ancak bu işlemin, ilk katılım kullanıcı deneyimi akışı sırasında yapılması gerekir.

Ortam doğru şekilde ayarlandıktan sonra cihaz güven sinyallerine erişilebilir. Cihaz güveni sinyallerine erişme başlıklı makaleyi inceleyin.

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());
}

Cihaz güveni sinyallerine erişme

İlgilendiğiniz cihaz güven sinyallerine erişmek için önceki adımda görünen deviceClient örneğini kullanarak Device nesnesini isteyebilirsiniz.

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());
}

ADP uygulaması yükleme işlemi sırasında kullanıcı etkileşimini izleme

Cihazın ADP uygulamasını prepareEnvironment sırasında yüklemesi gerekiyorsa uygulamanız, getPrepareEnvironmentListener'i geçersiz kılan bildirimler almak için NotificationReceiverService uygulayarak kullanıcı etkileşimini izleyebilir:

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");
        }
    }
}

Bilinen sorunlar

Şu anda bilinen bir sorun yok.