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:
- 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>
- Substitua o método
dispatchTouchEvent(motionEvent)
da atividade para transmitir os eventos de movimento ao métodoonTouchEvent(motionEvent)
do detector de gestos. - 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.
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:
- Chame
startActivityForResult()
com a intentACTION_RECOGNIZE_SPEECH
. Os extras de intent a seguir são compatíveis quando você inicia a atividade: - Modifique o
callback
onActivityResult()
para receber o texto transcrito da intentEXTRA_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:
- 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. - Solicite a permissão
RECORD_AUDIO
no seu app. - Substitua
onCreatePanelMenu()
e infle um recurso de menu. - 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:
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:
MediaStore#ACTION_IMAGE_CAPTURE
no botão da câmera.MediaStore#ACTION_VIDEO_CAPTURE
no botão da câmera e manter pressionado.
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:
-
TYPE_ACCELEROMETER
-
TYPE_GRAVITY
-
TYPE_GYROSCOPE
-
TYPE_LIGHT
-
TYPE_LINEAR_ACCELERATION
-
TYPE_MAGNETIC_FIELD
-
TYPE_ORIENTATION
(descontinuado) -
TYPE_ROTATION_VECTOR
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 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ê.