Manual sobre dispositivos dedicados

Este manual ajuda desenvolvedores e integradores de sistemas a aprimorar seus conhecimentos do Google Cloud. Siga nossas instruções e encontre soluções para dispositivos dedicados o comportamento dos modelos. Este manual funciona melhor para desenvolvedores que já têm uma experiência dedicada dispositivo do Google. se estiver começando, leia o artigo Dispositivos dedicados geral do Google.

Apps de casa personalizada

Estas receitas são úteis se você estiver desenvolvendo um app para substituir o Android Home. tela e acesso rápido.

Seja o app de início

É possível definir seu app como o app inicial do dispositivo para que ele seja iniciado. automaticamente quando o dispositivo é ligado. Você também pode ativar o botão "Início" que coloca seu app da lista de permissões em primeiro plano. modo de tarefa.

Todos os apps de casa processam a categoria de intent CATEGORY_HOME. Essa é como o sistema reconhece um app de início. Para se tornar o app de início padrão, defina um das atividades do seu app como o gerenciador preferencial de intent da página inicial, chamando DevicePolicyManager.addPersistentPreferredActivity() conforme mostrado neste exemplo:

Kotlin

// Create an intent filter to specify the Home category.
val filter = IntentFilter(Intent.ACTION_MAIN)
filter.addCategory(Intent.CATEGORY_HOME)
filter.addCategory(Intent.CATEGORY_DEFAULT)

// Set the activity as the preferred option for the device.
val activity = ComponentName(context, KioskModeActivity::class.java)
val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE)
        as DevicePolicyManager
dpm.addPersistentPreferredActivity(adminName, filter, activity)

Java

// Create an intent filter to specify the Home category.
IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
filter.addCategory(Intent.CATEGORY_HOME);
filter.addCategory(Intent.CATEGORY_DEFAULT);

// Set the activity as the preferred option for the device.
ComponentName activity = new ComponentName(context, KioskModeActivity.class);
DevicePolicyManager dpm =
    (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
dpm.addPersistentPreferredActivity(adminName, filter, activity);

Você ainda precisa declarar o filtro de intent. no arquivo de manifesto do app, conforme mostrado no snippet XML abaixo:

<activity
        android:name=".KioskModeActivity"
        android:label="@string/kiosk_mode"
        android:launchMode="singleInstance"
        android:excludeFromRecents="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.HOME"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

Normalmente, você não quer que seu app de tela de início apareça na tela "Visão geral". No entanto, não é necessário adicionar excludeFromRecents declaração de atividade porque o acesso rápido do Android oculta os elementos atividade quando o sistema está em execução no modo de bloqueio de tarefas.

Mostrar tarefas separadas

FLAG_ACTIVITY_NEW_TASK pode ser uma flag útil para de tela de início, porque cada nova tarefa aparece como um item separado na Visão geral. Para saber mais sobre as tarefas na tela "Visão geral", leia Recentes Tela.

Quiosques públicos

Essas receitas são ótimas para dispositivos autônomos em espaços públicos, mas também podem ajudam muitos usuários de dispositivos dedicados a se concentrarem em suas tarefas.

Bloquear o dispositivo

Para garantir que os dispositivos sejam usados para a finalidade pretendida, é possível adicionar restrições de usuário listadas na tabela 1.

:
Tabela 1. Restrições de usuários para dispositivos de quiosque
Restrição de usuários Descrição
DISALLOW_FACTORY_RESET Impede que um usuário redefina o dispositivo para a configuração original. Os administradores de dispositivos totalmente gerenciados e o usuário principal podem configurar isso. e a segunda é a restrição de recursos.
DISALLOW_SAFE_BOOT Impede que um usuário inicie o dispositivo em modo de segurança em que o sistema não vai iniciar o app automaticamente. Administradores do os dispositivos gerenciados e o usuário principal podem definir essa restrição.
DISALLOW_MOUNT_PHYSICAL_MEDIA Impede que o usuário do dispositivo monte qualquer volume de armazenamento possível ao dispositivo. Os administradores de dispositivos totalmente gerenciados e o usuário principal você pode definir essa restrição.
DISALLOW_ADJUST_VOLUME Desativa o som do dispositivo e impede que o usuário do dispositivo altere o som configurações de volume e vibração. Verifique se o quiosque não precisa de áudio para reprodução de mídia ou recursos de acessibilidade. Os administradores de contas totalmente gerenciadas dispositivos, o usuário principal, os usuários secundários e os perfis de trabalho podem definir isso e a segunda é a restrição de recursos.
DISALLOW_ADD_USER Impede que o usuário do dispositivo adicione novos usuários, como secundários ou usuários restritos. O sistema adiciona automaticamente essa restrição de usuário a dispositivos totalmente gerenciados, mas pode ter sido apagado. Administradores do os dispositivos gerenciados e o usuário principal podem definir essa restrição.

O snippet a seguir mostra como definir as restrições:

Kotlin

// If the system is running in lock task mode, set the user restrictions
// for a kiosk after launching the activity.
arrayOf(
        UserManager.DISALLOW_FACTORY_RESET,
        UserManager.DISALLOW_SAFE_BOOT,
        UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
        UserManager.DISALLOW_ADJUST_VOLUME,
        UserManager.DISALLOW_ADD_USER).forEach { dpm.addUserRestriction(adminName, it) }

Java

// If the system is running in lock task mode, set the user restrictions
// for a kiosk after launching the activity.
String[] restrictions = {
    UserManager.DISALLOW_FACTORY_RESET,
    UserManager.DISALLOW_SAFE_BOOT,
    UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
    UserManager.DISALLOW_ADJUST_VOLUME,
    UserManager.DISALLOW_ADD_USER};

for (String restriction: restrictions) dpm.addUserRestriction(adminName, restriction);

Convém remover essas restrições quando o aplicativo estiver no modo de administrador. que um administrador de TI ainda possa usar esses recursos para manutenção de dispositivos. Para limpar a restrição, chame DevicePolicyManager.clearUserRestriction()

Suprimir caixas de diálogo de erro

Em alguns ambientes, como demonstrações na loja ou informações públicas for exibido, talvez você não queira mostrar caixas de diálogo de erro aos usuários. No Android 9.0 (API nível 28) ou superior, é possível suprimir caixas de diálogo de erro do sistema para apps que não respondem, adicionando o Usuário do DISALLOW_SYSTEM_ERROR_DIALOGS e a segunda é a restrição de recursos. O sistema reinicia os apps que não respondem, como se o usuário do dispositivo tivesse fechado o app na caixa de diálogo. O exemplo a seguir mostra como fazer isso:

Kotlin

override fun onEnabled(context: Context, intent: Intent) {
    val dpm = getManager(context)
    val adminName = getWho(context)

    dpm.addUserRestriction(adminName, UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS)
}

Java

public void onEnabled(Context context, Intent intent) {
  DevicePolicyManager dpm = getManager(context);
  ComponentName adminName = getWho(context);

  dpm.addUserRestriction(adminName, UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS);
}

Se um administrador do usuário principal ou secundário definir essa restrição, o sistema suprime caixas de diálogo de erro apenas para esse usuário. Se um administrador de uma conta de serviço dispositivo definir essa restrição, o sistema suprima caixas de diálogo para todos os usuários.

Manter a tela ativada

Se você estiver construindo um quiosque, pode impedir um dispositivo que sono quando está executando a atividade do app. Adicionar a sinalização de layout FLAG_KEEP_SCREEN_ON à conforme mostrado neste exemplo:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // Keep the screen on and bright while this kiosk activity is running.
    window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  // Keep the screen on and bright while this kiosk activity is running.
  getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}

Verifique se o dispositivo está conectado a uma fonte de alimentação, USB ou sem fio. carregador. Registrar-se em transmissões de troca de bateria e usar BatteryManager para descobrir o estado de carregamento. É possível até enviar alertas remotos para um administrador caso o dispositivo seja desconectado. Para instruções detalhadas, leia Monitorar o nível de bateria e o carregamento Estado.

Você também pode definir o STAY_ON_WHILE_PLUGGED_IN configuração global para manter o dispositivo ativado enquanto ele está conectado a uma fonte de energia. Os administradores de dispositivos totalmente gerenciados no Android 6.0 (nível 23 da API) ou versões mais recentes podem chame DevicePolicyManager.setGlobalSetting(), conforme mostrado no exemplo a seguir:

Kotlin

val pluggedInto = BatteryManager.BATTERY_PLUGGED_AC or
        BatteryManager.BATTERY_PLUGGED_USB or
        BatteryManager.BATTERY_PLUGGED_WIRELESS
dpm.setGlobalSetting(adminName,
        Settings.Global.STAY_ON_WHILE_PLUGGED_IN, pluggedInto.toString())

Java

int pluggedInto = BatteryManager.BATTERY_PLUGGED_AC |
    BatteryManager.BATTERY_PLUGGED_USB |
    BatteryManager.BATTERY_PLUGGED_WIRELESS;
dpm.setGlobalSetting( adminName,
    Settings.Global.STAY_ON_WHILE_PLUGGED_IN, String.valueOf(pluggedInto));

Pacotes de apps

Esta seção contém receitas para instalar apps com eficiência em dispositivos dedicados.

Armazenar pacotes de apps em cache

Se os usuários de um dispositivo compartilhado compartilharem um conjunto comum de apps, isso facilita e evitar o download de aplicativos sempre que possível. Para simplificar o gerenciamento o provisionamento em dispositivos compartilhados com um conjunto fixo de usuários, como dispositivos "shift workers", no Android 9.0 (nível 28 da API) ou mais recente, é possível armazenar apps em cache pacotes (APKs) necessários para sessões multiusuário.

A instalação de um APK armazenado em cache (que já está instalado no dispositivo) acontece em dois estágios:

  1. O componente de administração de um dispositivo totalmente gerenciado (ou um delegado). Consulte seguinte) define a lista de APKs a serem mantidos no dispositivo.
  2. Os componentes de administrador de usuários secundários afiliados (ou seus delegados) podem instalar o APK armazenado em cache em nome do usuário. Os administradores do grupo do dispositivo, o usuário principal ou um perfil de trabalho afiliado (ou os delegados) também podem instalar o app em cache, se necessário.

Para definir a lista de APKs a serem mantidos no dispositivo, o administrador chama DevicePolicyManager.setKeepUninstalledPackages() Esse método não verifica se o APK está instalado no dispositivo, útil se você querem instalar um app antes de precisar dele para o usuário. Para conferir uma lista pacotes definidos anteriormente, é possível chamar DevicePolicyManager.getKeepUninstalledPackages() Depois de chamar setKeepUninstalledPackages() com mudanças ou quando uma instância secundária o usuário for excluído, o sistema excluirá todos os APKs armazenados em cache que não forem mais necessários.

Para instalar um APK armazenado em cache, chame DevicePolicyManager.installExistingPackage() Esse método só pode instalar um app que o sistema já armazenou em cache. solução de dispositivo dedicado (ou o usuário de um dispositivo) deve primeiro instalar o app no dispositivo antes de chamar esse método.

O exemplo a seguir mostra como você pode usar essas chamadas de API no administrador de um dispositivo totalmente gerenciado e um usuário secundário:

Kotlin

// Set the package to keep. This method assumes that the package is already
// installed on the device by managed Google Play.
val cachedAppPackageName = "com.example.android.myapp"
dpm.setKeepUninstalledPackages(adminName, listOf(cachedAppPackageName))

// ...

// The admin of a secondary user installs the app.
val success = dpm.installExistingPackage(adminName, cachedAppPackageName)

Java

// Set the package to keep. This method assumes that the package is already
// installed on the device by managed Google Play.
String cachedAppPackageName = "com.example.android.myapp";
List<String> packages = new ArrayList<String>();
packages.add(cachedAppPackageName);
dpm.setKeepUninstalledPackages(adminName, packages);

// ...

// The admin of a secondary user installs the app.
boolean success = dpm.installExistingPackage(adminName, cachedAppPackageName);

Delegar apps

É possível delegar o gerenciamento do armazenamento em cache de outro app. Você pode fazer isso para separar os recursos da solução ou permitir que os administradores de TI usem nos próprios apps. O app delegado recebe as mesmas permissões que o administrador componente. Por exemplo, um delegado do app do administrador de um usuário secundário pode chamar installExistingPackage(), mas não é possível chamar setKeepUninstalledPackages().

Para fazer uma chamada de delegado DevicePolicyManager.setDelegatedScopes() e incluem DELEGATION_KEEP_UNINSTALLED_PACKAGES no argumento escopos. O exemplo a seguir mostra como criar outro app o delegado:

Kotlin

var delegatePackageName = "com.example.tools.kept_app_assist"

// Check that the package is installed before delegating.
try {
    context.packageManager.getPackageInfo(delegatePackageName, 0)
    dpm.setDelegatedScopes(
            adminName,
            delegatePackageName,
            listOf(DevicePolicyManager.DELEGATION_KEEP_UNINSTALLED_PACKAGES))
} catch (e: PackageManager.NameNotFoundException) {
    // The delegate app isn't installed. Send a report to the IT admin ...
}

Java

String delegatePackageName = "com.example.tools.kept_app_assist";

// Check that the package is installed before delegating.
try {
  context.getPackageManager().getPackageInfo(delegatePackageName, 0);
  dpm.setDelegatedScopes(
      adminName,
      delegatePackageName,
      Arrays.asList(DevicePolicyManager.DELEGATION_KEEP_UNINSTALLED_PACKAGES));
} catch (PackageManager.NameNotFoundException e) {
  // The delegate app isn't installed. Send a report to the IT admin ...
}

Se tudo correr bem, o app delegado receberá a ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED e se torna o delegado. O app pode chamar os métodos neste guia como se fosse o proprietário do dispositivo ou do perfil. Ao ligar DevicePolicyManager, o delegado transmite null para o administrador. argumento do componente.

Instalar pacotes de apps

Às vezes é útil instalar um aplicativo personalizado armazenado em cache localmente em uma dispositivo. Por exemplo, dispositivos dedicados são frequentemente implantados em ambientes com largura de banda limitada ou áreas sem conectividade com a Internet. Seu solução de dispositivo dedicado deve considerar a largura de banda dos clientes. Seu app pode iniciar a instalação de outro pacote de apps (APK) usando o PackageInstaller.

Embora qualquer app possa instalar APKs, os administradores em dispositivos totalmente gerenciados podem instalar (ou desinstalar) pacotes sem interação do usuário. O administrador pode gerenciar no dispositivo, um usuário secundário afiliado ou um perfil de trabalho afiliado. Depois terminando a instalação, o sistema publica uma notificação informando que todos os usuários do dispositivo ver. A notificação informa aos usuários do dispositivo que o app foi instalado (ou atualizado) pelo administrador.

:
Tabela 2. Versões do Android compatíveis com a instalação de pacotes sem interação do usuário
Versão do Android Componente do administrador para instalação e desinstalação
Android 9.0 (nível 28 da API) ou mais recente Usuários secundários afiliados e perfis de trabalho, ambos em plataformas totalmente gerenciadas dispositivos
Ter o Android 6.0 (API de nível 23) ou versões mais recentes Dispositivos totalmente gerenciados

A forma como você distribui uma ou mais cópias do APK para dispositivos dedicados dependem da distância dos dispositivos e, possivelmente, da distância entre eles são umas das outras. Sua solução precisa seguir as práticas recomendadas de segurança antes de instalar APKs em dispositivos dedicados.

Use PackageInstaller.Session para criar uma sessão que enfileira um ou mais APKs para instalação. No exemplo a seguir, recebemos o status feedback em nossa atividade (modo singleTop), mas você pode usar uma serviço ou broadcast receiver:

Kotlin

// First, create a package installer session.
val packageInstaller = context.packageManager.packageInstaller
val params = PackageInstaller.SessionParams(
        PackageInstaller.SessionParams.MODE_FULL_INSTALL)
val sessionId = packageInstaller.createSession(params)
val session = packageInstaller.openSession(sessionId)

// Add the APK binary to the session. The APK is included in our app binary
// and is read from res/raw but file storage is a more typical location.
// The I/O streams can't be open when installation begins.
session.openWrite("apk", 0, -1).use { output ->
    getContext().resources.openRawResource(R.raw.app).use { input ->
        input.copyTo(output, 2048)
    }
}

// Create a status receiver to report progress of the installation.
// We'll use the current activity.
// Here we're requesting status feedback to our Activity but this can be a
// service or broadcast receiver.
val intent = Intent(context, activity.javaClass)
intent.action = "com.android.example.APK_INSTALLATION_ACTION"
val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0)
val statusReceiver = pendingIntent.intentSender

// Start the installation. Because we're an admin of a fully managed device,
// there isn't any user interaction.
session.commit(statusReceiver)

Java

// First, create a package installer session.
PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
    PackageInstaller.SessionParams.MODE_FULL_INSTALL);
int sessionId = packageInstaller.createSession(params);
PackageInstaller.Session session = packageInstaller.openSession(sessionId);

// Add the APK binary to the session. The APK is included in our app binary
// and is read from res/raw but file storage is a more typical location.
try (
    // These I/O streams can't be open when installation begins.
    OutputStream output = session.openWrite("apk", 0, -1);
    InputStream input = getContext().getResources().openRawResource(R.raw.app);
) {
  byte[] buffer = new byte[2048];
  int n;
  while ((n = input.read(buffer)) >= 0) {
    output.write(buffer, 0, n);
  }
}

// Create a status receiver to report progress of the installation.
// We'll use the current activity.
// Here we're requesting status feedback to our Activity but this can be a
// service or broadcast receiver.
Intent intent = new Intent(context, getActivity().getClass());
intent.setAction("com.android.example.APK_INSTALLATION_ACTION");
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
IntentSender statusReceiver = pendingIntent.getIntentSender();

// Start the installation. Because we're an admin of a fully managed device,
// there isn't any user interaction.
session.commit(statusReceiver);

A sessão usa intents para enviar feedback de status sobre a instalação. Marca de seleção campo EXTRA_STATUS de cada intent para receber status. Os administradores não recebem Atualização do status do STATUS_PENDING_USER_ACTION porque o usuário do dispositivo não precisa aprovar a instalação.

Para desinstalar apps, chame PackageInstaller.uninstall. Administradores de dispositivos totalmente gerenciados, usuários e perfis de trabalho podem desinstalar pacotes sem interação do usuário executando versões compatíveis do Android (consulte tabela 2).

Congelar atualizações do sistema

Os dispositivos Android recebem atualizações OTA (over-the-air) no sistema e no aplicativo de software. Para congelar a versão do SO em períodos críticos, como feriados ou em outros horários de pico, os dispositivos dedicados podem suspender atualizações do sistema OTA por até 90 dias. Saiba mais em Gerenciar atualizações do sistema.

Configuração remota

As configurações gerenciadas do Android permitem que os administradores de TI configurar remotamente seu aplicativo. Recomendamos que você exponha configurações como listas de permissões, hosts de rede ou URLs de conteúdo para tornar seu app mais útil para a equipe de TI do Google Cloud.

Se o seu aplicativo expõe sua configuração, lembre-se de incluí-las no seu na documentação do Google Cloud. Para saber mais sobre como expor a configuração do app e reagir a mudar as configurações, leia Definir configurações gerenciadas.

Configuração de desenvolvimento

Ao desenvolver uma solução para dispositivos dedicados, útil para definir seu aplicativo como o administrador de um dispositivo totalmente gerenciado sem uma fábrica redefinido. Para configurar o administrador de um dispositivo totalmente gerenciado, siga estas etapas:

  1. Crie e instale seu app controlador de política de dispositivo (DPC) no dispositivo.
  2. Verifique se não há contas no dispositivo.
  3. Execute o seguinte comando no shell do Android Debug Bridge (adb). Você é necessário substituir com.example.dpc/.MyDeviceAdminReceiver no exemplo por nome do componente de administrador do seu app:

    adb shell dpm set-device-owner com.example.dpc/.MyDeviceAdminReceiver

Para ajudar os clientes a implantar a solução, você precisará conferir outros tipos de métodos. Recomendamos o registro com QR code para dispositivos dedicados.

Outros recursos

Para saber mais sobre dispositivos dedicados, leia os seguintes documentos: