Ingressi e sensori

L'SDK Android consente di accedere ai vari input e sensori disponibili con Glass EE2. In questa pagina viene fornita una panoramica delle funzionalità disponibili, i dettagli dell'implementazione e suggerimenti utili.

Gesti tattili

Puoi utilizzare l'SDK Android per consentire l'accesso ai dati non elaborati dal touchpad di Glass. Ciò viene fatto tramite un rilevatore di gesti che rileva automaticamente i gesti più comuni su Glass, come tocco, scorrimento e scorrimento.

Puoi utilizzare questo rilevatore di gesti anche nelle app per toccare, scorrere in avanti, scorrere indietro e scorrere verso il basso. Questo scenario è simile a quello dei dispositivi Glass precedenti.

È meglio utilizzare questi gesti nei seguenti modi:

  • Tocca: conferma o inserisci.
  • Scorri in avanti, scorri indietro: scorri schede e schermate.
  • Scorri verso il basso: torna indietro o esci.

Per i dettagli dell'implementazione, leggi il rilevatore di gesti di esempio.

Rilevare i gesti con il rilevatore di gesti di Android

Android GestureDetector ti consente di rilevare gesti semplici e complessi, come quelli che utilizzano più dita o scorrimento.

Rilevare i gesti a livello di attività

Rileva i gesti a livello di attività solo quando ciò non è rilevante. Ad esempio, se vuoi mostrare 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 come segue:

  • 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);
       }
     }
   }
  }

Esempi di utilizzo

Per utilizzare il rilevamento dei gesti a livello di attività, devi completare le seguenti attività:

  1. Aggiungi la seguente dichiarazione al file manifest, all'interno della dichiarazione dell'applicazione. Ciò consente alla tua app di ricevere MotionEvent nell'attività:
    <application>
    <!-- Copy below declaration into your manifest file -->
    <meta-data
      android:name="com.google.android.glass.TouchEnabledApplication"
      android:value="true" />
    </application>
    
  2. Sostituisci il metodo dispatchTouchEvent(motionEvent) dell'attività per trasmettere gli eventi di movimento al metodo onTouchEvent(motionEvent) del rilevatore di gesti.
  3. Implementa GlassGestureDetector.OnGestureListener nella 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.

Per le seguenti sorgenti audio è stata implementata l'elaborazione avanzata dei segnali:

Riconoscimento vocale

Glass Enterprise Edition 2 supporta un'implementazione nativa per il riconoscimento vocale. Questa opzione è supportata solo per l'inglese.

Immagine di riconoscimento vocale di Glass.

L'interfaccia utente di riconoscimento vocale attende che l'utente parli e poi restituisca il testo trascritto al termine. Per avviare l'attività, procedi nel seguente modo:

  1. Chiama startActivityForResult() con l'intent ACTION_RECOGNIZE_SPEECH. Quando avvii l'attività, vengono supportati i seguenti extra aggiuntivi:
  2. Sostituisci il callback onActivityResult() per ricevere il testo trascritto dall'intent EXTRA_RESULTS extra, come mostrato nell'esempio di codice riportato di seguito. Questo callback viene richiamato quando l'utente ha finito 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 dell'implementazione, leggi l'app di riconoscimento vocale di esempio.

Differenziazione per parole chiave

Il riconoscimento vocale su Glass può essere mostrato in base a un elenco di parole chiave. La compensazione aumenta l'accuratezza del riconoscimento delle parole chiave. Per attivare la bias 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à. I comandi vocali vengono creati con le API di menu standard di 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à:

  1. Chiama getWindow().requestFeature(FEATURE_VOICE_COMMANDS) nell'attività desiderata per attivare i comandi vocali. Quando questa funzionalità è abilitata, l'icona del microfono viene visualizzata nell'angolo in basso a sinistra dello schermo ogni volta che l'attività è attiva.
  2. Richiedi l'autorizzazione RECORD_AUDIO nell'app.
  3. Esegui l'override di onCreatePanelMenu() e gonfia una risorsa di menu.
  4. Esegui l'override di 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 di 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 per scrivere note di esempio per un esempio completo.

Ricarica dell'elenco di comandi vocali

Puoi ricaricare in modo dinamico l'elenco di 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"));

Attiva e disattiva i comandi vocali in runtime

Puoi attivare e disattivare i comandi vocali in runtime. Per farlo, restituisci un valore appropriato dal metodo onCreatePanelMenu() nel seguente modo:

  • Imposta il valore su true per attivarlo.
  • Imposta il valore su false per disattivarlo.

Modalità di debug

Per attivare la modalità di debug per i comandi vocali, chiama getWindow().requestFeature(FEATURE_DEBUG_VOICE_COMMANDS) nell'attività desiderata. 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:
  • Immagine del comando di riconoscimento vocale in vetro non riconosciuto.

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 sull'implementazione, leggi i comandi vocali per il ricaricamento dell'app.

Sintesi vocale (TTS)

La funzionalità di sintesi vocale converte il testo digitale in output vocale sintetizzato. Per ulteriori informazioni, visita Documentazione per gli sviluppatori Android TextToSpeech.

In Glass EE2 è installato il motore Google Text-to-Speech. È impostato come motore TTS predefinito e funziona offline.

Le seguenti impostazioni internazionali vengono incluse nel motore di sintesi vocale di 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
Sondanese
Svedese
Tamil
Telugu
Thai
Turco
Ucraino
Vietnamita

Fotocamera

Glass Enterprise Edition 2 è dotato di una fotocamera con messa a fuoco fissa da 8 megapixel con apertura f/2.4, proporzioni del sensore 4:3 e campo visivo diagonale di 83° (71° x 57° con orientamento orizzontale). Ti consigliamo di utilizzare l'API standard FotocameraX o Fotocamera2.

Per i dettagli sull'implementazione, leggi l'app della fotocamera di esempio.

Pulsante Fotocamera

Il pulsante della fotocamera è il pulsante fisico sulla cerniera del dispositivo Glass Enterprise Edition 2. Può essere gestito come un'azione da tastiera standard e può essere identificato dal codice chiave KeyEvent#KEYCODE_CAMERA.

A partire dall'aggiornamento del sistema operativo OPM1.200313.001, vengono inviati l'intent con le seguenti azioni dall'applicazione Avvio app:

Sensori

Gli sviluppatori che sviluppano applicazioni in Glass EE2 hanno a disposizione una varietà di sensori.

I seguenti sensori Android standard sono supportati su Glass:

I seguenti sensori Android non sono supportati su Glass:

Il sistema di coordinate del sensore di vetro è mostrato nella figura seguente. È relativo al display Glass. Per maggiori informazioni, consulta Sistema di coordinate del sensore.

Il sistema di coordinate del sensore di vetro è mostrato qui, relativo al display Glass.

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'angolazione del pod ottico, quindi presta attenzione quando utilizzi gli angoli di questi sensori per le applicazioni, ad esempio un'intestazione della bussola.

Per preservare la durata della batteria, ascolta i sensori solo quando ti servono. Prendi in considerazione le esigenze e il ciclo di vita dell'app quando decidi quando avviare e interrompere l'ascolto dei sensori.

I callback degli eventi dei sensori vengono eseguiti nel thread dell'interfaccia utente, quindi elabora gli eventi e restituisce il più rapidamente possibile. Se l'elaborazione richiede troppo tempo, invia gli eventi del sensore a una coda e utilizza un thread in background per gestirli.

50 Hz è spesso una frequenza di campionamento sufficiente per monitorare il movimento della testa.

Per maggiori 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 geolocalizzazione, 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 sicura 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 di MDM di terze parti, quest'ultima deve essere in grado di modificare queste impostazioni per tuo conto.