O SDK do Android dá acesso às várias entradas e sensores disponíveis com o Glass EE2. Nesta página, você encontra uma visão geral dos recursos disponíveis, detalhes da implementação e dicas úteis.
Gestos de toque
É possível usar o SDK do Android para ativar o acesso a dados brutos do touchpad do Glass. Isso é realizado por um detector de gestos que detecta automaticamente gestos comuns no Glass, como toque, deslize e rolagem.
Você também pode usar esse detector de gestos nos seus apps para considerar toques, deslizar para frente, para trás e para baixo. Isso é semelhante aos dispositivos Glass anteriores.
É melhor usar esses gestos das seguintes maneiras:
- Toque: confirme ou insira.
- Deslizar para frente, deslizar para trás: navegue pelos cards e telas.
- Deslizar para baixo: voltar ou sair.
Para detalhes de implementação, leia o detector de gestos de exemplo.
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 apenas quando não importa qual parte da interface tem foco.
Por exemplo, se você quiser abrir um menu quando um usuário tocar no touchpad,
independente de qual visualização está em foco, processe o
MotionEvent
na atividade.
Confira abaixo 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
processados e traduzidos para o seguinte:
TAPSWIPE_FORWARDSWIPE_BACKWARDSWIPE_UPSWIPE_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, conclua 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
MotionEventna 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.OnGestureListenerna sua atividade.
Confira 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 padrão baseado no AOSP que oferece suporte a fontes de áudio básicas.
As seguintes fontes de áudio têm processamento de sinal avançado implementado:
Reconhecimento de voz
O Glass Enterprise Edition 2 oferece suporte a uma implementação nativa para reconhecimento de fala. Esse recurso está disponível apenas em inglês.
A interface do reconhecimento de fala aguarda o usuário falar e retorna o texto transcrito depois que ele termina. Para iniciar a atividade, siga estas etapas:
- Chame
startActivityForResult()com a intentACTION_RECOGNIZE_SPEECH. Os seguintes extras de intent são compatíveis ao iniciar a atividade: - Substitua o callback
onActivityResult()para receber o texto transcrito do extra de intentEXTRA_RESULTSconforme 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 detalhes da implementação, leia o app de exemplo de reconhecimento de voz.
Tendência para palavras-chave
O reconhecimento de fala no Glass pode ser tendencioso para uma lista de palavras-chave. O ajuste aumenta a precisão do reconhecimento de palavras-chave. Para ativar a tendência para 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 em atividades. Você cria comandos de voz com as APIs de menu padrão 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 em 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 recebe foco. - Solicite a permissão
RECORD_AUDIOno 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); } } }
Confira 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 exemplo para anotações e confira um exemplo completo.
A lista de comandos de voz está sendo recarregada
É possível 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 as mudanças, 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 estende AppCompatActivity, use o método
sendBroadcast()
com a ação de intent reload-voice-commands:
Kotlin
sendBroadcast(Intent("reload-voice-commands"))
Java
sendBroadcast(new Intent("reload-voice-commands"));
Ativar e desativar comandos de voz durante a execução
É possível ativar e desativar os comandos de voz durante a execução. Para fazer isso, retorne um valor adequado do método
onCreatePanelMenu()
da seguinte maneira:
- Defina o valor como
truepara ativar. - Defina o valor como
falsepara desativar.
Modo de depuração
Para ativar o modo de depuração para 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 da interface é mostrada quando um comando não reconhecido é detectado, como mostrado abaixo:
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 detalhes da implementação, leia o app de recarregamento de comandos de voz de exemplo.
Conversão de texto em voz (TTS)
A funcionalidade Text-to-Speech converte texto digital em saída de fala sintetizada. Para mais informações, acesse Documentação do Android Developers TextToSpeech.
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 (mandarim) Tcheco Dinamarquês Alemão Grego Inglês Espanhol Estoniano Finlandês Francês Guzerate Hindi |
Húngaro Indonésio Italiano Japonês Javanês Austronésio Austro-asiático Canará Coreano Malaiala Norueguês Holandês |
Polonês Português Russo Eslovaco Sundanês Sueco Tâmil Telugu Tailandês Turco Ucraniano Vietnamita |
Câmera
O Glass Enterprise Edition 2 está equipado com uma câmera de 8 megapixels e foco fixo com abertura de f/2,4, proporção de sensor de 4:3 e campo de visão diagonal de 83° (71° x 57° na orientação paisagem). Recomendamos usar a API padrão CameraX ou Camera2.
Para detalhes da implementação, leia o app de câmera de exemplo.
Botão "Câmera"
O botão da câmera é o botão físico na dobradiça do dispositivo Glass Enterprise Edition 2.
Ele 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 app Launcher:
MediaStore#ACTION_IMAGE_CAPTUREao pressionar rapidamente o botão da câmera.MediaStore#ACTION_VIDEO_CAPTUREao tocar e pressionar o botão da câmera.
Sensores
Há vários sensores disponíveis para os desenvolvedores criarem aplicativos no Glass EE2.
Os seguintes sensores padrão do Android são compatíveis com o Glass:
-
TYPE_ACCELEROMETER -
TYPE_GRAVITY -
TYPE_GYROSCOPE -
TYPE_LIGHT -
TYPE_LINEAR_ACCELERATION -
TYPE_MAGNETIC_FIELD -
TYPE_ORIENTATION(obsoleto) -
TYPE_ROTATION_VECTOR
Os seguintes sensores do Android não são compatíveis com o Glass:
O sistema de coordenadas do sensor do Glass é mostrado na ilustração a seguir. Ele é relativo à tela do Glass. Para mais informações, consulte Sistema de coordenadas do sensor.
O acelerômetro, o giroscópio e o magnetômetro estão localizados no módulo óptico do dispositivo Glass, que os usuários giram para alinhar o dispositivo à visão. Não é possível medir o ângulo do módulo óptico diretamente. Portanto, tenha isso em mente ao usar ângulos desses sensores para aplicativos, como uma direção de bússola.
Para preservar a bateria, ouça os sensores apenas quando necessário. Considere as necessidades e o ciclo de vida do app ao decidir quando começar e parar de usar os sensores.
Os callbacks de eventos do sensor são executados na linha de execução da interface. Portanto, processe eventos e retornos 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 sensores, consulte o guia para desenvolvedores Android.
Serviços de Localização
O dispositivo Glass Enterprise Edition 2 não está equipado com um módulo GPS e não informa a localização do usuário. No entanto, ele tem serviços de localização implementados, o que é necessário para mostrar uma lista de redes Wi-Fi e dispositivos Bluetooth por perto.
Se o aplicativo tiver privilégios de proprietário do dispositivo, use-o para mudar de forma programática 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 conseguir mudar essas configurações para você.