Entradas e sensores

O SDK do Android oferece acesso às várias entradas e sensores disponíveis com o Glass EE2. Esta página oferece uma visão geral dos recursos disponíveis, detalhes de implementação e dicas úteis.

Gestos de toque

Você pode usar o SDK do Android para permitir o acesso a dados brutos do touchpad do Glass. Isso é feito com um detector de gestos que detecta automaticamente gestos comuns no Google Glass, como tocar, deslizar e rolar.

Você também pode usar esse detector de gestos nos seus apps para considerar a ação de tocar, deslizar para frente, deslizar para trás e deslizar para baixo. Isso é semelhante aos dispositivos anteriores do Google Glass.

É melhor usar esses gestos das seguintes maneiras:

  • Toque em"Confirmar"ou"Enter".
  • Deslizar para frente, deslizar para trás: navegar pelos cards e telas
  • Deslizar para baixo: voltar ou sair.

Para ver detalhes de implementação, leia o exemplo de detector de gestos.

Detectar gestos com o detector de gestos do Android

O GestureDetector do Android permite detectar gestos simples e complexos, como aqueles que usam vários dedos ou rolagem.

Detectar gestos no nível da atividade

Detecte gestos no nível da atividade somente quando não importa qual parte da IU está em foco. Por exemplo, caso você queira abrir um menu quando um usuário tocar no touchpad, independentemente da visualização em foco, processe o MotionEvent dentro da atividade.

Veja a seguir um exemplo de detecção de gestos no nível da atividade que usa GestureDetector e implementa GestureDetector.OnGestureListener para processar gestos reconhecidos, que são tratados e traduzidos para o seguinte:

  • TAP
  • SWIPE_FORWARD
  • SWIPE_BACKWARD
  • SWIPE_UP
  • SWIPE_DOWN

Kotlin

class GlassGestureDetector(context: Context, private val onGestureListener: OnGestureListener) :
    GestureDetector.OnGestureListener {

    private val gestureDetector = GestureDetector(context, this)

    enum class Gesture {
        TAP,
        SWIPE_FORWARD,
        SWIPE_BACKWARD,
        SWIPE_UP,
        SWIPE_DOWN
    }

    interface OnGestureListener {
        fun onGesture(gesture: Gesture): Boolean
    }

    fun onTouchEvent(motionEvent: MotionEvent): Boolean {
        return gestureDetector.onTouchEvent(motionEvent)
    }

    override fun onDown(e: MotionEvent): Boolean {
        return false
    }

    override fun onShowPress(e: MotionEvent) {}

    override fun onSingleTapUp(e: MotionEvent): Boolean {
        return onGestureListener.onGesture(Gesture.TAP)
    }

    override fun onScroll(
        e1: MotionEvent,
        e2: MotionEvent,
        distanceX: Float,
        distanceY: Float
    ): Boolean {
        return false
    }

    override fun onLongPress(e: MotionEvent) {}

    /**
     * Swipe detection depends on the:
     * - movement tan value,
     * - movement distance,
     * - movement velocity.
     *
     * To prevent unintentional SWIPE_DOWN and SWIPE_UP gestures, they are detected if movement
     * angle is only between 60 and 120 degrees.
     * Any other detected swipes, will be considered as SWIPE_FORWARD and SWIPE_BACKWARD, depends
     * on deltaX value sign.
     *
     * ______________________________________________________________
     * |                     \        UP         /                    |
     * |                       \               /                      |
     * |                         60         120                       |
     * |                           \       /                          |
     * |                             \   /                            |
     * |  BACKWARD  <-------  0  ------------  180  ------>  FORWARD  |
     * |                             /   \                            |
     * |                           /       \                          |
     * |                         60         120                       |
     * |                       /               \                      |
     * |                     /       DOWN        \                    |
     * --------------------------------------------------------------
     */
    override fun onFling(
        e1: MotionEvent,
        e2: MotionEvent,
        velocityX: Float,
        velocityY: Float
    ): Boolean {
        val deltaX = e2.x - e1.x
        val deltaY = e2.y - e1.y
        val tan =
            if (deltaX != 0f) abs(deltaY / deltaX).toDouble() else java.lang.Double.MAX_VALUE

        return if (tan > TAN_60_DEGREES) {
            if (abs(deltaY) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityY) < SWIPE_VELOCITY_THRESHOLD_PX) {
                false
            } else if (deltaY < 0) {
                onGestureListener.onGesture(Gesture.SWIPE_UP)
            } else {
                onGestureListener.onGesture(Gesture.SWIPE_DOWN)
            }
        } else {
            if (Math.abs(deltaX) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityX) < SWIPE_VELOCITY_THRESHOLD_PX) {
                false
            } else if (deltaX < 0) {
                onGestureListener.onGesture(Gesture.SWIPE_FORWARD)
            } else {
                onGestureListener.onGesture(Gesture.SWIPE_BACKWARD)
            }
        }
    }

    companion object {

        private const val SWIPE_DISTANCE_THRESHOLD_PX = 100
        private const val SWIPE_VELOCITY_THRESHOLD_PX = 100
        private val TAN_60_DEGREES = tan(Math.toRadians(60.0))
    }
}

Java

  public class GlassGestureDetector implements GestureDetector.OnGestureListener {

   enum Gesture {
     TAP,
     SWIPE_FORWARD,
     SWIPE_BACKWARD,
     SWIPE_UP,
     SWIPE_DOWN,
   }

   interface OnGestureListener {
     boolean onGesture(Gesture gesture);
   }

   private static final int SWIPE_DISTANCE_THRESHOLD_PX = 100;
   private static final int SWIPE_VELOCITY_THRESHOLD_PX = 100;
   private static final double TAN_60_DEGREES = Math.tan(Math.toRadians(60));

   private GestureDetector gestureDetector;
   private OnGestureListener onGestureListener;

   public GlassGestureDetector(Context context, OnGestureListener onGestureListener) {
     gestureDetector = new GestureDetector(context, this);
     this.onGestureListener = onGestureListener;
   }

   public boolean onTouchEvent(MotionEvent motionEvent) {
     return gestureDetector.onTouchEvent(motionEvent);
   }

   @Override
   public boolean onDown(MotionEvent e) {
     return false;
   }

   @Override
   public void onShowPress(MotionEvent e) {
   }

   @Override
   public boolean onSingleTapUp(MotionEvent e) {
     return onGestureListener.onGesture(Gesture.TAP);
   }

   @Override
   public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
     return false;
   }

   @Override
   public void onLongPress(MotionEvent e) {
   }

   /**
    * Swipe detection depends on the:
    * - movement tan value,
    * - movement distance,
    * - movement velocity.
    *
    * To prevent unintentional SWIPE_DOWN and SWIPE_UP gestures, they are detected if movement
    * angle is only between 60 and 120 degrees.
    * Any other detected swipes, will be considered as SWIPE_FORWARD and SWIPE_BACKWARD, depends
    * on deltaX value sign.
    *
    *           ______________________________________________________________
    *          |                     \        UP         /                    |
    *          |                       \               /                      |
    *          |                         60         120                       |
    *          |                           \       /                          |
    *          |                             \   /                            |
    *          |  BACKWARD  <-------  0  ------------  180  ------>  FORWARD  |
    *          |                             /   \                            |
    *          |                           /       \                          |
    *          |                         60         120                       |
    *          |                       /               \                      |
    *          |                     /       DOWN        \                    |
    *           --------------------------------------------------------------
    */
   @Override
   public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
     final float deltaX = e2.getX() - e1.getX();
     final float deltaY = e2.getY() - e1.getY();
     final double tan = deltaX != 0 ? Math.abs(deltaY/deltaX) : Double.MAX_VALUE;

     if (tan > TAN_60_DEGREES) {
       if (Math.abs(deltaY) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityY) < SWIPE_VELOCITY_THRESHOLD_PX) {
         return false;
       } else if (deltaY < 0) {
         return onGestureListener.onGesture(Gesture.SWIPE_UP);
       } else {
         return onGestureListener.onGesture(Gesture.SWIPE_DOWN);
       }
     } else {
       if (Math.abs(deltaX) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityX) < SWIPE_VELOCITY_THRESHOLD_PX) {
         return false;
       } else if (deltaX < 0) {
         return onGestureListener.onGesture(Gesture.SWIPE_FORWARD);
       } else {
         return onGestureListener.onGesture(Gesture.SWIPE_BACKWARD);
       }
     }
   }
  }

Exemplo de uso

Para usar a detecção de gestos no nível da atividade, você precisa concluir as seguintes tarefas:

  1. Adicione a seguinte declaração ao arquivo de manifesto dentro da declaração do aplicativo. Isso permite que o app receba o MotionEvent na atividade:
    <application>
    <!-- Copy below declaration into your manifest file -->
    <meta-data
      android:name="com.google.android.glass.TouchEnabledApplication"
      android:value="true" />
    </application>
    
  2. Substitua o método dispatchTouchEvent(motionEvent) da atividade para transmitir os eventos de movimento ao método onTouchEvent(motionEvent) do detector de gestos.
  3. Implemente GlassGestureDetector.OnGestureListener na sua atividade.

Veja a seguir um exemplo de detector de gestos no nível da atividade:

Kotlin

class MainAcvitiy : AppCompatActivity(), GlassGestureDetector.OnGestureListener {

    private lateinit var glassGestureDetector: GlassGestureDetector

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

        glassGestureDetector = GlassGestureDetector(this, this)
    }

    override fun onGesture(gesture: GlassGestureDetector.Gesture): Boolean {
        when (gesture) {
            TAP ->
                // Response for TAP gesture
                return true
            SWIPE_FORWARD ->
                // Response for SWIPE_FORWARD gesture
                return true
            SWIPE_BACKWARD ->
                // Response for SWIPE_BACKWARD gesture
                return true
            else -> return false
        }
    }

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        return if (glassGestureDetector.onTouchEvent(ev)) {
            true
        } else super.dispatchTouchEvent(ev)
    }
}

Java

  public class MainActivity extends AppCompatActivity implements OnGestureListener {

   private GlassGestureDetector glassGestureDetector;

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

     glassGestureDetector = new GlassGestureDetector(this, this);
   }

   @Override
   public boolean onGesture(Gesture gesture) {
     switch (gesture) {
       case TAP:
         // Response for TAP gesture
         return true;
       case SWIPE_FORWARD:
         // Response for SWIPE_FORWARD gesture
         return true;
       case SWIPE_BACKWARD:
         // Response for SWIPE_BACKWARD gesture
         return true;
       default:
         return false;
     }
   }

   @Override
   public boolean dispatchTouchEvent(MotionEvent ev) {
     if (glassGestureDetector.onTouchEvent(ev)) {
       return true;
     }
     return super.dispatchTouchEvent(ev);
   }
  }

Entrada de áudio

O Glass Enterprise Edition 2 é um dispositivo baseado em AOSP padrão que oferece suporte a fontes de áudio básicas.

As seguintes fontes de áudio têm o processamento avançado de indicadores implementado:

Reconhecimento de voz

O Glass Enterprise Edition 2 é compatível com uma implementação nativa para reconhecimento de fala. Só há suporte para esse idioma em inglês.

Imagem de reconhecimento de voz de vidro.

A IU de reconhecimento de fala aguarda até que um usuário fale e, em seguida, retorna o texto transcrito. Para iniciar a atividade, siga estas etapas:

  1. Chame startActivityForResult() com a intent ACTION_RECOGNIZE_SPEECH. Os extras de intent a seguir são compatíveis quando você inicia a atividade:
  2. Modifique o callback onActivityResult() para receber o texto transcrito da intent EXTRA_RESULTS extra, conforme mostrado no exemplo de código a seguir. Esse callback é chamado quando o usuário termina de falar.

Kotlin

private const val SPEECH_REQUEST = 109

private fun displaySpeechRecognizer() {
    val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
    startActivityForResult(intent, SPEECH_REQUEST)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    if (requestCode == SPEECH_REQUEST && resultCode == RESULT_OK) {
        val results: List<String>? =
            data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
        val spokenText = results?.get(0)
        // Do something with spokenText.
    }
    super.onActivityResult(requestCode, resultCode, data)
}

Java

private static final int SPEECH_REQUEST = 109;

private void displaySpeechRecognizer() {
    Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
    startActivityForResult(intent, SPEECH_REQUEST);
}

@Override
protected void onActivityResult(int requestCode, int resultCode,
        Intent data) {
    if (requestCode == SPEECH_REQUEST && resultCode == RESULT_OK) {
        List<String> results = data.getStringArrayListExtra(
                RecognizerIntent.EXTRA_RESULTS);
        String spokenText = results.get(0);
        // Do something with spokenText.
    }
    super.onActivityResult(requestCode, resultCode, data);
}

Para ver detalhes de implementação, leia a amostra de app de reconhecimento de voz.

Viés de palavras-chave

O reconhecimento de fala no Google Glass pode ser enviesado para uma lista de palavras-chave. A sobrecarga aumenta a precisão do reconhecimento de palavras-chave. Para ativar a polarização de palavras-chave, use o seguinte:

Kotlin

val keywords = arrayOf("Example", "Biasing", "Keywords")

val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
intent.putExtra("recognition-phrases", keywords)

startActivityForResult(intent, SPEECH_REQUEST)

Java

final String[] keywords = {"Example", "Biasing", "Keywords"};

Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra("recognition-phrases", keywords);

startActivityForResult(intent, SPEECH_REQUEST);

Comandos de voz

Com os comandos de voz, os usuários podem realizar ações nas atividades. Você cria comandos de voz com as APIs padrão de menu do Android, mas os usuários podem invocar os itens de menu com comandos de voz em vez de toque.

Para ativar os comandos de voz para uma atividade específica, siga estas etapas:

  1. Chame getWindow().requestFeature(FEATURE_VOICE_COMMANDS) na atividade desejada para ativar os comandos de voz. Com esse recurso ativado, o ícone do microfone aparece no canto inferior esquerdo da tela sempre que essa atividade receber o foco.
  2. Solicite a permissão RECORD_AUDIO no seu app.
  3. Substitua onCreatePanelMenu() e infle um recurso de menu.
  4. Substitua onContextItemSelected() para processar os comandos de voz detectados.

Kotlin

class VoiceCommandsActivity : AppCompatActivity() {

    companion object {
        const val FEATURE_VOICE_COMMANDS = 14
        const val REQUEST_PERMISSION_CODE = 200
        val PERMISSIONS = arrayOf(Manifest.permission.RECORD_AUDIO)
        val TAG = VoiceCommandsActivity::class.java.simpleName
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        window.requestFeature(FEATURE_VOICE_COMMANDS)
        setContentView(R.layout.activity_voice_commands)

        // Requesting permissions to enable voice commands menu
        ActivityCompat.requestPermissions(
            this,
            PERMISSIONS,
            REQUEST_PERMISSION_CODE
        )
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        if (requestCode == REQUEST_PERMISSION_CODE) {
            for (result in grantResults) {
                if (result != PackageManager.PERMISSION_GRANTED) {
                    Log.d(TAG, "Permission denied. Voice commands menu is disabled.")
                }
            }
        } else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        }
    }

    override fun onCreatePanelMenu(featureId: Int, menu: Menu): Boolean {
        menuInflater.inflate(R.menu.voice_commands_menu, menu)
        return true
    }

    override fun onContextItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            // Handle selected menu item
            R.id.edit -> {
                // Handle edit action
                true
            }
            else -> super.onContextItemSelected(item)
        }
    }
}

Java

public class VoiceCommandsActivity extends AppCompatActivity {

  private static final String TAG = VoiceCommandsActivity.class.getSimpleName();
  private static final int FEATURE_VOICE_COMMANDS = 14;
  private static final int REQUEST_PERMISSION_CODE = 200;
  private static final String[] PERMISSIONS = new String[]{Manifest.permission.RECORD_AUDIO};

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().requestFeature(FEATURE_VOICE_COMMANDS);
    setContentView(R.layout.activity_voice_commands);

    // Requesting permissions to enable voice commands menu
    ActivityCompat.requestPermissions(this, PERMISSIONS, REQUEST_PERMISSION_CODE);
  }

  @Override
  public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (requestCode == REQUEST_PERMISSION_CODE) {
      for (int result : grantResults) {
        if (result != PackageManager.PERMISSION_GRANTED) {
          Log.d(TAG, "Permission denied. Voice commands menu is disabled.");
        }
      }
    } else {
      super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
  }

  @Override
  public boolean onCreatePanelMenu(int featureId, @NonNull Menu menu) {
    getMenuInflater().inflate(R.menu.voice_commands_menu, menu);
    return true;
  }

  @Override
  public boolean onContextItemSelected(@NonNull MenuItem item) {
    switch (item.getItemId()) {
      // Handle selected menu item
      case R.id.edit:
        // Handle edit action
        return true;
      default:
        return super.onContextItemSelected(item);
    }
  }
}

Veja a seguir um exemplo do recurso de menu usado pela atividade anterior:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/delete"
        android:icon="@drawable/ic_delete"
        android:title="@string/delete"/>
    <item
        android:id="@+id/edit"
        android:icon="@drawable/ic_edit"
        android:title="@string/edit"/>
    <item
        android:id="@+id/find"
        android:icon="@drawable/ic_search"
        android:title="@string/find"/>
</menu>

Leia o app de notas de exemplo para ver um exemplo completo.

Recarregando lista de comandos de voz

Você pode recarregar dinamicamente a lista de comandos de voz. Para fazer isso, substitua o recurso menu no método onCreatePanelMenu() ou modifique o objeto de menu no método onPreparePanel(). Para aplicar alterações, chame o método invalidateOptionsMenu().

Kotlin

private val options = mutableListOf<String>()

fun onPreparePanel(featureId: Int, view: View?, menu: Menu): Boolean {
  if (featureId != FEATURE_VOICE_COMMANDS) {
    return super.onCreatePanelMenu(featureId, menu)
  }
  for (optionTitle in options) {
    menu.add(optionTitle)
  }
  return true
}

/**
 * Method showing example implementation of voice command list modification
 *
 * If you call [Activity.invalidateOptionsMenu] method, voice command  list will be
 * reloaded (onCreatePanelMenu and onPreparePanel methods will be called).
 */
private fun modifyVoiceCommandList() {
  options.add("Delete")
  options.add("Play")
  options.add("Pause")
  invalidateOptionsMenu()
}

Java

private final List<String> options = new ArrayList<>();

@Override
public boolean onPreparePanel(int featureId, View view, Menu menu) {
  if (featureId != FEATURE_VOICE_COMMANDS) {
    return super.onCreatePanelMenu(featureId, menu);
  }
  for (String optionTitle : options) {
    menu.add(optionTitle);
  }
  return true;
}

/**
 * Method showing example implementation of voice command list modification
 *
 * If you call {@link Activity#invalidateOptionsMenu()} method, voice command  list will be
 * reloaded (onCreatePanelMenu and onPreparePanel methods will be called).
 */
private void modifyVoiceCommandList() {
  options.add("Delete");
  options.add("Play");
  options.add("Pause");
  invalidateOptionsMenu();
}

Solução AppCompatActivity

Para recarregar uma lista de comandos de voz em uma atividade que estenda AppCompatActivity, use o método sendBroadcast() com a ação da intent reload-voice-commands:

Kotlin

sendBroadcast(Intent("reload-voice-commands"))

Java

sendBroadcast(new Intent("reload-voice-commands"));

Ativar e desativar comandos de voz no momento da execução

Você pode ativar e desativar os comandos de voz no momento da execução. Para fazer isso, retorne um valor apropriado do método onCreatePanelMenu() da seguinte maneira:

  • Defina o valor como true para ativar.
  • Defina o valor como false para desativar.

Modo de depuração

Para ativar o modo de depuração de comandos de voz, chame getWindow().requestFeature(FEATURE_DEBUG_VOICE_COMMANDS) na atividade desejada. O modo de depuração ativa os seguintes recursos:

  • O Logcat contém o registro com a frase reconhecida para depuração.
  • A sobreposição de IU é exibida quando um comando não reconhecido é detectado:
  • Imagem de comando não reconhecida de reconhecimento de voz em vidro.

Kotlin

class VoiceCommandsActivity : AppCompatActivity() {

    companion object {
        const val FEATURE_VOICE_COMMANDS = 14
        const val FEATURE_DEBUG_VOICE_COMMANDS = 15
        const val REQUEST_PERMISSION_CODE = 200
        val PERMISSIONS = arrayOf(Manifest.permission.RECORD_AUDIO)
        val TAG = VoiceCommandsActivity::class.java.simpleName
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        window.requestFeature(FEATURE_VOICE_COMMANDS)
        window.requestFeature(FEATURE_DEBUG_VOICE_COMMANDS)
        setContentView(R.layout.activity_voice_commands)

        // Requesting permissions to enable voice commands menu
        ActivityCompat.requestPermissions(
            this,
            PERMISSIONS,
            REQUEST_PERMISSION_CODE
        )
    }
    .
    .
    .
}

Java

public class VoiceCommandsActivity extends AppCompatActivity {

  private static final String TAG = VoiceCommandsActivity.class.getSimpleName();
  private static final int FEATURE_VOICE_COMMANDS = 14;
  private static final int FEATURE_DEBUG_VOICE_COMMANDS = 15;
  private static final int REQUEST_PERMISSION_CODE = 200;
  private static final String[] PERMISSIONS = new String[]{Manifest.permission.RECORD_AUDIO};

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().requestFeature(FEATURE_VOICE_COMMANDS);
    getWindow().requestFeature(FEATURE_DEBUG_VOICE_COMMANDS);
    setContentView(R.layout.activity_voice_commands);

    // Requesting permissions to enable voice commands menu
    ActivityCompat.requestPermissions(this, PERMISSIONS, REQUEST_PERMISSION_CODE);
  }
  .
  .
  .
}

Para ver detalhes sobre a implementação, leia o exemplo de app de recarga de comandos de voz.

Conversão de texto em voz (TTS, na sigla em inglês)

A funcionalidade Text-to-Speech converte texto digital em saída de fala sintetizada. Para mais informações, acesse a TextToSpeech da documentação para desenvolvedores Android.

O Glass EE2 tem o mecanismo de conversão de texto em voz do Google instalado. Ele é definido como o mecanismo de TTS padrão e funciona off-line.

As seguintes localidades estão incluídas no mecanismo de conversão de texto em voz do Google:

Bengali
Chinês em mandarim
Tcheco
Dinamarquês
Alemão
Grego
Inglês
Espanhol
Estoniano
Finlandês
Francês
Guzerate
Híndi
Húngaro
Indonésio
Italiano
Japonês
Javanês
Austronésio
Austroastromático
Canarês
Coreano
Malaiala
Norueguês
Holandês
Polonês
Português
Russo
Eslovaco
Sudanês
Sueco
Tâmil
Télugo
Tailandês
Turco
Ucraniano
Vietnamita

Câmera

O Glass Enterprise Edition 2 tem um câmera de foco fixo de 8 megapixels que tem uma abertura de f/2,4, proporção de sensor 4:3 e campo de visão diagonal de 83° (orientação paisagem de 71° x 57°). Recomendamos que você use a API CameraX ou Camera2 padrão.

Para ver detalhes de implementação, leia o app de câmera de amostra.

Botão "Câmera"

O botão da câmera é o botão físico na articulação do dispositivo do Glass Enterprise Edition 2. Isso pode ser processado como uma ação de teclado padrão e identificado pelo código de tecla KeyEvent#KEYCODE_CAMERA.

A partir da atualização do SO OPM1.200313.001, as intents com as seguintes ações são enviadas do aplicativo inicializador:

Sensores

Existem vários sensores disponíveis para desenvolvedores que desenvolvem aplicativos no Glass EE2.

Os seguintes sensores padrão do Android são compatíveis com o Google Glass:

Os seguintes sensores Android não são compatíveis com o Google Glass:

O sistema de coordenadas do sensor de vidro é mostrado na ilustração a seguir. Ele é relacionado à tela do Glass. Para ver mais informações, consulte Sistema de coordenadas do sensor.

O sistema de coordenadas do sensor de vidro é mostrado aqui em relação à tela do Glass.

O acelerômetro, o giroscópio e o magnetômetro estão localizados no pod óptico do dispositivo de vidro, que os usuários giram para alinhar o dispositivo com a visão deles. Não é possível medir o ângulo do pod óptico diretamente, portanto, esteja ciente disso ao usar ângulos desses sensores para aplicativos, como a direção de uma bússola.

Para prolongar a duração da bateria, ouça os sensores somente quando precisar deles. Considere as necessidades e o ciclo de vida do app ao decidir quando começar e parar de ouvir os sensores.

Os callbacks de eventos do sensor são executados na linha de execução de IU. Portanto, processe eventos e retornes o mais rápido possível. Se o processamento demorar muito, envie os eventos do sensor para uma fila e use uma linha de execução em segundo plano para processá-los.

50 Hz geralmente é uma taxa de amostragem suficiente para rastrear o movimento da cabeça.

Para mais informações sobre como usar os sensores, consulte o Guia para desenvolvedores Android.

Serviços de localização

O dispositivo Glass Enterprise Edition 2 não tem um módulo de GPS e não fornece a localização do usuário. No entanto, ele tem serviços de localização implementados, o que é necessário para exibir uma lista de redes Wi-Fi e dispositivos Bluetooth próximos.

Se o aplicativo tiver privilégios de proprietário do dispositivo, você poderá usá-lo para mudar programaticamente o valor da configuração segura correspondente:

Kotlin

val devicePolicyManager = context
    .getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
if (devicePolicyManager.isDeviceOwnerApp(context.getPackageName())) {
    val componentName = ComponentName(context, MyDeviceAdmin::class.java)
    devicePolicyManager.setSecureSetting(
        componentName,
        Settings.Secure.LOCATION_MODE,
        Settings.Secure.LOCATION_MODE_SENSORS_ONLY.toString()
    )
}

Java

final DevicePolicyManager devicePolicyManager = (DevicePolicyManager) context
    .getSystemService(Context.DEVICE_POLICY_SERVICE);
if (devicePolicyManager.isDeviceOwnerApp(context.getPackageName())) {
  final ComponentName componentName = new ComponentName(context, MyDeviceAdmin.class);
  devicePolicyManager.setSecureSetting(componentName, Settings.Secure.LOCATION_MODE,
      String.valueOf(Settings.Secure.LOCATION_MODE_SENSORS_ONLY));
}

Se você usa uma solução de MDM de terceiros, ela precisa ser capaz de alterar essas configurações para você.