L'SDK Android ti consente di accedere ai vari input e sensori disponibili con Glass EE2. Questa pagina fornisce una panoramica delle funzionalità disponibili, dei dettagli di implementazione e suggerimenti utili.
Gesti tattili
Puoi utilizzare l'SDK Android per attivare l'accesso ai dati non elaborati dal touchpad di Glass. Ciò avviene tramite un rilevatore di gesti che rileva automaticamente i gesti comuni su Glass, come toccare, scorrere e sfogliare.
Puoi anche utilizzare questo rilevatore di gesti nelle tue app per tenere conto di tocco, scorrimento in avanti, scorrimento indietro e scorrimento verso il basso. È simile ai precedenti dispositivi Glass.
È consigliabile utilizzare questi gesti nei seguenti modi:
- Tocca: conferma o inserisci.
- Scorrere in avanti, scorrere indietro: naviga tra le schede e le schermate.
- Scorri verso il basso: torna indietro o esci.
Per i dettagli di implementazione, leggi il rilevatore di gesti di esempio.
Rilevare i gesti con il rilevatore di gesti di Android
L'GestureDetector di Android
consente di rilevare gesti semplici e complessi, ad esempio quelli che utilizzano più dita o lo scorrimento.
Rilevare i gesti a livello di attività
Rileva i gesti a livello di attività solo quando non importa quale parte della UI è attiva.
Ad esempio, se vuoi visualizzare un menu quando un utente tocca il touchpad,
indipendentemente dalla visualizzazione attiva, gestisci
MotionEvent
all'interno dell'attività.
Di seguito è riportato un esempio di rilevamento dei gesti a livello di attività che utilizza
GestureDetector e implementa
GestureDetector.OnGestureListener per elaborare i gesti riconosciuti, che vengono
poi gestiti e tradotti in quanto segue:
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); } } } }
Esempi di utilizzo
Per utilizzare il rilevamento dei gesti a livello di attività, devi completare le seguenti attività:
- Aggiungi la seguente dichiarazione al file manifest, all'interno della dichiarazione dell'applicazione. In questo modo,
la tua app può ricevere l'intent
MotionEventnell'attività:<application> <!-- Copy below declaration into your manifest file --> <meta-data android:name="com.google.android.glass.TouchEnabledApplication" android:value="true" /> </application>
- Esegui l'override del metodo
dispatchTouchEvent(motionEvent)dell'attività per passare gli eventi di movimento al metodoonTouchEvent(motionEvent)del rilevatore di gesti. - Implementa
GlassGestureDetector.OnGestureListenernella tua attività.
Di seguito è riportato un esempio di rilevatore di gesti a livello di attività:
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); } }
Input audio
Glass Enterprise Edition 2 è un dispositivo standard basato su AOSP che supporta le origini audio di base.
Le seguenti sorgenti audio hanno implementato l'elaborazione avanzata del segnale:
Riconoscimento vocale
Glass Enterprise Edition 2 supporta un'implementazione nativa per il riconoscimento vocale. Questa funzionalità è supportata solo per l'inglese.
L'interfaccia utente del riconoscimento vocale attende che gli utenti parlino e poi restituisce il testo trascritto dopo che hanno terminato. Per avviare l'attività, segui questi passaggi:
- Chiama
startActivityForResult()con l'intentACTION_RECOGNIZE_SPEECH. Quando avvii l'attività, sono supportati i seguenti extra intent: - Esegui l'override del
callback
onActivityResult()per ricevere il testo trascritto dall'extra dell'intentEXTRA_RESULTScome mostrato nel seguente esempio di codice. Questo callback viene chiamato quando l'utente finisce di parlare.
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); }
Per i dettagli di implementazione, leggi l'app di riconoscimento vocale di esempio.
Bias per le parole chiave
Il riconoscimento vocale su Glass può essere distorto per un elenco di parole chiave. Il biasing aumenta l'accuratezza del riconoscimento delle parole chiave. Per attivare la ponderazione per le parole chiave, utilizza quanto segue:
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);
Comandi vocali
I comandi vocali consentono agli utenti di eseguire azioni dalle attività. Puoi creare comandi vocali con le API standard del menu Android, ma gli utenti possono richiamare le voci di menu con i comandi vocali anziché con il tocco.
Per attivare i comandi vocali per una determinata attività:
- Chiama
getWindow().requestFeature(FEATURE_VOICE_COMMANDS)nell'attività che preferisci per attivare i comandi vocali. Se questa funzionalità è attivata, l'icona del microfono viene visualizzata nell'angolo in basso a sinistra dello schermo ogni volta che questa attività riceve il focus. - Richiedi l'autorizzazione
RECORD_AUDIOnella tua app. - Override
onCreatePanelMenu()e gonfia una risorsa di menu. - Esegui l'override
onContextItemSelected()per gestire i comandi vocali rilevati.
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); } } }
Di seguito è riportato un esempio della risorsa di menu utilizzata dall'attività precedente:
<?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>
Leggi l'app di esempio per prendere appunti per un esempio completo.
Ricaricamento dell'elenco di comandi vocali
Puoi ricaricare dinamicamente l'elenco dei comandi vocali. Per farlo, sostituisci la risorsa menu nel metodo
onCreatePanelMenu() o modifica l'oggetto menu nel metodo
onPreparePanel(). Per applicare le modifiche, chiama il metodo
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(); }
Soluzione AppCompatActivity
Per ricaricare un elenco di comandi vocali in un'attività che estende AppCompatActivity, utilizza il metodo
sendBroadcast()
con l'azione intent reload-voice-commands:
Kotlin
sendBroadcast(Intent("reload-voice-commands"))
Java
sendBroadcast(new Intent("reload-voice-commands"));
Attivare e disattivare i comandi vocali in fase di runtime
Puoi attivare e disattivare i comandi vocali in fase di runtime. Per farlo, restituisci un valore appropriato dal metodo
onCreatePanelMenu() come segue:
- Imposta il valore su
trueper abilitare. - Imposta il valore su
falseper disattivare.
Modalità di debug
Per attivare la modalità di debug per i comandi vocali, chiama
getWindow().requestFeature(FEATURE_DEBUG_VOICE_COMMANDS)
nell'attività che preferisci. La modalità di debug attiva le seguenti funzionalità:
- Logcat contiene il log con la frase riconosciuta per il debug.
- L'overlay dell'interfaccia utente viene visualizzato quando viene rilevato un comando non riconosciuto, come mostrato di seguito:
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); } . . . }
Per i dettagli di implementazione, leggi l'app di ricarica dei comandi vocali di esempio.
Sintesi vocale (TTS)
La funzionalità Text-to-Speech converte il testo digitale in un output vocale sintetizzato. Per saperne di più, visita la documentazione per sviluppatori Android TextToSpeech.
Glass EE2 ha installato il motore di sintesi vocale di Google. È impostato come motore di sintesi vocale predefinito e funziona offline.
Le seguenti impostazioni internazionali sono incluse nel motore di sintesi vocale Google:
|
Bengalese Cinese mandarino Ceco Danese Tedesco Greco Inglese Spagnolo Estone Finlandese Francese Gujarati Hindi |
Ungherese Indonesiano Italiano Giapponese Giavanese Austronesiano Austroasiatico Kannada Coreano Malayalam Norvegese Olandese |
Polacco Portoghese Russo Slovacco Sundanese Svedese Tamil Telugu Thailandese Turco Ucraino Vietnamita |
Fotocamera
Glass Enterprise Edition 2 è dotato di una fotocamera da 8 megapixel a messa a fuoco fissa con apertura f/2.4, proporzioni del sensore 4:3 e campo visivo diagonale di 83° (71° x 57° in orientamento orizzontale). Ti consigliamo di utilizzare l'API CameraX o Camera2 standard.
Per i dettagli di implementazione, leggi l'app fotocamera di esempio.
Pulsante Fotocamera
Il pulsante della fotocamera è il tasto fisico sulla cerniera del dispositivo Glass Enterprise Edition 2.
Può essere gestito come una normale
azione della tastiera e
può essere identificato dal codice tasto
KeyEvent#KEYCODE_CAMERA.
A partire dall'aggiornamento del sistema operativo OPM1.200313.001, gli intent con le seguenti azioni vengono inviati dall'applicazione Avvio app:
MediaStore#ACTION_IMAGE_CAPTUREcon la pressione breve del pulsante della videocamera.MediaStore#ACTION_VIDEO_CAPTUREquando premi a lungo il pulsante della fotocamera.
Sensori
Gli sviluppatori hanno a disposizione una serie di sensori per sviluppare applicazioni in Glass EE2.
Su Glass sono supportati i seguenti sensori Android standard:
-
TYPE_ACCELEROMETER -
TYPE_GRAVITY -
TYPE_GYROSCOPE -
TYPE_LIGHT -
TYPE_LINEAR_ACCELERATION -
TYPE_MAGNETIC_FIELD -
TYPE_ORIENTATION(obsoleto) -
TYPE_ROTATION_VECTOR
I seguenti sensori Android non sono supportati su Glass:
Il sistema di coordinate del sensore di Glass è mostrato nella figura seguente. È relativo al display di Glass. Per saperne di più, consulta Sistema di coordinate del sensore.
L'accelerometro, il giroscopio e il magnetometro si trovano sul pod ottico del dispositivo Glass, che gli utenti ruotano per allineare il dispositivo alla loro vista. Non puoi misurare direttamente l'angolo del pod ottico, quindi tieni presente questo aspetto quando utilizzi gli angoli di questi sensori per applicazioni, come la direzione della bussola.
Per preservare la durata della batteria, ascolta i sensori solo quando ne hai bisogno. Considera le esigenze e il ciclo di vita dell'app quando decidi quando iniziare e interrompere l'ascolto dei sensori.
I callback degli eventi del sensore vengono eseguiti sul thread UI, quindi elabora gli eventi e i ritorni il più rapidamente possibile. Se l'elaborazione richiede troppo tempo, inserisci gli eventi del sensore in una coda e utilizza un thread in background per gestirli.
50 Hz è spesso una frequenza di campionamento sufficiente per tracciare il movimento della testa.
Per ulteriori informazioni su come utilizzare i sensori, consulta la Guida per gli sviluppatori Android.
Servizi di geolocalizzazione
Il dispositivo Glass Enterprise Edition 2 non è dotato di un modulo GPS e non fornisce la posizione dell'utente. Tuttavia, sono implementati i servizi di localizzazione, necessari per visualizzare un elenco di reti Wi-Fi e dispositivi Bluetooth nelle vicinanze.
Se la tua applicazione dispone dei privilegi di proprietario del dispositivo, puoi utilizzarla per modificare in modo programmatico il valore dell'impostazione protetta corrispondente:
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 utilizzi una soluzione MDM di terze parti, questa deve essere in grado di modificare queste impostazioni per te.